From 707ee735b2ab56bd59cbfcd513285d77f8e95962 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Thu, 23 May 2024 18:42:16 +0200 Subject: [PATCH 01/39] Pass active font faces to appearance control component --- .../src/components/global-styles/typography-panel.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/block-editor/src/components/global-styles/typography-panel.js b/packages/block-editor/src/components/global-styles/typography-panel.js index 64a7be0443e1e9..ca4dc40a94b9a7 100644 --- a/packages/block-editor/src/components/global-styles/typography-panel.js +++ b/packages/block-editor/src/components/global-styles/typography-panel.js @@ -178,6 +178,9 @@ export default function TypographyPanel( { ); }, [ fontFamilies ] ); const fontFamily = decodeValue( inheritedValue?.typography?.fontFamily ); + const fontFamilyFaces = mergedFontFamilies.find( + ( family ) => family.name === fontFamily + )?.fontFace; const setFontFamily = ( newValue ) => { const slug = mergedFontFamilies?.find( ( { fontFamily: f } ) => f === newValue @@ -406,6 +409,7 @@ export default function TypographyPanel( { onChange={ setFontAppearance } hasFontStyles={ hasFontStyles } hasFontWeights={ hasFontWeights } + fontFamilyFaces={ fontFamilyFaces } size="__unstable-large" __nextHasNoMarginBottom /> From c7334320f8a08571b37bb3ff28e8c9b41b553486 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Thu, 23 May 2024 19:34:01 +0200 Subject: [PATCH 02/39] Add formatFontWeight function --- .../src/utils/format-font-weight.js | 53 ++++++++++++++++++ .../src/utils/test/format-font-weight.js | 54 +++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 packages/block-editor/src/utils/format-font-weight.js create mode 100644 packages/block-editor/src/utils/test/format-font-weight.js diff --git a/packages/block-editor/src/utils/format-font-weight.js b/packages/block-editor/src/utils/format-font-weight.js new file mode 100644 index 00000000000000..9ddd7d07e41d8f --- /dev/null +++ b/packages/block-editor/src/utils/format-font-weight.js @@ -0,0 +1,53 @@ +/** + * Formats font weights to human readable names. + * + * @param {string} fontWeight font weight string + * @return {Object} new object with formatted font weight + */ +export function formatFontWeight( fontWeight ) { + if ( ! fontWeight ) { + return {}; + } + + if ( typeof fontWeight === 'object' ) { + return fontWeight; + } + + let name; + + switch ( fontWeight ) { + case '100': + name = 'Thin'; + break; + case '200': + name = 'Extra Light'; + break; + case '300': + name = 'Light'; + break; + case '400': + name = 'Regular'; + break; + case '500': + name = 'Medium'; + break; + case '600': + name = 'Semi Bold'; + break; + case '700': + name = 'Bold'; + break; + case '800': + name = 'Extra Bold'; + break; + case '900': + name = 'Black'; + break; + + default: + name = fontWeight; + break; + } + + return { name, value: fontWeight }; +} diff --git a/packages/block-editor/src/utils/test/format-font-weight.js b/packages/block-editor/src/utils/test/format-font-weight.js new file mode 100644 index 00000000000000..37ece66c905147 --- /dev/null +++ b/packages/block-editor/src/utils/test/format-font-weight.js @@ -0,0 +1,54 @@ +/** + * Internal dependencies + */ +import { formatFontWeight } from '../format-font-weight'; + +describe( 'formatFontWeight', () => { + it( 'should return empty object if weight is not available', () => { + expect( formatFontWeight() ).toEqual( {} ); + } ); + + it( 'should return the same object if weight is already an object', () => { + const fontWeight = { name: 'Thin', value: '100' }; + expect( formatFontWeight( fontWeight ) ).toEqual( fontWeight ); + } ); + + it( 'should return the formatted font weight', () => { + expect( formatFontWeight( '100' ) ).toEqual( { + name: 'Thin', + value: '100', + } ); + expect( formatFontWeight( '200' ) ).toEqual( { + name: 'Extra Light', + value: '200', + } ); + expect( formatFontWeight( '300' ) ).toEqual( { + name: 'Light', + value: '300', + } ); + expect( formatFontWeight( '400' ) ).toEqual( { + name: 'Regular', + value: '400', + } ); + expect( formatFontWeight( '500' ) ).toEqual( { + name: 'Medium', + value: '500', + } ); + expect( formatFontWeight( '600' ) ).toEqual( { + name: 'Semi Bold', + value: '600', + } ); + expect( formatFontWeight( '700' ) ).toEqual( { + name: 'Bold', + value: '700', + } ); + expect( formatFontWeight( '800' ) ).toEqual( { + name: 'Extra Bold', + value: '800', + } ); + expect( formatFontWeight( '900' ) ).toEqual( { + name: 'Black', + value: '900', + } ); + } ); +} ); From 42811bda47f95142e5c8b4a3ffd1c7ea4b20a88c Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Thu, 23 May 2024 19:35:25 +0200 Subject: [PATCH 03/39] Use only available font weights in FontAppearanceControl --- .../font-appearance-control/index.js | 50 +++++++++++++++++-- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/font-appearance-control/index.js b/packages/block-editor/src/components/font-appearance-control/index.js index 18e814ad23ddb4..58002840e4a678 100644 --- a/packages/block-editor/src/components/font-appearance-control/index.js +++ b/packages/block-editor/src/components/font-appearance-control/index.js @@ -5,6 +5,11 @@ import { CustomSelectControl } from '@wordpress/components'; import { useMemo } from '@wordpress/element'; import { __, _x, sprintf } from '@wordpress/i18n'; +/** + * Internal dependencies + */ +import { formatFontWeight } from '../../utils/format-font-weight'; + const FONT_STYLES = [ { name: _x( 'Regular', 'font style' ), @@ -87,6 +92,7 @@ export default function FontAppearanceControl( props ) { onChange, hasFontStyles = true, hasFontWeights = true, + fontFamilyFaces, value: { fontStyle, fontWeight }, ...otherProps } = props; @@ -97,13 +103,47 @@ export default function FontAppearanceControl( props ) { name: __( 'Default' ), style: { fontStyle: undefined, fontWeight: undefined }, }; + let fontWeights = []; + let fontStyles = []; + + fontFamilyFaces.forEach( ( face ) => { + if ( face.fontWeight ) { + if ( + fontWeights.findIndex( + ( weight ) => weight.value === face.fontWeight + ) === -1 + ) { + fontWeights.push( formatFontWeight( face.fontWeight ) ); + } + } + if ( face.fontStyle ) { + if ( + fontStyles.findIndex( + ( style ) => style.value === face.fontStyle + ) === -1 + ) { + fontStyles.push( { + name: face.fontStyle, + value: face.fontStyle, + } ); + } + } + } ); + + if ( fontWeights.length === 0 ) { + fontWeights = FONT_WEIGHTS; + } + + if ( fontStyles.length === 0 ) { + fontStyles = FONT_STYLES; + } // Combines both font style and weight options into a single dropdown. const combineOptions = () => { const combinedOptions = [ defaultOption ]; - FONT_STYLES.forEach( ( { name: styleName, value: styleValue } ) => { - FONT_WEIGHTS.forEach( + fontStyles.forEach( ( { name: styleName, value: styleValue } ) => { + fontWeights.forEach( ( { name: weightName, value: weightValue } ) => { const optionName = styleValue === 'normal' @@ -133,7 +173,7 @@ export default function FontAppearanceControl( props ) { // Generates select options for font styles only. const styleOptions = () => { const combinedOptions = [ defaultOption ]; - FONT_STYLES.forEach( ( { name, value } ) => { + fontStyles.forEach( ( { name, value } ) => { combinedOptions.push( { key: value, name, @@ -146,7 +186,7 @@ export default function FontAppearanceControl( props ) { // Generates select options for font weights only. const weightOptions = () => { const combinedOptions = [ defaultOption ]; - FONT_WEIGHTS.forEach( ( { name, value } ) => { + fontWeights.forEach( ( { name, value } ) => { combinedOptions.push( { key: value, name, @@ -163,7 +203,7 @@ export default function FontAppearanceControl( props ) { } return hasFontStyles ? styleOptions() : weightOptions(); - }, [ props.options ] ); + }, [ props.options, fontStyles, fontWeights ] ); // Find current selection by comparing font style & weight against options, // and fall back to the Default option if there is no matching option. From a4ad7f9ce4a4b216aecd6934dcb16c98636076b8 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Fri, 24 May 2024 00:53:50 +0200 Subject: [PATCH 04/39] Refactor weight and style array fallbacks --- .../src/components/font-appearance-control/index.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/src/components/font-appearance-control/index.js b/packages/block-editor/src/components/font-appearance-control/index.js index 58002840e4a678..20af4c2c33d181 100644 --- a/packages/block-editor/src/components/font-appearance-control/index.js +++ b/packages/block-editor/src/components/font-appearance-control/index.js @@ -130,13 +130,8 @@ export default function FontAppearanceControl( props ) { } } ); - if ( fontWeights.length === 0 ) { - fontWeights = FONT_WEIGHTS; - } - - if ( fontStyles.length === 0 ) { - fontStyles = FONT_STYLES; - } + fontWeights = fontWeights.length === 0 ? FONT_WEIGHTS : fontWeights; + fontStyles = fontStyles.length === 0 ? FONT_STYLES : fontStyles; // Combines both font style and weight options into a single dropdown. const combineOptions = () => { From ead32c3736c95054c771cc66a6a30af34f27bc93 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Fri, 24 May 2024 00:54:29 +0200 Subject: [PATCH 05/39] Rename normal to regular in styles list --- .../src/components/font-appearance-control/index.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/font-appearance-control/index.js b/packages/block-editor/src/components/font-appearance-control/index.js index 20af4c2c33d181..01b1857fb9d8ee 100644 --- a/packages/block-editor/src/components/font-appearance-control/index.js +++ b/packages/block-editor/src/components/font-appearance-control/index.js @@ -81,7 +81,7 @@ const getFontAppearanceLabel = ( hasFontStyles, hasFontWeights ) => { }; /** - * Control to display unified font style and weight options. + * Control to display font style and weight options of the active font. * * @param {Object} props Component props. * @@ -103,6 +103,7 @@ export default function FontAppearanceControl( props ) { name: __( 'Default' ), style: { fontStyle: undefined, fontWeight: undefined }, }; + let fontWeights = []; let fontStyles = []; @@ -122,8 +123,13 @@ export default function FontAppearanceControl( props ) { ( style ) => style.value === face.fontStyle ) === -1 ) { + let styleName = face.fontStyle; + if ( face.fontStyle === 'normal' ) { + styleName = _x( 'Regular', 'font style' ); + } + fontStyles.push( { - name: face.fontStyle, + name: styleName, value: face.fontStyle, } ); } From 861cd72bc6095c3c10e57da1ea2100c2cbfcdb4f Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Fri, 24 May 2024 00:58:21 +0200 Subject: [PATCH 06/39] Make font weight labels translatable --- .../src/utils/format-font-weight.js | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/packages/block-editor/src/utils/format-font-weight.js b/packages/block-editor/src/utils/format-font-weight.js index 9ddd7d07e41d8f..21f56ac62940d6 100644 --- a/packages/block-editor/src/utils/format-font-weight.js +++ b/packages/block-editor/src/utils/format-font-weight.js @@ -1,3 +1,8 @@ +/** + * WordPress dependencies + */ +import { _x } from '@wordpress/i18n'; + /** * Formats font weights to human readable names. * @@ -17,31 +22,31 @@ export function formatFontWeight( fontWeight ) { switch ( fontWeight ) { case '100': - name = 'Thin'; + name = _x( 'Thin', 'font weight' ); break; case '200': - name = 'Extra Light'; + name = _x( 'Extra Light', 'font weight' ); break; case '300': - name = 'Light'; + name = _x( 'Light', 'font weight' ); break; case '400': - name = 'Regular'; + name = _x( 'Regular', 'font weight' ); break; case '500': - name = 'Medium'; + name = _x( 'Medium', 'font weight' ); break; case '600': - name = 'Semi Bold'; + name = _x( 'Semi Bold', 'font weight' ); break; case '700': - name = 'Bold'; + name = _x( 'Bold', 'font weight' ); break; case '800': - name = 'Extra Bold'; + name = _x( 'Extra Bold', 'font weight' ); break; case '900': - name = 'Black'; + name = _x( 'Black', 'font weight' ); break; default: From af44839cc9ab2d7309cf4a56e5812c4014ef9830 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Sat, 25 May 2024 15:13:53 +0200 Subject: [PATCH 07/39] Handle system fonts --- .../src/components/font-appearance-control/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/font-appearance-control/index.js b/packages/block-editor/src/components/font-appearance-control/index.js index 01b1857fb9d8ee..27f07dbf1f70f0 100644 --- a/packages/block-editor/src/components/font-appearance-control/index.js +++ b/packages/block-editor/src/components/font-appearance-control/index.js @@ -107,7 +107,7 @@ export default function FontAppearanceControl( props ) { let fontWeights = []; let fontStyles = []; - fontFamilyFaces.forEach( ( face ) => { + fontFamilyFaces?.forEach( ( face ) => { if ( face.fontWeight ) { if ( fontWeights.findIndex( From af005a525cf8364e0caec586c3d5962ce7c09d5b Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Sat, 25 May 2024 15:50:52 +0200 Subject: [PATCH 08/39] Add comment for font weight and style options --- .../block-editor/src/components/font-appearance-control/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-editor/src/components/font-appearance-control/index.js b/packages/block-editor/src/components/font-appearance-control/index.js index 27f07dbf1f70f0..12b136ba09c040 100644 --- a/packages/block-editor/src/components/font-appearance-control/index.js +++ b/packages/block-editor/src/components/font-appearance-control/index.js @@ -104,6 +104,7 @@ export default function FontAppearanceControl( props ) { style: { fontStyle: undefined, fontWeight: undefined }, }; + // Build font style and weight options based on the font family faces. let fontWeights = []; let fontStyles = []; From 52802aae81dd6a03aaa7aaddbd01daec5a11e73c Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Sat, 25 May 2024 17:13:44 +0200 Subject: [PATCH 09/39] Check against fontFamily rather than name --- .../src/components/global-styles/typography-panel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/global-styles/typography-panel.js b/packages/block-editor/src/components/global-styles/typography-panel.js index ca4dc40a94b9a7..8a719ed460ff67 100644 --- a/packages/block-editor/src/components/global-styles/typography-panel.js +++ b/packages/block-editor/src/components/global-styles/typography-panel.js @@ -179,7 +179,7 @@ export default function TypographyPanel( { }, [ fontFamilies ] ); const fontFamily = decodeValue( inheritedValue?.typography?.fontFamily ); const fontFamilyFaces = mergedFontFamilies.find( - ( family ) => family.name === fontFamily + ( family ) => family.fontFamily === fontFamily )?.fontFace; const setFontFamily = ( newValue ) => { const slug = mergedFontFamilies?.find( From 281126284aa5a90366e20ed386c1f9918351a81f Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Sat, 25 May 2024 17:59:50 +0200 Subject: [PATCH 10/39] Handle font style names and values similar to font weights --- .../font-appearance-control/index.js | 11 +---- .../src/utils/format-font-style.js | 43 +++++++++++++++++++ .../src/utils/format-font-weight.js | 6 +++ .../src/utils/test/format-font-style.js | 34 +++++++++++++++ 4 files changed, 85 insertions(+), 9 deletions(-) create mode 100644 packages/block-editor/src/utils/format-font-style.js create mode 100644 packages/block-editor/src/utils/test/format-font-style.js diff --git a/packages/block-editor/src/components/font-appearance-control/index.js b/packages/block-editor/src/components/font-appearance-control/index.js index 12b136ba09c040..806e2d0a79c625 100644 --- a/packages/block-editor/src/components/font-appearance-control/index.js +++ b/packages/block-editor/src/components/font-appearance-control/index.js @@ -9,6 +9,7 @@ import { __, _x, sprintf } from '@wordpress/i18n'; * Internal dependencies */ import { formatFontWeight } from '../../utils/format-font-weight'; +import { formatFontStyle } from '../../utils/format-font-style'; const FONT_STYLES = [ { @@ -124,15 +125,7 @@ export default function FontAppearanceControl( props ) { ( style ) => style.value === face.fontStyle ) === -1 ) { - let styleName = face.fontStyle; - if ( face.fontStyle === 'normal' ) { - styleName = _x( 'Regular', 'font style' ); - } - - fontStyles.push( { - name: styleName, - value: face.fontStyle, - } ); + fontStyles.push( formatFontStyle( face.fontStyle ) ); } } } ); diff --git a/packages/block-editor/src/utils/format-font-style.js b/packages/block-editor/src/utils/format-font-style.js new file mode 100644 index 00000000000000..cf426aaf7bc63f --- /dev/null +++ b/packages/block-editor/src/utils/format-font-style.js @@ -0,0 +1,43 @@ +/** + * WordPress dependencies + */ +import { _x } from '@wordpress/i18n'; + +/** + * Formats font styles to human readable names. + * + * @param {string} fontStyle font style string + * @return {Object} new object with formatted font style + */ +export function formatFontStyle( fontStyle ) { + if ( ! fontStyle ) { + return {}; + } + + if ( typeof fontStyle === 'object' ) { + return fontStyle; + } + + let name; + + switch ( fontStyle ) { + case 'normal': + name = _x( 'Regular', 'font style' ); + break; + case 'italic': + name = _x( 'Italic', 'font style' ); + break; + case 'oblique': + name = _x( 'Oblique', 'font style' ); + break; + + default: + name = fontStyle; + break; + } + + // Ensure first letter of font style name is capitalized. + name = name.charAt( 0 ).toUpperCase() + name.slice( 1 ); + + return { name, value: fontStyle }; +} diff --git a/packages/block-editor/src/utils/format-font-weight.js b/packages/block-editor/src/utils/format-font-weight.js index 21f56ac62940d6..78e550099b4c15 100644 --- a/packages/block-editor/src/utils/format-font-weight.js +++ b/packages/block-editor/src/utils/format-font-weight.js @@ -21,6 +21,12 @@ export function formatFontWeight( fontWeight ) { let name; switch ( fontWeight ) { + case 'normal': + name = _x( 'Regular', 'font weight' ); + break; + case 'bold': + name = _x( 'Bold', 'font weight' ); + break; case '100': name = _x( 'Thin', 'font weight' ); break; diff --git a/packages/block-editor/src/utils/test/format-font-style.js b/packages/block-editor/src/utils/test/format-font-style.js new file mode 100644 index 00000000000000..18282e83dba29f --- /dev/null +++ b/packages/block-editor/src/utils/test/format-font-style.js @@ -0,0 +1,34 @@ +/** + * Internal dependencies + */ +import { formatFontStyle } from '../format-font-style'; + +describe( 'formatFontStyle', () => { + it( 'should return empty object if style is not available', () => { + expect( formatFontStyle() ).toEqual( {} ); + } ); + + it( 'should return the same object if style is already an object', () => { + const fontStyle = { name: 'Italic', value: 'italic' }; + expect( formatFontStyle( fontStyle ) ).toEqual( fontStyle ); + } ); + + it( 'should return the formatted font style', () => { + expect( formatFontStyle( 'normal' ) ).toEqual( { + name: 'Regular', + value: 'normal', + } ); + expect( formatFontStyle( 'italic' ) ).toEqual( { + name: 'Italic', + value: 'italic', + } ); + expect( formatFontStyle( 'oblique' ) ).toEqual( { + name: 'Oblique', + value: 'oblique', + } ); + expect( formatFontStyle( 'oblique 40deg' ) ).toEqual( { + name: 'Oblique 40deg', + value: 'oblique 40deg', + } ); + } ); +} ); From a1bc596c1aad4622c0394cec9d75c763a582ace5 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Sat, 25 May 2024 18:15:33 +0200 Subject: [PATCH 11/39] Use some() rather than findIndex() --- .../src/components/font-appearance-control/index.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/font-appearance-control/index.js b/packages/block-editor/src/components/font-appearance-control/index.js index 806e2d0a79c625..0e5e1541c974d7 100644 --- a/packages/block-editor/src/components/font-appearance-control/index.js +++ b/packages/block-editor/src/components/font-appearance-control/index.js @@ -112,18 +112,16 @@ export default function FontAppearanceControl( props ) { fontFamilyFaces?.forEach( ( face ) => { if ( face.fontWeight ) { if ( - fontWeights.findIndex( + ! fontWeights.some( ( weight ) => weight.value === face.fontWeight - ) === -1 + ) ) { fontWeights.push( formatFontWeight( face.fontWeight ) ); } } if ( face.fontStyle ) { if ( - fontStyles.findIndex( - ( style ) => style.value === face.fontStyle - ) === -1 + ! fontStyles.some( ( style ) => style.value === face.fontStyle ) ) { fontStyles.push( formatFontStyle( face.fontStyle ) ); } From 2d42dc48b448c84627529c67fcbe932ea40e17cb Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Thu, 30 May 2024 12:03:38 +0100 Subject: [PATCH 12/39] Add getMergedFontFamiliesAndFontFamilyFaces function --- .../global-styles/typography-panel.js | 18 +++++-------- .../global-styles/typography-utils.js | 26 +++++++++++++++++++ 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/typography-panel.js b/packages/block-editor/src/components/global-styles/typography-panel.js index 8a719ed460ff67..132a04cdbee9b3 100644 --- a/packages/block-editor/src/components/global-styles/typography-panel.js +++ b/packages/block-editor/src/components/global-styles/typography-panel.js @@ -22,6 +22,7 @@ import TextDecorationControl from '../text-decoration-control'; import WritingModeControl from '../writing-mode-control'; import { getValueFromVariable, TOOLSPANEL_DROPDOWNMENU_PROPS } from './utils'; import { setImmutably } from '../../utils/object'; +import { getMergedFontFamiliesAndFontFamilyFaces } from './typography-utils'; const MIN_TEXT_COLUMNS = 1; const MAX_TEXT_COLUMNS = 6; @@ -171,18 +172,13 @@ export default function TypographyPanel( { // Font Family const hasFontFamilyEnabled = useHasFontFamilyControl( settings ); - const fontFamilies = settings?.typography?.fontFamilies; - const mergedFontFamilies = useMemo( () => { - return [ 'default', 'theme', 'custom' ].flatMap( - ( key ) => fontFamilies?.[ key ] ?? [] - ); - }, [ fontFamilies ] ); const fontFamily = decodeValue( inheritedValue?.typography?.fontFamily ); - const fontFamilyFaces = mergedFontFamilies.find( - ( family ) => family.fontFamily === fontFamily - )?.fontFace; + const { fontFamilies, fontFamilyFaces } = useMemo( () => { + return getMergedFontFamiliesAndFontFamilyFaces( settings, fontFamily ); + }, [ settings, fontFamily ] ); + const setFontFamily = ( newValue ) => { - const slug = mergedFontFamilies?.find( + const slug = fontFamilies?.find( ( { fontFamily: f } ) => f === newValue )?.slug; onChange( @@ -365,7 +361,7 @@ export default function TypographyPanel( { panelId={ panelId } > fontFamiliesFromSettings?.[ key ] ?? [] + ); + + const fontFamilyFaces = + fontFamilies.find( + ( family ) => family.fontFamily === selectedFontFamily + )?.fontFace ?? []; + + return { fontFamilies, fontFamilyFaces }; +} From b4fa5eb3b35aa91123558efd5b848f16a01f24f5 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Thu, 30 May 2024 12:03:55 +0100 Subject: [PATCH 13/39] Add tests for getMergedFontFamiliesAndFontFamilyFaces --- .../global-styles/test/typography-utils.js | 213 ++++++++++++++++++ 1 file changed, 213 insertions(+) diff --git a/packages/block-editor/src/components/global-styles/test/typography-utils.js b/packages/block-editor/src/components/global-styles/test/typography-utils.js index bea8a5c0032757..7860e27d1454f4 100644 --- a/packages/block-editor/src/components/global-styles/test/typography-utils.js +++ b/packages/block-editor/src/components/global-styles/test/typography-utils.js @@ -4,6 +4,7 @@ import { getTypographyFontSizeValue, getFluidTypographyOptionsFromSettings, + getMergedFontFamiliesAndFontFamilyFaces, } from '../typography-utils'; describe( 'typography utils', () => { @@ -682,6 +683,218 @@ describe( 'typography utils', () => { } ); } ); + describe( 'getMergedFontFamiliesAndFontFamilyFaces', () => { + [ + { + message: + 'should return empty arrays when settings and fontFamily are empty', + settings: {}, + fontFamily: '', + expected: { + fontFamilies: [], + fontFamilyFaces: [], + }, + }, + + { + message: + 'should return empty arrays when only settings is `undefined`', + settings: undefined, + fontFamily: 'ABeeZee, sans-serif', + expected: { + fontFamilies: [], + fontFamilyFaces: [], + }, + }, + + { + message: + 'should return fontFamilies array and an empty fontFamilyFaces array when fontfamily is empty', + settings: { + typography: { + fontFamilies: { + custom: [ + { + name: 'ABeeZee', + slug: 'abeezee', + fontFamily: 'ABeeZee, sans-serif', + fontFace: [ + { + src: 'http://www.wordpress.org/wp-content/uploads/fonts/esDT31xSG-6AGleN2tCkkJUCGpG-GQ.woff2', + fontWeight: '400', + fontStyle: 'italic', + fontFamily: 'ABeeZee', + }, + ], + }, + ], + }, + }, + }, + fontFamily: '', + expected: { + fontFamilies: [ + { + fontFace: [ + { + fontFamily: 'ABeeZee', + fontStyle: 'italic', + fontWeight: '400', + src: 'http://www.wordpress.org/wp-content/uploads/fonts/esDT31xSG-6AGleN2tCkkJUCGpG-GQ.woff2', + }, + ], + fontFamily: 'ABeeZee, sans-serif', + name: 'ABeeZee', + slug: 'abeezee', + }, + ], + fontFamilyFaces: [], + }, + }, + + { + message: + 'should return font families and font faces when both settings and fontFamily are defined', + settings: { + typography: { + fontFamilies: { + theme: [ + { + fontFace: [ + { + fontFamily: 'PT Sans', + fontStyle: 'normal', + fontWeight: '400', + src: [ + 'file:./assets/fonts/pt-sans_normal_400.ttf', + ], + }, + { + fontFamily: 'PT Sans', + fontStyle: 'normal', + fontWeight: '700', + src: [ + 'file:./assets/fonts/pt-sans_normal_700.ttf', + ], + }, + { + fontFamily: 'PT Sans', + fontStyle: 'italic', + fontWeight: '400', + src: [ + 'file:./assets/fonts/pt-sans_italic_400.ttf', + ], + }, + { + fontFamily: 'PT Sans', + fontStyle: 'italic', + fontWeight: '700', + src: [ + 'file:./assets/fonts/pt-sans_italic_700.ttf', + ], + }, + ], + fontFamily: 'PT Sans', + name: 'PT Sans', + slug: 'pt-sans', + }, + ], + custom: [ + { + name: 'ABeeZee', + slug: 'abeezee', + fontFamily: 'ABeeZee, sans-serif', + fontFace: [ + { + src: 'http://www.wordpress.org/wp-content/uploads/fonts/esDT31xSG-6AGleN2tCkkJUCGpG-GQ.woff2', + fontWeight: '400', + fontStyle: 'italic', + fontFamily: 'ABeeZee', + }, + ], + }, + ], + }, + }, + }, + fontFamily: 'ABeeZee, sans-serif', + expected: { + fontFamilyFaces: [ + { + fontFamily: 'ABeeZee', + fontStyle: 'italic', + fontWeight: '400', + src: 'http://www.wordpress.org/wp-content/uploads/fonts/esDT31xSG-6AGleN2tCkkJUCGpG-GQ.woff2', + }, + ], + fontFamilies: [ + { + fontFace: [ + { + fontFamily: 'PT Sans', + fontStyle: 'normal', + fontWeight: '400', + src: [ + 'file:./assets/fonts/pt-sans_normal_400.ttf', + ], + }, + { + fontFamily: 'PT Sans', + fontStyle: 'normal', + fontWeight: '700', + src: [ + 'file:./assets/fonts/pt-sans_normal_700.ttf', + ], + }, + { + fontFamily: 'PT Sans', + fontStyle: 'italic', + fontWeight: '400', + src: [ + 'file:./assets/fonts/pt-sans_italic_400.ttf', + ], + }, + { + fontFamily: 'PT Sans', + fontStyle: 'italic', + fontWeight: '700', + src: [ + 'file:./assets/fonts/pt-sans_italic_700.ttf', + ], + }, + ], + fontFamily: 'PT Sans', + name: 'PT Sans', + slug: 'pt-sans', + }, + { + fontFace: [ + { + fontFamily: 'ABeeZee', + fontStyle: 'italic', + fontWeight: '400', + src: 'http://www.wordpress.org/wp-content/uploads/fonts/esDT31xSG-6AGleN2tCkkJUCGpG-GQ.woff2', + }, + ], + fontFamily: 'ABeeZee, sans-serif', + name: 'ABeeZee', + slug: 'abeezee', + }, + ], + }, + }, + ].forEach( ( { message, settings, fontFamily, expected } ) => { + it( `${ message }`, () => { + expect( + getMergedFontFamiliesAndFontFamilyFaces( + settings, + fontFamily + ) + ).toEqual( expected ); + } ); + } ); + } ); + describe( 'typography utils', () => { [ { From 672ae3afdf3be1be1369220ce8c65b4e95668104 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Thu, 30 May 2024 17:20:37 +0100 Subject: [PATCH 14/39] Merge common case statements --- packages/block-editor/src/utils/format-font-weight.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/src/utils/format-font-weight.js b/packages/block-editor/src/utils/format-font-weight.js index 78e550099b4c15..c0c8a865e4c26a 100644 --- a/packages/block-editor/src/utils/format-font-weight.js +++ b/packages/block-editor/src/utils/format-font-weight.js @@ -22,9 +22,11 @@ export function formatFontWeight( fontWeight ) { switch ( fontWeight ) { case 'normal': + case '400': name = _x( 'Regular', 'font weight' ); break; case 'bold': + case '700': name = _x( 'Bold', 'font weight' ); break; case '100': @@ -36,18 +38,12 @@ export function formatFontWeight( fontWeight ) { case '300': name = _x( 'Light', 'font weight' ); break; - case '400': - name = _x( 'Regular', 'font weight' ); - break; case '500': name = _x( 'Medium', 'font weight' ); break; case '600': name = _x( 'Semi Bold', 'font weight' ); break; - case '700': - name = _x( 'Bold', 'font weight' ); - break; case '800': name = _x( 'Extra Bold', 'font weight' ); break; From dc60306de757f164f959a307779629c473b4b281 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Thu, 30 May 2024 17:27:54 +0100 Subject: [PATCH 15/39] Remove toUpperCase() on font style names --- packages/block-editor/src/utils/format-font-style.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/block-editor/src/utils/format-font-style.js b/packages/block-editor/src/utils/format-font-style.js index cf426aaf7bc63f..5db52f8a5808f5 100644 --- a/packages/block-editor/src/utils/format-font-style.js +++ b/packages/block-editor/src/utils/format-font-style.js @@ -36,8 +36,5 @@ export function formatFontStyle( fontStyle ) { break; } - // Ensure first letter of font style name is capitalized. - name = name.charAt( 0 ).toUpperCase() + name.slice( 1 ); - return { name, value: fontStyle }; } From 3ba9ce861847fd7d8d6acebb3460dc518063659a Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Thu, 30 May 2024 17:40:49 +0100 Subject: [PATCH 16/39] Attempt to fix variable fonts options --- .../src/components/font-appearance-control/index.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/font-appearance-control/index.js b/packages/block-editor/src/components/font-appearance-control/index.js index 0e5e1541c974d7..72487e77562733 100644 --- a/packages/block-editor/src/components/font-appearance-control/index.js +++ b/packages/block-editor/src/components/font-appearance-control/index.js @@ -108,6 +108,7 @@ export default function FontAppearanceControl( props ) { // Build font style and weight options based on the font family faces. let fontWeights = []; let fontStyles = []; + let variableFont = false; fontFamilyFaces?.forEach( ( face ) => { if ( face.fontWeight ) { @@ -116,6 +117,11 @@ export default function FontAppearanceControl( props ) { ( weight ) => weight.value === face.fontWeight ) ) { + // Check if font weight includes a space, if so it must be a variable font. + if ( /\s/.test( face.fontWeight ) ) { + variableFont = true; + } + fontWeights.push( formatFontWeight( face.fontWeight ) ); } } @@ -128,8 +134,10 @@ export default function FontAppearanceControl( props ) { } } ); - fontWeights = fontWeights.length === 0 ? FONT_WEIGHTS : fontWeights; - fontStyles = fontStyles.length === 0 ? FONT_STYLES : fontStyles; + fontWeights = + fontWeights.length === 0 || variableFont ? FONT_WEIGHTS : fontWeights; + fontStyles = + fontStyles.length === 0 || variableFont ? FONT_STYLES : fontStyles; // Combines both font style and weight options into a single dropdown. const combineOptions = () => { From 15739d84860184a7b681c32b5e2dbae8e5577121 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Thu, 30 May 2024 17:47:39 +0100 Subject: [PATCH 17/39] Fix formatFontStyle test --- packages/block-editor/src/utils/test/format-font-style.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/utils/test/format-font-style.js b/packages/block-editor/src/utils/test/format-font-style.js index 18282e83dba29f..f8557143cb4e24 100644 --- a/packages/block-editor/src/utils/test/format-font-style.js +++ b/packages/block-editor/src/utils/test/format-font-style.js @@ -27,7 +27,7 @@ describe( 'formatFontStyle', () => { value: 'oblique', } ); expect( formatFontStyle( 'oblique 40deg' ) ).toEqual( { - name: 'Oblique 40deg', + name: 'oblique 40deg', value: 'oblique 40deg', } ); } ); From 7677b53099f7572434dffd91080c980f89b5b044 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Fri, 31 May 2024 10:24:56 +0100 Subject: [PATCH 18/39] Trim any surrounding whitespace from fontweight string --- .../src/components/font-appearance-control/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/font-appearance-control/index.js b/packages/block-editor/src/components/font-appearance-control/index.js index 72487e77562733..d271b46353bba1 100644 --- a/packages/block-editor/src/components/font-appearance-control/index.js +++ b/packages/block-editor/src/components/font-appearance-control/index.js @@ -118,7 +118,7 @@ export default function FontAppearanceControl( props ) { ) ) { // Check if font weight includes a space, if so it must be a variable font. - if ( /\s/.test( face.fontWeight ) ) { + if ( /\s/.test( face.fontWeight.trim() ) ) { variableFont = true; } From 362d1c7afccc2841b165165c77e4f750cf5fb21f Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Fri, 31 May 2024 10:28:32 +0100 Subject: [PATCH 19/39] Add tests for normal and bold font weights --- .../block-editor/src/utils/test/format-font-weight.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/block-editor/src/utils/test/format-font-weight.js b/packages/block-editor/src/utils/test/format-font-weight.js index 37ece66c905147..3e6aedac909348 100644 --- a/packages/block-editor/src/utils/test/format-font-weight.js +++ b/packages/block-editor/src/utils/test/format-font-weight.js @@ -50,5 +50,13 @@ describe( 'formatFontWeight', () => { name: 'Black', value: '900', } ); + expect( formatFontWeight( 'normal' ) ).toEqual( { + name: 'Regular', + value: 'normal', + } ); + expect( formatFontWeight( 'bold' ) ).toEqual( { + name: 'Bold', + value: 'bold', + } ); } ); } ); From aba764dc91a26685b3a4f51420f26b94ed42f935 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Fri, 31 May 2024 13:09:50 +0100 Subject: [PATCH 20/39] Trim font weight before checking for spaces --- .../src/components/font-appearance-control/index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/font-appearance-control/index.js b/packages/block-editor/src/components/font-appearance-control/index.js index d271b46353bba1..f251f839720333 100644 --- a/packages/block-editor/src/components/font-appearance-control/index.js +++ b/packages/block-editor/src/components/font-appearance-control/index.js @@ -117,8 +117,11 @@ export default function FontAppearanceControl( props ) { ( weight ) => weight.value === face.fontWeight ) ) { + // Remove any leading or trailing whitespace from the font weight. + face.fontWeight.trim(); + // Check if font weight includes a space, if so it must be a variable font. - if ( /\s/.test( face.fontWeight.trim() ) ) { + if ( /\s/.test( face.fontWeight ) ) { variableFont = true; } From e6d2e67d0898b361c13fd092bae6497e7529b010 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Fri, 31 May 2024 13:55:17 +0100 Subject: [PATCH 21/39] Create getFontStylesAndWeights function --- .../font-appearance-control/index.js | 94 +-------------- .../src/utils/get-font-styles-and-weights.js | 110 ++++++++++++++++++ .../utils/test/get-font-styles-and-weights.js | 97 +++++++++++++++ 3 files changed, 211 insertions(+), 90 deletions(-) create mode 100644 packages/block-editor/src/utils/get-font-styles-and-weights.js create mode 100644 packages/block-editor/src/utils/test/get-font-styles-and-weights.js diff --git a/packages/block-editor/src/components/font-appearance-control/index.js b/packages/block-editor/src/components/font-appearance-control/index.js index f251f839720333..f8d4af455002cf 100644 --- a/packages/block-editor/src/components/font-appearance-control/index.js +++ b/packages/block-editor/src/components/font-appearance-control/index.js @@ -3,63 +3,12 @@ */ import { CustomSelectControl } from '@wordpress/components'; import { useMemo } from '@wordpress/element'; -import { __, _x, sprintf } from '@wordpress/i18n'; +import { __, sprintf } from '@wordpress/i18n'; /** * Internal dependencies */ -import { formatFontWeight } from '../../utils/format-font-weight'; -import { formatFontStyle } from '../../utils/format-font-style'; - -const FONT_STYLES = [ - { - name: _x( 'Regular', 'font style' ), - value: 'normal', - }, - { - name: _x( 'Italic', 'font style' ), - value: 'italic', - }, -]; - -const FONT_WEIGHTS = [ - { - name: _x( 'Thin', 'font weight' ), - value: '100', - }, - { - name: _x( 'Extra Light', 'font weight' ), - value: '200', - }, - { - name: _x( 'Light', 'font weight' ), - value: '300', - }, - { - name: _x( 'Regular', 'font weight' ), - value: '400', - }, - { - name: _x( 'Medium', 'font weight' ), - value: '500', - }, - { - name: _x( 'Semi Bold', 'font weight' ), - value: '600', - }, - { - name: _x( 'Bold', 'font weight' ), - value: '700', - }, - { - name: _x( 'Extra Bold', 'font weight' ), - value: '800', - }, - { - name: _x( 'Black', 'font weight' ), - value: '900', - }, -]; +import { getFontStylesAndWeights } from '../../utils/get-font-styles-and-weights'; /** * Adjusts font appearance field label in case either font styles or weights @@ -104,43 +53,8 @@ export default function FontAppearanceControl( props ) { name: __( 'Default' ), style: { fontStyle: undefined, fontWeight: undefined }, }; - - // Build font style and weight options based on the font family faces. - let fontWeights = []; - let fontStyles = []; - let variableFont = false; - - fontFamilyFaces?.forEach( ( face ) => { - if ( face.fontWeight ) { - if ( - ! fontWeights.some( - ( weight ) => weight.value === face.fontWeight - ) - ) { - // Remove any leading or trailing whitespace from the font weight. - face.fontWeight.trim(); - - // Check if font weight includes a space, if so it must be a variable font. - if ( /\s/.test( face.fontWeight ) ) { - variableFont = true; - } - - fontWeights.push( formatFontWeight( face.fontWeight ) ); - } - } - if ( face.fontStyle ) { - if ( - ! fontStyles.some( ( style ) => style.value === face.fontStyle ) - ) { - fontStyles.push( formatFontStyle( face.fontStyle ) ); - } - } - } ); - - fontWeights = - fontWeights.length === 0 || variableFont ? FONT_WEIGHTS : fontWeights; - fontStyles = - fontStyles.length === 0 || variableFont ? FONT_STYLES : fontStyles; + const { fontStyles, fontWeights } = + getFontStylesAndWeights( fontFamilyFaces ); // Combines both font style and weight options into a single dropdown. const combineOptions = () => { diff --git a/packages/block-editor/src/utils/get-font-styles-and-weights.js b/packages/block-editor/src/utils/get-font-styles-and-weights.js new file mode 100644 index 00000000000000..74f576da194542 --- /dev/null +++ b/packages/block-editor/src/utils/get-font-styles-and-weights.js @@ -0,0 +1,110 @@ +/** + * WordPress dependencies + */ +import { _x } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { formatFontStyle } from './format-font-style'; +import { formatFontWeight } from './format-font-weight'; + +const FONT_STYLES = [ + { + name: _x( 'Regular', 'font style' ), + value: 'normal', + }, + { + name: _x( 'Italic', 'font style' ), + value: 'italic', + }, +]; + +const FONT_WEIGHTS = [ + { + name: _x( 'Thin', 'font weight' ), + value: '100', + }, + { + name: _x( 'Extra Light', 'font weight' ), + value: '200', + }, + { + name: _x( 'Light', 'font weight' ), + value: '300', + }, + { + name: _x( 'Regular', 'font weight' ), + value: '400', + }, + { + name: _x( 'Medium', 'font weight' ), + value: '500', + }, + { + name: _x( 'Semi Bold', 'font weight' ), + value: '600', + }, + { + name: _x( 'Bold', 'font weight' ), + value: '700', + }, + { + name: _x( 'Extra Bold', 'font weight' ), + value: '800', + }, + { + name: _x( 'Black', 'font weight' ), + value: '900', + }, +]; + +/** + * Builds a list of font style and weight options based on font family faces. + * + * @param {Array} fontFamilyFaces font family faces array + * @return {Object} new object with font style and weight options + */ +export function getFontStylesAndWeights( fontFamilyFaces ) { + if ( ! fontFamilyFaces ) { + return {}; + } + + let fontStyles = []; + let fontWeights = []; + let variableFont = false; + + fontFamilyFaces.forEach( ( face ) => { + if ( face.fontStyle ) { + if ( + ! fontStyles.some( ( style ) => style.value === face.fontStyle ) + ) { + fontStyles.push( formatFontStyle( face.fontStyle ) ); + } + } + if ( face.fontWeight ) { + if ( + ! fontWeights.some( + ( weight ) => weight.value === face.fontWeight + ) + ) { + // Remove any leading or trailing whitespace from the font weight. + face.fontWeight.trim(); + + // Check if font weight includes a space, if so it must be a variable font. + if ( /\s/.test( face.fontWeight ) ) { + variableFont = true; + } + + fontWeights.push( formatFontWeight( face.fontWeight ) ); + } + } + } ); + + fontStyles = + fontStyles.length === 0 || variableFont ? FONT_STYLES : fontStyles; + fontWeights = + fontWeights.length === 0 || variableFont ? FONT_WEIGHTS : fontWeights; + + return { fontStyles, fontWeights }; +} diff --git a/packages/block-editor/src/utils/test/get-font-styles-and-weights.js b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js new file mode 100644 index 00000000000000..2c19a28c449624 --- /dev/null +++ b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js @@ -0,0 +1,97 @@ +/** + * Internal dependencies + */ +import { getFontStylesAndWeights } from '../get-font-styles-and-weights'; + +describe( 'getFontStylesAndWeights', () => { + it( 'should return empty object if fontFamilyFaces is not available', () => { + expect( getFontStylesAndWeights() ).toEqual( {} ); + } ); + + it( 'should return correct font styles and weights based on available options', () => { + const fontFamilyFaces = [ + { + fontFamily: 'ABeeZee', + fontStyle: 'italic', + fontWeight: '400', + src: 'http://www.wordpress.org/wp-content/uploads/fonts/esDT31xSG-6AGleN2tCkkJUCGpG-GQ.woff2', + }, + ]; + expect( getFontStylesAndWeights( fontFamilyFaces ) ).toEqual( { + fontStyles: [ + { + name: 'Italic', + value: 'italic', + }, + ], + fontWeights: [ + { + name: 'Regular', + value: '400', + }, + ], + } ); + } ); + + it( 'should return all available style and weight options if font weights string includes a space', () => { + const fontFamilyFaces = [ + { + fontFamily: 'Inter', + fontStyle: 'normal', + fontWeight: '100 900', + src: 'http://www.wordpress.org/wp-content/uploads/fonts/Inter-VariableFont_slntwght.ttf', + }, + ]; + + expect( getFontStylesAndWeights( fontFamilyFaces ) ).toEqual( { + fontStyles: [ + { + name: 'Regular', + value: 'normal', + }, + { + name: 'Italic', + value: 'italic', + }, + ], + fontWeights: [ + { + name: 'Thin', + value: '100', + }, + { + name: 'Extra Light', + value: '200', + }, + { + name: 'Light', + value: '300', + }, + { + name: 'Regular', + value: '400', + }, + { + name: 'Medium', + value: '500', + }, + { + name: 'Semi Bold', + value: '600', + }, + { + name: 'Bold', + value: '700', + }, + { + name: 'Extra Bold', + value: '800', + }, + { + name: 'Black', + value: '900', + }, + ], + } ); + } ); +} ); From 7bd07ab08120159cd65df8087605687bd36a439a Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Fri, 31 May 2024 17:59:44 +0100 Subject: [PATCH 22/39] Move trim into if statement and improve comment --- .../block-editor/src/utils/get-font-styles-and-weights.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/utils/get-font-styles-and-weights.js b/packages/block-editor/src/utils/get-font-styles-and-weights.js index 74f576da194542..22662ab6694173 100644 --- a/packages/block-editor/src/utils/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/get-font-styles-and-weights.js @@ -88,11 +88,8 @@ export function getFontStylesAndWeights( fontFamilyFaces ) { ( weight ) => weight.value === face.fontWeight ) ) { - // Remove any leading or trailing whitespace from the font weight. - face.fontWeight.trim(); - - // Check if font weight includes a space, if so it must be a variable font. - if ( /\s/.test( face.fontWeight ) ) { + // Check if font weight includes a space that is not at the start or end of the string. If so, it must be a variable font. e.g. "100 900" + if ( /\s/.test( face.fontWeight.trim() ) ) { variableFont = true; } From 48eac26ad42abdc8b506d0becf3c46a135ef9630 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Mon, 3 Jun 2024 18:33:44 +0100 Subject: [PATCH 23/39] Allow all uncombined weights and styles to be returned from getFontStylesAndWeights --- .../font-appearance-control/index.js | 29 ++++++- .../src/utils/get-font-styles-and-weights.js | 53 +++++++++---- .../utils/test/get-font-styles-and-weights.js | 75 ++++++++++++++++++- 3 files changed, 136 insertions(+), 21 deletions(-) diff --git a/packages/block-editor/src/components/font-appearance-control/index.js b/packages/block-editor/src/components/font-appearance-control/index.js index f8d4af455002cf..31b439820aee90 100644 --- a/packages/block-editor/src/components/font-appearance-control/index.js +++ b/packages/block-editor/src/components/font-appearance-control/index.js @@ -53,7 +53,8 @@ export default function FontAppearanceControl( props ) { name: __( 'Default' ), style: { fontStyle: undefined, fontWeight: undefined }, }; - const { fontStyles, fontWeights } = + const isSystemFont = ! fontFamilyFaces; + const { allStylesAndWeights, fontStyles, fontWeights, isVariableFont } = getFontStylesAndWeights( fontFamilyFaces ); // Combines both font style and weight options into a single dropdown. @@ -88,6 +89,14 @@ export default function FontAppearanceControl( props ) { return combinedOptions; }; + const allOptions = () => { + const allFontOptions = [ defaultOption ]; + if ( allStylesAndWeights ) { + allFontOptions.push( ...allStylesAndWeights ); + } + return allFontOptions; + }; + // Generates select options for font styles only. const styleOptions = () => { const combinedOptions = [ defaultOption ]; @@ -116,12 +125,26 @@ export default function FontAppearanceControl( props ) { // Map font styles and weights to select options. const selectOptions = useMemo( () => { - if ( hasFontStyles && hasFontWeights ) { + // Display combined font style and weight options if font family + // is a system font or a variable font. + if ( isSystemFont || isVariableFont ) { return combineOptions(); } + // Display all available font style and weight options. + if ( hasFontStyles && hasFontWeights ) { + return allOptions(); + } + + // Display only font style options or font weight options. return hasFontStyles ? styleOptions() : weightOptions(); - }, [ props.options, fontStyles, fontWeights ] ); + }, [ + props.options, + fontStyles, + fontWeights, + isSystemFont, + isVariableFont, + ] ); // Find current selection by comparing font style & weight against options, // and fall back to the Default option if there is no matching option. diff --git a/packages/block-editor/src/utils/get-font-styles-and-weights.js b/packages/block-editor/src/utils/get-font-styles-and-weights.js index 22662ab6694173..b9574d04ff8c81 100644 --- a/packages/block-editor/src/utils/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/get-font-styles-and-weights.js @@ -61,47 +61,68 @@ const FONT_WEIGHTS = [ /** * Builds a list of font style and weight options based on font family faces. + * Defaults to the standard font styles and weights if no font family faces are provided. * * @param {Array} fontFamilyFaces font family faces array - * @return {Object} new object with font style and weight options + * @return {Object} new object with font style, weight, and variable font properties */ export function getFontStylesAndWeights( fontFamilyFaces ) { - if ( ! fontFamilyFaces ) { - return {}; - } - + const allStylesAndWeights = []; let fontStyles = []; let fontWeights = []; - let variableFont = false; + let isVariableFont = false; + + if ( ! fontFamilyFaces ) { + // Return default font styles and weights if no font family faces are provided. + return { fontStyles: FONT_STYLES, fontWeights: FONT_WEIGHTS }; + } fontFamilyFaces.forEach( ( face ) => { - if ( face.fontStyle ) { + const fontStyle = formatFontStyle( face.fontStyle ); + const fontWeight = formatFontWeight( face.fontWeight ); + const optionName = + fontStyle.value === 'normal' + ? fontWeight.name + : `${ fontWeight.name } ${ fontStyle.name }`; + + allStylesAndWeights.push( { + key: `${ fontWeight.value }-${ fontStyle.value }`, + name: optionName, + style: { + fontStyle: fontStyle.value, + fontWeight: fontWeight.value, + }, + } ); + + if ( fontStyle ) { if ( - ! fontStyles.some( ( style ) => style.value === face.fontStyle ) + ! fontStyles.some( + ( style ) => style.value === fontStyle.value + ) ) { - fontStyles.push( formatFontStyle( face.fontStyle ) ); + fontStyles.push( fontStyle ); } } - if ( face.fontWeight ) { + if ( fontWeight ) { if ( ! fontWeights.some( - ( weight ) => weight.value === face.fontWeight + ( weight ) => weight.value === fontWeight.value ) ) { // Check if font weight includes a space that is not at the start or end of the string. If so, it must be a variable font. e.g. "100 900" if ( /\s/.test( face.fontWeight.trim() ) ) { - variableFont = true; + isVariableFont = true; } - fontWeights.push( formatFontWeight( face.fontWeight ) ); + fontWeights.push( fontWeight ); } } } ); fontStyles = - fontStyles.length === 0 || variableFont ? FONT_STYLES : fontStyles; + fontStyles.length === 0 || isVariableFont ? FONT_STYLES : fontStyles; fontWeights = - fontWeights.length === 0 || variableFont ? FONT_WEIGHTS : fontWeights; + fontWeights.length === 0 || isVariableFont ? FONT_WEIGHTS : fontWeights; - return { fontStyles, fontWeights }; + return { allStylesAndWeights, fontStyles, fontWeights, isVariableFont }; } diff --git a/packages/block-editor/src/utils/test/get-font-styles-and-weights.js b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js index 2c19a28c449624..3f27231b3e84d3 100644 --- a/packages/block-editor/src/utils/test/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js @@ -4,8 +4,57 @@ import { getFontStylesAndWeights } from '../get-font-styles-and-weights'; describe( 'getFontStylesAndWeights', () => { - it( 'should return empty object if fontFamilyFaces is not available', () => { - expect( getFontStylesAndWeights() ).toEqual( {} ); + it( 'should return default styles and weights if fontFamilyFaces is not available', () => { + expect( getFontStylesAndWeights() ).toEqual( { + fontStyles: [ + { + name: 'Regular', + value: 'normal', + }, + { + name: 'Italic', + value: 'italic', + }, + ], + fontWeights: [ + { + name: 'Thin', + value: '100', + }, + { + name: 'Extra Light', + value: '200', + }, + { + name: 'Light', + value: '300', + }, + { + name: 'Regular', + value: '400', + }, + { + name: 'Medium', + value: '500', + }, + { + name: 'Semi Bold', + value: '600', + }, + { + name: 'Bold', + value: '700', + }, + { + name: 'Extra Bold', + value: '800', + }, + { + name: 'Black', + value: '900', + }, + ], + } ); } ); it( 'should return correct font styles and weights based on available options', () => { @@ -18,6 +67,16 @@ describe( 'getFontStylesAndWeights', () => { }, ]; expect( getFontStylesAndWeights( fontFamilyFaces ) ).toEqual( { + allStylesAndWeights: [ + { + key: '400-italic', + name: 'Regular Italic', + style: { + fontStyle: 'italic', + fontWeight: '400', + }, + }, + ], fontStyles: [ { name: 'Italic', @@ -30,6 +89,7 @@ describe( 'getFontStylesAndWeights', () => { value: '400', }, ], + isVariableFont: false, } ); } ); @@ -44,6 +104,16 @@ describe( 'getFontStylesAndWeights', () => { ]; expect( getFontStylesAndWeights( fontFamilyFaces ) ).toEqual( { + allStylesAndWeights: [ + { + key: '100 900-normal', + name: '100 900 Regular', + style: { + fontStyle: 'normal', + fontWeight: '100 900', + }, + }, + ], fontStyles: [ { name: 'Regular', @@ -92,6 +162,7 @@ describe( 'getFontStylesAndWeights', () => { value: '900', }, ], + isVariableFont: true, } ); } ); } ); From 8ffd9b2ca7f8132d456c1885795f1303d297da8a Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Tue, 4 Jun 2024 12:34:12 +0100 Subject: [PATCH 24/39] Make option key consistent with combined result --- .../src/utils/get-font-styles-and-weights.js | 14 ++++++++------ .../src/utils/test/get-font-styles-and-weights.js | 10 +++++----- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/block-editor/src/utils/get-font-styles-and-weights.js b/packages/block-editor/src/utils/get-font-styles-and-weights.js index b9574d04ff8c81..2bad24a6faa715 100644 --- a/packages/block-editor/src/utils/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/get-font-styles-and-weights.js @@ -80,13 +80,20 @@ export function getFontStylesAndWeights( fontFamilyFaces ) { fontFamilyFaces.forEach( ( face ) => { const fontStyle = formatFontStyle( face.fontStyle ); const fontWeight = formatFontWeight( face.fontWeight ); + + // Check if font weight includes a space that is not at the start or end of the string. If so, it must be a variable font. e.g. "100 900" + if ( /\s/.test( fontWeight.value.trim() ) ) { + isVariableFont = true; + fontWeight.value = fontWeight.value.replace( /\s+/g, '-' ); + } + const optionName = fontStyle.value === 'normal' ? fontWeight.name : `${ fontWeight.name } ${ fontStyle.name }`; allStylesAndWeights.push( { - key: `${ fontWeight.value }-${ fontStyle.value }`, + key: `${ fontStyle.value }-${ fontWeight.value }`, name: optionName, style: { fontStyle: fontStyle.value, @@ -109,11 +116,6 @@ export function getFontStylesAndWeights( fontFamilyFaces ) { ( weight ) => weight.value === fontWeight.value ) ) { - // Check if font weight includes a space that is not at the start or end of the string. If so, it must be a variable font. e.g. "100 900" - if ( /\s/.test( face.fontWeight.trim() ) ) { - isVariableFont = true; - } - fontWeights.push( fontWeight ); } } diff --git a/packages/block-editor/src/utils/test/get-font-styles-and-weights.js b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js index 3f27231b3e84d3..8107efc8822fc6 100644 --- a/packages/block-editor/src/utils/test/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js @@ -69,7 +69,7 @@ describe( 'getFontStylesAndWeights', () => { expect( getFontStylesAndWeights( fontFamilyFaces ) ).toEqual( { allStylesAndWeights: [ { - key: '400-italic', + key: 'italic-400', name: 'Regular Italic', style: { fontStyle: 'italic', @@ -93,7 +93,7 @@ describe( 'getFontStylesAndWeights', () => { } ); } ); - it( 'should return all available style and weight options if font weights string includes a space', () => { + it( 'should return all available style and weight options if `fontWeight` includes a space', () => { const fontFamilyFaces = [ { fontFamily: 'Inter', @@ -106,11 +106,11 @@ describe( 'getFontStylesAndWeights', () => { expect( getFontStylesAndWeights( fontFamilyFaces ) ).toEqual( { allStylesAndWeights: [ { - key: '100 900-normal', - name: '100 900 Regular', + key: 'normal-100-900', + name: '100 900', style: { fontStyle: 'normal', - fontWeight: '100 900', + fontWeight: '100-900', }, }, ], From 6b36ff0e6fbfbb62a931a9a179225a1545a31603 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Tue, 4 Jun 2024 14:47:54 +0100 Subject: [PATCH 25/39] Move combined option logic into getFontStylesAndWeights() --- .../font-appearance-control/index.js | 55 +-- .../src/utils/get-font-styles-and-weights.js | 96 +++-- .../utils/test/get-font-styles-and-weights.js | 350 ++++++++++++++++-- 3 files changed, 390 insertions(+), 111 deletions(-) diff --git a/packages/block-editor/src/components/font-appearance-control/index.js b/packages/block-editor/src/components/font-appearance-control/index.js index 31b439820aee90..418d43e322ac89 100644 --- a/packages/block-editor/src/components/font-appearance-control/index.js +++ b/packages/block-editor/src/components/font-appearance-control/index.js @@ -53,48 +53,16 @@ export default function FontAppearanceControl( props ) { name: __( 'Default' ), style: { fontStyle: undefined, fontWeight: undefined }, }; - const isSystemFont = ! fontFamilyFaces; - const { allStylesAndWeights, fontStyles, fontWeights, isVariableFont } = + const { fontStyles, fontWeights, combinedStyleAndWeightOptions } = getFontStylesAndWeights( fontFamilyFaces ); - // Combines both font style and weight options into a single dropdown. + // Generates select options for combined font styles and weights. const combineOptions = () => { const combinedOptions = [ defaultOption ]; - - fontStyles.forEach( ( { name: styleName, value: styleValue } ) => { - fontWeights.forEach( - ( { name: weightName, value: weightValue } ) => { - const optionName = - styleValue === 'normal' - ? weightName - : sprintf( - /* translators: 1: Font weight name. 2: Font style name. */ - __( '%1$s %2$s' ), - weightName, - styleName - ); - - combinedOptions.push( { - key: `${ styleValue }-${ weightValue }`, - name: optionName, - style: { - fontStyle: styleValue, - fontWeight: weightValue, - }, - } ); - } - ); - } ); - - return combinedOptions; - }; - - const allOptions = () => { - const allFontOptions = [ defaultOption ]; - if ( allStylesAndWeights ) { - allFontOptions.push( ...allStylesAndWeights ); + if ( combinedStyleAndWeightOptions ) { + combinedOptions.push( ...combinedStyleAndWeightOptions ); } - return allFontOptions; + return combinedOptions; }; // Generates select options for font styles only. @@ -125,15 +93,9 @@ export default function FontAppearanceControl( props ) { // Map font styles and weights to select options. const selectOptions = useMemo( () => { - // Display combined font style and weight options if font family - // is a system font or a variable font. - if ( isSystemFont || isVariableFont ) { - return combineOptions(); - } - - // Display all available font style and weight options. + // Display combined available font style and weight options. if ( hasFontStyles && hasFontWeights ) { - return allOptions(); + return combineOptions(); } // Display only font style options or font weight options. @@ -142,8 +104,7 @@ export default function FontAppearanceControl( props ) { props.options, fontStyles, fontWeights, - isSystemFont, - isVariableFont, + combinedStyleAndWeightOptions, ] ); // Find current selection by comparing font style & weight against options, diff --git a/packages/block-editor/src/utils/get-font-styles-and-weights.js b/packages/block-editor/src/utils/get-font-styles-and-weights.js index 2bad24a6faa715..1e2062022dcd28 100644 --- a/packages/block-editor/src/utils/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/get-font-styles-and-weights.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { _x } from '@wordpress/i18n'; +import { _x, __, sprintf } from '@wordpress/i18n'; /** * Internal dependencies @@ -64,22 +64,18 @@ const FONT_WEIGHTS = [ * Defaults to the standard font styles and weights if no font family faces are provided. * * @param {Array} fontFamilyFaces font family faces array - * @return {Object} new object with font style, weight, and variable font properties + * @return {Object} new object with combined and separated font style and weight properties */ export function getFontStylesAndWeights( fontFamilyFaces ) { - const allStylesAndWeights = []; let fontStyles = []; let fontWeights = []; + const combinedStyleAndWeightOptions = []; + const isSystemFont = ! fontFamilyFaces; let isVariableFont = false; - if ( ! fontFamilyFaces ) { - // Return default font styles and weights if no font family faces are provided. - return { fontStyles: FONT_STYLES, fontWeights: FONT_WEIGHTS }; - } - - fontFamilyFaces.forEach( ( face ) => { - const fontStyle = formatFontStyle( face.fontStyle ); + fontFamilyFaces?.forEach( ( face ) => { const fontWeight = formatFontWeight( face.fontWeight ); + const fontStyle = formatFontStyle( face.fontStyle ); // Check if font weight includes a space that is not at the start or end of the string. If so, it must be a variable font. e.g. "100 900" if ( /\s/.test( fontWeight.value.trim() ) ) { @@ -87,20 +83,7 @@ export function getFontStylesAndWeights( fontFamilyFaces ) { fontWeight.value = fontWeight.value.replace( /\s+/g, '-' ); } - const optionName = - fontStyle.value === 'normal' - ? fontWeight.name - : `${ fontWeight.name } ${ fontStyle.name }`; - - allStylesAndWeights.push( { - key: `${ fontStyle.value }-${ fontWeight.value }`, - name: optionName, - style: { - fontStyle: fontStyle.value, - fontWeight: fontWeight.value, - }, - } ); - + // Create font style and font weight lists without duplicates. if ( fontStyle ) { if ( ! fontStyles.some( @@ -119,12 +102,67 @@ export function getFontStylesAndWeights( fontFamilyFaces ) { fontWeights.push( fontWeight ); } } + + if ( isVariableFont ) { + // If the font is a variable font, we don't need to generate the list of font styles and weights. + return; + } + + // Generate combined font style and weight options for available fonts. + const optionName = + fontStyle.value === 'normal' + ? fontWeight.name + : `${ fontWeight.name } ${ fontStyle.name }`; + + combinedStyleAndWeightOptions.push( { + key: `${ fontStyle.value }-${ fontWeight.value }`, + name: optionName, + style: { + fontStyle: fontStyle.value, + fontWeight: fontWeight.value, + }, + } ); } ); - fontStyles = - fontStyles.length === 0 || isVariableFont ? FONT_STYLES : fontStyles; - fontWeights = - fontWeights.length === 0 || isVariableFont ? FONT_WEIGHTS : fontWeights; + // Generate combined default options for system fonts and variable fonts. + if ( isSystemFont || isVariableFont ) { + FONT_STYLES.forEach( ( { name: styleName, value: styleValue } ) => { + FONT_WEIGHTS.forEach( + ( { name: weightName, value: weightValue } ) => { + const optionName = + styleValue === 'normal' + ? weightName + : sprintf( + /* translators: 1: Font weight name. 2: Font style name. */ + __( '%1$s %2$s' ), + weightName, + styleName + ); + + combinedStyleAndWeightOptions.push( { + key: `${ styleValue }-${ weightValue }`, + name: optionName, + style: { + fontStyle: styleValue, + fontWeight: weightValue, + }, + } ); + } + ); + } ); + + // Use default font styles and weights for system and variable fonts. + fontStyles = FONT_STYLES; + fontWeights = FONT_WEIGHTS; + } + + // Use default font styles and weights if no font family faces are provided. + fontStyles = fontStyles.length === 0 ? FONT_STYLES : fontStyles; + fontWeights = fontWeights.length === 0 ? FONT_WEIGHTS : fontWeights; - return { allStylesAndWeights, fontStyles, fontWeights, isVariableFont }; + return { + fontStyles, + fontWeights, + combinedStyleAndWeightOptions, + }; } diff --git a/packages/block-editor/src/utils/test/get-font-styles-and-weights.js b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js index 8107efc8822fc6..36053189802f65 100644 --- a/packages/block-editor/src/utils/test/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js @@ -54,20 +54,103 @@ describe( 'getFontStylesAndWeights', () => { value: '900', }, ], - } ); - } ); - - it( 'should return correct font styles and weights based on available options', () => { - const fontFamilyFaces = [ - { - fontFamily: 'ABeeZee', - fontStyle: 'italic', - fontWeight: '400', - src: 'http://www.wordpress.org/wp-content/uploads/fonts/esDT31xSG-6AGleN2tCkkJUCGpG-GQ.woff2', - }, - ]; - expect( getFontStylesAndWeights( fontFamilyFaces ) ).toEqual( { - allStylesAndWeights: [ + combinedStyleAndWeightOptions: [ + { + key: 'normal-100', + name: 'Thin', + style: { + fontStyle: 'normal', + fontWeight: '100', + }, + }, + { + key: 'normal-200', + name: 'Extra Light', + style: { + fontStyle: 'normal', + fontWeight: '200', + }, + }, + { + key: 'normal-300', + name: 'Light', + style: { + fontStyle: 'normal', + fontWeight: '300', + }, + }, + { + key: 'normal-400', + name: 'Regular', + style: { + fontStyle: 'normal', + fontWeight: '400', + }, + }, + { + key: 'normal-500', + name: 'Medium', + style: { + fontStyle: 'normal', + fontWeight: '500', + }, + }, + { + key: 'normal-600', + name: 'Semi Bold', + style: { + fontStyle: 'normal', + fontWeight: '600', + }, + }, + { + key: 'normal-700', + name: 'Bold', + style: { + fontStyle: 'normal', + fontWeight: '700', + }, + }, + { + key: 'normal-800', + name: 'Extra Bold', + style: { + fontStyle: 'normal', + fontWeight: '800', + }, + }, + { + key: 'normal-900', + name: 'Black', + style: { + fontStyle: 'normal', + fontWeight: '900', + }, + }, + { + key: 'italic-100', + name: 'Thin Italic', + style: { + fontStyle: 'italic', + fontWeight: '100', + }, + }, + { + key: 'italic-200', + name: 'Extra Light Italic', + style: { + fontStyle: 'italic', + fontWeight: '200', + }, + }, + { + key: 'italic-300', + name: 'Light Italic', + style: { + fontStyle: 'italic', + fontWeight: '300', + }, + }, { key: 'italic-400', name: 'Regular Italic', @@ -76,24 +159,51 @@ describe( 'getFontStylesAndWeights', () => { fontWeight: '400', }, }, - ], - fontStyles: [ { - name: 'Italic', - value: 'italic', + key: 'italic-500', + name: 'Medium Italic', + style: { + fontStyle: 'italic', + fontWeight: '500', + }, }, - ], - fontWeights: [ { - name: 'Regular', - value: '400', + key: 'italic-600', + name: 'Semi Bold Italic', + style: { + fontStyle: 'italic', + fontWeight: '600', + }, + }, + { + key: 'italic-700', + name: 'Bold Italic', + style: { + fontStyle: 'italic', + fontWeight: '700', + }, + }, + { + key: 'italic-800', + name: 'Extra Bold Italic', + style: { + fontStyle: 'italic', + fontWeight: '800', + }, + }, + { + key: 'italic-900', + name: 'Black Italic', + style: { + fontStyle: 'italic', + fontWeight: '900', + }, }, ], - isVariableFont: false, } ); } ); - it( 'should return all available style and weight options if `fontWeight` includes a space', () => { + it( 'should return default styles and weights if fontWeight includes a space', () => { const fontFamilyFaces = [ { fontFamily: 'Inter', @@ -104,16 +214,6 @@ describe( 'getFontStylesAndWeights', () => { ]; expect( getFontStylesAndWeights( fontFamilyFaces ) ).toEqual( { - allStylesAndWeights: [ - { - key: 'normal-100-900', - name: '100 900', - style: { - fontStyle: 'normal', - fontWeight: '100-900', - }, - }, - ], fontStyles: [ { name: 'Regular', @@ -162,7 +262,187 @@ describe( 'getFontStylesAndWeights', () => { value: '900', }, ], - isVariableFont: true, + combinedStyleAndWeightOptions: [ + { + key: 'normal-100', + name: 'Thin', + style: { + fontStyle: 'normal', + fontWeight: '100', + }, + }, + { + key: 'normal-200', + name: 'Extra Light', + style: { + fontStyle: 'normal', + fontWeight: '200', + }, + }, + { + key: 'normal-300', + name: 'Light', + style: { + fontStyle: 'normal', + fontWeight: '300', + }, + }, + { + key: 'normal-400', + name: 'Regular', + style: { + fontStyle: 'normal', + fontWeight: '400', + }, + }, + { + key: 'normal-500', + name: 'Medium', + style: { + fontStyle: 'normal', + fontWeight: '500', + }, + }, + { + key: 'normal-600', + name: 'Semi Bold', + style: { + fontStyle: 'normal', + fontWeight: '600', + }, + }, + { + key: 'normal-700', + name: 'Bold', + style: { + fontStyle: 'normal', + fontWeight: '700', + }, + }, + { + key: 'normal-800', + name: 'Extra Bold', + style: { + fontStyle: 'normal', + fontWeight: '800', + }, + }, + { + key: 'normal-900', + name: 'Black', + style: { + fontStyle: 'normal', + fontWeight: '900', + }, + }, + { + key: 'italic-100', + name: 'Thin Italic', + style: { + fontStyle: 'italic', + fontWeight: '100', + }, + }, + { + key: 'italic-200', + name: 'Extra Light Italic', + style: { + fontStyle: 'italic', + fontWeight: '200', + }, + }, + { + key: 'italic-300', + name: 'Light Italic', + style: { + fontStyle: 'italic', + fontWeight: '300', + }, + }, + { + key: 'italic-400', + name: 'Regular Italic', + style: { + fontStyle: 'italic', + fontWeight: '400', + }, + }, + { + key: 'italic-500', + name: 'Medium Italic', + style: { + fontStyle: 'italic', + fontWeight: '500', + }, + }, + { + key: 'italic-600', + name: 'Semi Bold Italic', + style: { + fontStyle: 'italic', + fontWeight: '600', + }, + }, + { + key: 'italic-700', + name: 'Bold Italic', + style: { + fontStyle: 'italic', + fontWeight: '700', + }, + }, + { + key: 'italic-800', + name: 'Extra Bold Italic', + style: { + fontStyle: 'italic', + fontWeight: '800', + }, + }, + { + key: 'italic-900', + name: 'Black Italic', + style: { + fontStyle: 'italic', + fontWeight: '900', + }, + }, + ], + } ); + } ); + + it( 'should return correct font styles and weights based on available options', () => { + const fontFamilyFaces = [ + { + fontFamily: 'ABeeZee', + fontStyle: 'italic', + fontWeight: '400', + src: 'http://www.wordpress.org/wp-content/uploads/fonts/esDT31xSG-6AGleN2tCkkJUCGpG-GQ.woff2', + }, + ]; + expect( getFontStylesAndWeights( fontFamilyFaces ) ).toEqual( { + combinedStyleAndWeightOptions: [ + { + key: 'italic-400', + name: 'Regular Italic', + style: { + fontStyle: 'italic', + fontWeight: '400', + }, + }, + ], + fontStyles: [ + { + name: 'Italic', + value: 'italic', + }, + ], + fontWeights: [ + { + name: 'Regular', + value: '400', + }, + ], } ); } ); } ); From 1ca996bfd54ada3246596aab3ae22586652227b3 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Tue, 4 Jun 2024 17:27:34 +0100 Subject: [PATCH 26/39] Swap ABeeZee test for Piazzolla example Co-Authored-By: Vicente Canales <1157901+vcanales@users.noreply.github.com> --- .../utils/test/get-font-styles-and-weights.js | 80 ++++++++++++++++--- 1 file changed, 67 insertions(+), 13 deletions(-) diff --git a/packages/block-editor/src/utils/test/get-font-styles-and-weights.js b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js index 36053189802f65..db97e96fdc58d8 100644 --- a/packages/block-editor/src/utils/test/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js @@ -411,27 +411,39 @@ describe( 'getFontStylesAndWeights', () => { } ); } ); - it( 'should return correct font styles and weights based on available options', () => { + it( 'should return only provided font styles and weights', () => { const fontFamilyFaces = [ { - fontFamily: 'ABeeZee', - fontStyle: 'italic', + fontFamily: 'Piazzolla', + fontStyle: 'normal', fontWeight: '400', - src: 'http://www.wordpress.org/wp-content/uploads/fonts/esDT31xSG-6AGleN2tCkkJUCGpG-GQ.woff2', + src: 'http://www.wordpress.org/wp-content/uploads/fonts/N0b52SlTPu5rIkWIZjVKKtYtfxYqZ4RJBFzFfYUjkSDdlqZgy7LYxnL31AHfAAy5.woff2', + }, + { + fontFamily: 'Piazzolla', + fontStyle: 'normal', + fontWeight: '900', + src: 'http://www.wordpress.org/wp-content/uploads/fonts/N0b52SlTPu5rIkWIZjVKKtYtfxYqZ4RJBFzFfYUjkSDdlqZgy7JxwXL31AHfAAy5.woff2', + }, + { + fontFamily: 'Piazzolla', + fontStyle: 'italic', + fontWeight: '300', + src: 'http://www.wordpress.org/wp-content/uploads/fonts/N0b72SlTPu5rIkWIZjVgI-TckS03oGpPETyEJ88Rbvi0_TzOzKcQhcSx3gD9BRy5m5M.woff2', + }, + { + fontFamily: 'Piazzolla', + fontStyle: 'italic', + fontWeight: '900', + src: 'http://www.wordpress.org/wp-content/uploads/fonts/N0b72SlTPu5rIkWIZjVgI-TckS03oGpPETyEJ88Rbvi0_TzOzKcQhTO23gD9BRy5m5M.woff2', }, ]; expect( getFontStylesAndWeights( fontFamilyFaces ) ).toEqual( { - combinedStyleAndWeightOptions: [ + fontStyles: [ { - key: 'italic-400', - name: 'Regular Italic', - style: { - fontStyle: 'italic', - fontWeight: '400', - }, + name: 'Regular', + value: 'normal', }, - ], - fontStyles: [ { name: 'Italic', value: 'italic', @@ -442,6 +454,48 @@ describe( 'getFontStylesAndWeights', () => { name: 'Regular', value: '400', }, + { + name: 'Black', + value: '900', + }, + { + name: 'Light', + value: '300', + }, + ], + combinedStyleAndWeightOptions: [ + { + key: 'normal-400', + name: 'Regular', + style: { + fontStyle: 'normal', + fontWeight: '400', + }, + }, + { + key: 'normal-900', + name: 'Black', + style: { + fontStyle: 'normal', + fontWeight: '900', + }, + }, + { + key: 'italic-300', + name: 'Light Italic', + style: { + fontStyle: 'italic', + fontWeight: '300', + }, + }, + { + key: 'italic-900', + name: 'Black Italic', + style: { + fontStyle: 'italic', + fontWeight: '900', + }, + }, ], } ); } ); From 29f6fcb91e368b82a08a8328796453caffaa3aef Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Tue, 18 Jun 2024 22:59:04 +0100 Subject: [PATCH 27/39] Fix isSystemFont logic --- packages/block-editor/src/utils/get-font-styles-and-weights.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/utils/get-font-styles-and-weights.js b/packages/block-editor/src/utils/get-font-styles-and-weights.js index 1e2062022dcd28..67cbaff3a1c55f 100644 --- a/packages/block-editor/src/utils/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/get-font-styles-and-weights.js @@ -70,7 +70,7 @@ export function getFontStylesAndWeights( fontFamilyFaces ) { let fontStyles = []; let fontWeights = []; const combinedStyleAndWeightOptions = []; - const isSystemFont = ! fontFamilyFaces; + const isSystemFont = fontFamilyFaces.length === 0 || ! fontFamilyFaces; let isVariableFont = false; fontFamilyFaces?.forEach( ( face ) => { From 7a965076b9962394d753de81600a41a12937d4b7 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Fri, 21 Jun 2024 19:38:29 +0100 Subject: [PATCH 28/39] Apply available font styles and weights when fontFamily changes --- .../global-styles/typography-panel.js | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/global-styles/typography-panel.js b/packages/block-editor/src/components/global-styles/typography-panel.js index 69f2dea8114909..ab8e3d5efe3ff5 100644 --- a/packages/block-editor/src/components/global-styles/typography-panel.js +++ b/packages/block-editor/src/components/global-styles/typography-panel.js @@ -8,7 +8,7 @@ import { __experimentalToolsPanelItem as ToolsPanelItem, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { useCallback, useMemo } from '@wordpress/element'; +import { useCallback, useMemo, useEffect } from '@wordpress/element'; /** * Internal dependencies @@ -250,6 +250,25 @@ export default function TypographyPanel( { setFontAppearance( {} ); }; + // Check if previous font style and weight values are available in the new font family + useEffect( () => { + const isSystemFont = fontFamilyFaces.length === 0; + const hasFontStyle = fontFamilyFaces?.some( + ( { fontStyle: fs } ) => fs === fontStyle + ); + const hasFontWeight = fontFamilyFaces?.some( + ( { fontWeight: fw } ) => fw === fontWeight + ); + if ( isSystemFont || ( hasFontStyle && hasFontWeight ) ) { + setFontAppearance( { + fontStyle, + fontWeight, + } ); + } else { + resetFontAppearance(); + } + }, [ fontFamily ] ); + // Line Height const hasLineHeightEnabled = useHasLineHeightControl( settings ); const lineHeight = decodeValue( inheritedValue?.typography?.lineHeight ); From 150e3a9ff6030d487b3793d5f283dfb2038ab3e4 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Fri, 21 Jun 2024 19:57:57 +0100 Subject: [PATCH 29/39] Swap isSystemFont logic around --- packages/block-editor/src/utils/get-font-styles-and-weights.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/utils/get-font-styles-and-weights.js b/packages/block-editor/src/utils/get-font-styles-and-weights.js index 67cbaff3a1c55f..98e5b9697e985f 100644 --- a/packages/block-editor/src/utils/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/get-font-styles-and-weights.js @@ -70,7 +70,7 @@ export function getFontStylesAndWeights( fontFamilyFaces ) { let fontStyles = []; let fontWeights = []; const combinedStyleAndWeightOptions = []; - const isSystemFont = fontFamilyFaces.length === 0 || ! fontFamilyFaces; + const isSystemFont = ! fontFamilyFaces || fontFamilyFaces?.length === 0; let isVariableFont = false; fontFamilyFaces?.forEach( ( face ) => { From 97cbbad51828d0850c2f8bca73a98d203276e49f Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Mon, 24 Jun 2024 17:55:23 +0100 Subject: [PATCH 30/39] Export isSystemFont and isVariableFont from getFontStylesAndWeights --- .../block-editor/src/utils/get-font-styles-and-weights.js | 2 ++ .../src/utils/test/get-font-styles-and-weights.js | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/packages/block-editor/src/utils/get-font-styles-and-weights.js b/packages/block-editor/src/utils/get-font-styles-and-weights.js index 98e5b9697e985f..36124607f201fd 100644 --- a/packages/block-editor/src/utils/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/get-font-styles-and-weights.js @@ -164,5 +164,7 @@ export function getFontStylesAndWeights( fontFamilyFaces ) { fontStyles, fontWeights, combinedStyleAndWeightOptions, + isSystemFont, + isVariableFont, }; } diff --git a/packages/block-editor/src/utils/test/get-font-styles-and-weights.js b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js index db97e96fdc58d8..897290e1016c47 100644 --- a/packages/block-editor/src/utils/test/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js @@ -200,6 +200,8 @@ describe( 'getFontStylesAndWeights', () => { }, }, ], + isSystemFont: true, + isVariableFont: false, } ); } ); @@ -408,6 +410,8 @@ describe( 'getFontStylesAndWeights', () => { }, }, ], + isSystemFont: false, + isVariableFont: true, } ); } ); @@ -497,6 +501,8 @@ describe( 'getFontStylesAndWeights', () => { }, }, ], + isSystemFont: false, + isVariableFont: false, } ); } ); } ); From ec2cf86ffa15435da8c925b7c70a93de75fda14e Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Mon, 24 Jun 2024 17:56:09 +0100 Subject: [PATCH 31/39] Use getFontStylesAndWeights to compare font face values --- .../components/global-styles/typography-panel.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/typography-panel.js b/packages/block-editor/src/components/global-styles/typography-panel.js index ab8e3d5efe3ff5..30d7ab0d3e64eb 100644 --- a/packages/block-editor/src/components/global-styles/typography-panel.js +++ b/packages/block-editor/src/components/global-styles/typography-panel.js @@ -24,6 +24,7 @@ import WritingModeControl from '../writing-mode-control'; import { getValueFromVariable, TOOLSPANEL_DROPDOWNMENU_PROPS } from './utils'; import { setImmutably } from '../../utils/object'; import { getMergedFontFamiliesAndFontFamilyFaces } from './typography-utils'; +import { getFontStylesAndWeights } from '../../utils/get-font-styles-and-weights'; const MIN_TEXT_COLUMNS = 1; const MAX_TEXT_COLUMNS = 6; @@ -252,13 +253,15 @@ export default function TypographyPanel( { // Check if previous font style and weight values are available in the new font family useEffect( () => { - const isSystemFont = fontFamilyFaces.length === 0; - const hasFontStyle = fontFamilyFaces?.some( - ( { fontStyle: fs } ) => fs === fontStyle + const { fontStyles, fontWeights, isSystemFont } = + getFontStylesAndWeights( fontFamilyFaces ); + const hasFontStyle = fontStyles?.some( + ( { value: fs } ) => fs === fontStyle ); - const hasFontWeight = fontFamilyFaces?.some( - ( { fontWeight: fw } ) => fw === fontWeight + const hasFontWeight = fontWeights?.some( + ( { value: fw } ) => fw === fontWeight ); + if ( isSystemFont || ( hasFontStyle && hasFontWeight ) ) { setFontAppearance( { fontStyle, From ce081217e29a56d49f9936d9831e137dad37e10f Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Wed, 26 Jun 2024 11:06:59 +0100 Subject: [PATCH 32/39] Improve comments for getFontStylesAndWeights --- .../block-editor/src/utils/get-font-styles-and-weights.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/utils/get-font-styles-and-weights.js b/packages/block-editor/src/utils/get-font-styles-and-weights.js index 36124607f201fd..4889c350057777 100644 --- a/packages/block-editor/src/utils/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/get-font-styles-and-weights.js @@ -104,7 +104,7 @@ export function getFontStylesAndWeights( fontFamilyFaces ) { } if ( isVariableFont ) { - // If the font is a variable font, we don't need to generate the list of font styles and weights. + // If the font is a variable font, use the default list of font styles and weights. return; } @@ -156,7 +156,7 @@ export function getFontStylesAndWeights( fontFamilyFaces ) { fontWeights = FONT_WEIGHTS; } - // Use default font styles and weights if no font family faces are provided. + // Use default styles and weights if there are no available styles or weights from the provided font faces. fontStyles = fontStyles.length === 0 ? FONT_STYLES : fontStyles; fontWeights = fontWeights.length === 0 ? FONT_WEIGHTS : fontWeights; From 541010c61b60f2a32400205b22963981c58b4f9f Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Wed, 26 Jun 2024 11:09:35 +0100 Subject: [PATCH 33/39] Improve test wording --- .../src/utils/test/get-font-styles-and-weights.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/utils/test/get-font-styles-and-weights.js b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js index 897290e1016c47..358f00205ddf2e 100644 --- a/packages/block-editor/src/utils/test/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js @@ -205,7 +205,7 @@ describe( 'getFontStylesAndWeights', () => { } ); } ); - it( 'should return default styles and weights if fontWeight includes a space', () => { + it( 'should return default styles and weights for a variable font', () => { const fontFamilyFaces = [ { fontFamily: 'Inter', @@ -415,7 +415,7 @@ describe( 'getFontStylesAndWeights', () => { } ); } ); - it( 'should return only provided font styles and weights', () => { + it( 'should return specific font styles and weights based on provided font faces', () => { const fontFamilyFaces = [ { fontFamily: 'Piazzolla', From da9f221ffc27ade3985acb1a6c64a34fac1a19a2 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Wed, 26 Jun 2024 17:49:53 +0100 Subject: [PATCH 34/39] Add todo item --- packages/block-editor/src/utils/get-font-styles-and-weights.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-editor/src/utils/get-font-styles-and-weights.js b/packages/block-editor/src/utils/get-font-styles-and-weights.js index 4889c350057777..a74dbc8de3b3ce 100644 --- a/packages/block-editor/src/utils/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/get-font-styles-and-weights.js @@ -105,6 +105,7 @@ export function getFontStylesAndWeights( fontFamilyFaces ) { if ( isVariableFont ) { // If the font is a variable font, use the default list of font styles and weights. + // TODO: Handle variable weights and styles. return; } From d359d9ec7406e124a43d0d1f02c45664ebabfd4b Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Fri, 28 Jun 2024 12:04:15 +0100 Subject: [PATCH 35/39] Include faux bold and italic as options --- .../src/utils/get-font-styles-and-weights.js | 86 +++++++++---------- .../utils/test/get-font-styles-and-weights.js | 42 ++++++++- 2 files changed, 79 insertions(+), 49 deletions(-) diff --git a/packages/block-editor/src/utils/get-font-styles-and-weights.js b/packages/block-editor/src/utils/get-font-styles-and-weights.js index a74dbc8de3b3ce..b92e5385717d47 100644 --- a/packages/block-editor/src/utils/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/get-font-styles-and-weights.js @@ -81,6 +81,7 @@ export function getFontStylesAndWeights( fontFamilyFaces ) { if ( /\s/.test( fontWeight.value.trim() ) ) { isVariableFont = true; fontWeight.value = fontWeight.value.replace( /\s+/g, '-' ); + // TODO: Handle variable weights and styles. } // Create font style and font weight lists without duplicates. @@ -102,57 +103,26 @@ export function getFontStylesAndWeights( fontFamilyFaces ) { fontWeights.push( fontWeight ); } } - - if ( isVariableFont ) { - // If the font is a variable font, use the default list of font styles and weights. - // TODO: Handle variable weights and styles. - return; - } - - // Generate combined font style and weight options for available fonts. - const optionName = - fontStyle.value === 'normal' - ? fontWeight.name - : `${ fontWeight.name } ${ fontStyle.name }`; - - combinedStyleAndWeightOptions.push( { - key: `${ fontStyle.value }-${ fontWeight.value }`, - name: optionName, - style: { - fontStyle: fontStyle.value, - fontWeight: fontWeight.value, - }, - } ); } ); - // Generate combined default options for system fonts and variable fonts. - if ( isSystemFont || isVariableFont ) { - FONT_STYLES.forEach( ( { name: styleName, value: styleValue } ) => { - FONT_WEIGHTS.forEach( - ( { name: weightName, value: weightValue } ) => { - const optionName = - styleValue === 'normal' - ? weightName - : sprintf( - /* translators: 1: Font weight name. 2: Font style name. */ - __( '%1$s %2$s' ), - weightName, - styleName - ); + // If there is no font weight of 700, then include faux bold as an option. + if ( ! fontWeights.some( ( weight ) => weight.value === '700' ) ) { + fontWeights.push( { + name: _x( 'Bold', 'font weight' ), + value: '700', + } ); + } - combinedStyleAndWeightOptions.push( { - key: `${ styleValue }-${ weightValue }`, - name: optionName, - style: { - fontStyle: styleValue, - fontWeight: weightValue, - }, - } ); - } - ); + // If there is no italic font style, then include faux italic as an option. + if ( ! fontStyles.some( ( style ) => style.value === 'italic' ) ) { + fontStyles.push( { + name: _x( 'Italic', 'font style' ), + value: 'italic', } ); + } - // Use default font styles and weights for system and variable fonts. + // Use default font styles and weights for system and variable fonts. + if ( isSystemFont || isVariableFont ) { fontStyles = FONT_STYLES; fontWeights = FONT_WEIGHTS; } @@ -161,6 +131,30 @@ export function getFontStylesAndWeights( fontFamilyFaces ) { fontStyles = fontStyles.length === 0 ? FONT_STYLES : fontStyles; fontWeights = fontWeights.length === 0 ? FONT_WEIGHTS : fontWeights; + // Generate combined font style and weight options for available fonts. + fontStyles.forEach( ( { name: styleName, value: styleValue } ) => { + fontWeights.forEach( ( { name: weightName, value: weightValue } ) => { + const optionName = + styleValue === 'normal' + ? weightName + : sprintf( + /* translators: 1: Font weight name. 2: Font style name. */ + __( '%1$s %2$s' ), + weightName, + styleName + ); + + combinedStyleAndWeightOptions.push( { + key: `${ styleValue }-${ weightValue }`, + name: optionName, + style: { + fontStyle: styleValue, + fontWeight: weightValue, + }, + } ); + } ); + } ); + return { fontStyles, fontWeights, diff --git a/packages/block-editor/src/utils/test/get-font-styles-and-weights.js b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js index 358f00205ddf2e..55731aadd803a7 100644 --- a/packages/block-editor/src/utils/test/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js @@ -466,6 +466,10 @@ describe( 'getFontStylesAndWeights', () => { name: 'Light', value: '300', }, + { + name: 'Bold', + value: '700', + }, ], combinedStyleAndWeightOptions: [ { @@ -485,13 +489,29 @@ describe( 'getFontStylesAndWeights', () => { }, }, { - key: 'italic-300', - name: 'Light Italic', + key: 'normal-300', + name: 'Light', style: { - fontStyle: 'italic', + fontStyle: 'normal', fontWeight: '300', }, }, + { + key: 'normal-700', + name: 'Bold', + style: { + fontStyle: 'normal', + fontWeight: '700', + }, + }, + { + key: 'italic-400', + name: 'Regular Italic', + style: { + fontStyle: 'italic', + fontWeight: '400', + }, + }, { key: 'italic-900', name: 'Black Italic', @@ -500,6 +520,22 @@ describe( 'getFontStylesAndWeights', () => { fontWeight: '900', }, }, + { + key: 'italic-300', + name: 'Light Italic', + style: { + fontStyle: 'italic', + fontWeight: '300', + }, + }, + { + key: 'italic-700', + name: 'Bold Italic', + style: { + fontStyle: 'italic', + fontWeight: '700', + }, + }, ], isSystemFont: false, isVariableFont: false, From 0ece8f5bee1a58ef5521f3c795451911bec1d614 Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Fri, 28 Jun 2024 13:14:02 +0100 Subject: [PATCH 36/39] Handle variable font weights --- .../src/utils/format-font-weight.js | 3 + .../src/utils/get-font-styles-and-weights.js | 46 +++++-- .../src/utils/test/format-font-weight.js | 4 + .../utils/test/get-font-styles-and-weights.js | 130 ++++-------------- 4 files changed, 68 insertions(+), 115 deletions(-) diff --git a/packages/block-editor/src/utils/format-font-weight.js b/packages/block-editor/src/utils/format-font-weight.js index c0c8a865e4c26a..8fc1c9e479a23d 100644 --- a/packages/block-editor/src/utils/format-font-weight.js +++ b/packages/block-editor/src/utils/format-font-weight.js @@ -50,6 +50,9 @@ export function formatFontWeight( fontWeight ) { case '900': name = _x( 'Black', 'font weight' ); break; + case '1000': + name = _x( 'Extra Black', 'font weight' ); + break; default: name = fontWeight; diff --git a/packages/block-editor/src/utils/get-font-styles-and-weights.js b/packages/block-editor/src/utils/get-font-styles-and-weights.js index b92e5385717d47..0fb43178dd51ce 100644 --- a/packages/block-editor/src/utils/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/get-font-styles-and-weights.js @@ -57,6 +57,10 @@ const FONT_WEIGHTS = [ name: _x( 'Black', 'font weight' ), value: '900', }, + { + name: _x( 'Extra Black', 'font weight' ), + value: '1000', + }, ]; /** @@ -74,16 +78,36 @@ export function getFontStylesAndWeights( fontFamilyFaces ) { let isVariableFont = false; fontFamilyFaces?.forEach( ( face ) => { - const fontWeight = formatFontWeight( face.fontWeight ); - const fontStyle = formatFontStyle( face.fontStyle ); - - // Check if font weight includes a space that is not at the start or end of the string. If so, it must be a variable font. e.g. "100 900" - if ( /\s/.test( fontWeight.value.trim() ) ) { + // Check for variable font by looking for a space in the font weight value. e.g. "100 900" + if ( /\s/.test( face.fontWeight.trim() ) ) { isVariableFont = true; - fontWeight.value = fontWeight.value.replace( /\s+/g, '-' ); - // TODO: Handle variable weights and styles. + + // Find font weight start and end values. + let [ startValue, endValue ] = face.fontWeight.split( ' ' ); + startValue = parseInt( startValue.slice( 0, 1 ) ); + if ( endValue === '1000' ) { + endValue = 10; + } else { + endValue = parseInt( endValue.slice( 0, 1 ) ); + } + + // Create font weight options for available variable weights. + for ( let i = startValue; i <= endValue; i++ ) { + const fontWeightValue = `${ i.toString() }00`; + if ( + ! fontWeights.some( + ( weight ) => weight.value === fontWeightValue + ) + ) { + fontWeights.push( formatFontWeight( fontWeightValue ) ); + } + } } + // Format font style and weight values. + const fontWeight = formatFontWeight( face.fontWeight ); + const fontStyle = formatFontStyle( face.fontStyle ); + // Create font style and font weight lists without duplicates. if ( fontStyle ) { if ( @@ -100,7 +124,9 @@ export function getFontStylesAndWeights( fontFamilyFaces ) { ( weight ) => weight.value === fontWeight.value ) ) { - fontWeights.push( fontWeight ); + if ( ! isVariableFont ) { + fontWeights.push( fontWeight ); + } } } } ); @@ -121,8 +147,8 @@ export function getFontStylesAndWeights( fontFamilyFaces ) { } ); } - // Use default font styles and weights for system and variable fonts. - if ( isSystemFont || isVariableFont ) { + // Use default font styles and weights for system fonts. + if ( isSystemFont ) { fontStyles = FONT_STYLES; fontWeights = FONT_WEIGHTS; } diff --git a/packages/block-editor/src/utils/test/format-font-weight.js b/packages/block-editor/src/utils/test/format-font-weight.js index 3e6aedac909348..8830e45532acfe 100644 --- a/packages/block-editor/src/utils/test/format-font-weight.js +++ b/packages/block-editor/src/utils/test/format-font-weight.js @@ -50,6 +50,10 @@ describe( 'formatFontWeight', () => { name: 'Black', value: '900', } ); + expect( formatFontWeight( '1000' ) ).toEqual( { + name: 'Extra Black', + value: '1000', + } ); expect( formatFontWeight( 'normal' ) ).toEqual( { name: 'Regular', value: 'normal', diff --git a/packages/block-editor/src/utils/test/get-font-styles-and-weights.js b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js index 55731aadd803a7..2510bc417c34e2 100644 --- a/packages/block-editor/src/utils/test/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js @@ -53,6 +53,10 @@ describe( 'getFontStylesAndWeights', () => { name: 'Black', value: '900', }, + { + name: 'Extra Black', + value: '1000', + }, ], combinedStyleAndWeightOptions: [ { @@ -127,6 +131,14 @@ describe( 'getFontStylesAndWeights', () => { fontWeight: '900', }, }, + { + key: 'normal-1000', + name: 'Extra Black', + style: { + fontStyle: 'normal', + fontWeight: '1000', + }, + }, { key: 'italic-100', name: 'Thin Italic', @@ -199,19 +211,27 @@ describe( 'getFontStylesAndWeights', () => { fontWeight: '900', }, }, + { + key: 'italic-1000', + name: 'Extra Black Italic', + style: { + fontStyle: 'italic', + fontWeight: '1000', + }, + }, ], isSystemFont: true, isVariableFont: false, } ); } ); - it( 'should return default styles and weights for a variable font', () => { + it( 'should return available styles and weights for a variable font', () => { const fontFamilyFaces = [ { - fontFamily: 'Inter', + fontFamily: 'AR One Sans', fontStyle: 'normal', - fontWeight: '100 900', - src: 'http://www.wordpress.org/wp-content/uploads/fonts/Inter-VariableFont_slntwght.ttf', + fontWeight: '400 700', + src: 'http://www.wordpress.org/wp-content/uploads/fonts/AROneSans-VariableFont_ARRRwght.ttf', }, ]; @@ -227,18 +247,6 @@ describe( 'getFontStylesAndWeights', () => { }, ], fontWeights: [ - { - name: 'Thin', - value: '100', - }, - { - name: 'Extra Light', - value: '200', - }, - { - name: 'Light', - value: '300', - }, { name: 'Regular', value: '400', @@ -255,40 +263,8 @@ describe( 'getFontStylesAndWeights', () => { name: 'Bold', value: '700', }, - { - name: 'Extra Bold', - value: '800', - }, - { - name: 'Black', - value: '900', - }, ], combinedStyleAndWeightOptions: [ - { - key: 'normal-100', - name: 'Thin', - style: { - fontStyle: 'normal', - fontWeight: '100', - }, - }, - { - key: 'normal-200', - name: 'Extra Light', - style: { - fontStyle: 'normal', - fontWeight: '200', - }, - }, - { - key: 'normal-300', - name: 'Light', - style: { - fontStyle: 'normal', - fontWeight: '300', - }, - }, { key: 'normal-400', name: 'Regular', @@ -321,46 +297,6 @@ describe( 'getFontStylesAndWeights', () => { fontWeight: '700', }, }, - { - key: 'normal-800', - name: 'Extra Bold', - style: { - fontStyle: 'normal', - fontWeight: '800', - }, - }, - { - key: 'normal-900', - name: 'Black', - style: { - fontStyle: 'normal', - fontWeight: '900', - }, - }, - { - key: 'italic-100', - name: 'Thin Italic', - style: { - fontStyle: 'italic', - fontWeight: '100', - }, - }, - { - key: 'italic-200', - name: 'Extra Light Italic', - style: { - fontStyle: 'italic', - fontWeight: '200', - }, - }, - { - key: 'italic-300', - name: 'Light Italic', - style: { - fontStyle: 'italic', - fontWeight: '300', - }, - }, { key: 'italic-400', name: 'Regular Italic', @@ -393,29 +329,13 @@ describe( 'getFontStylesAndWeights', () => { fontWeight: '700', }, }, - { - key: 'italic-800', - name: 'Extra Bold Italic', - style: { - fontStyle: 'italic', - fontWeight: '800', - }, - }, - { - key: 'italic-900', - name: 'Black Italic', - style: { - fontStyle: 'italic', - fontWeight: '900', - }, - }, ], isSystemFont: false, isVariableFont: true, } ); } ); - it( 'should return specific font styles and weights based on provided font faces', () => { + it( 'should return available styles and weights for a regular font', () => { const fontFamilyFaces = [ { fontFamily: 'Piazzolla', From ad00060e33fcdf4690aa15227d738cc0e6a24c3f Mon Sep 17 00:00:00 2001 From: Sarah Norris Date: Fri, 28 Jun 2024 14:31:03 +0100 Subject: [PATCH 37/39] Try to set the nearest available font weight --- .../global-styles/test/typography-utils.js | 56 +++++++++++++++++++ .../global-styles/typography-panel.js | 19 ++++++- .../global-styles/typography-utils.js | 37 ++++++++++++ 3 files changed, 110 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/test/typography-utils.js b/packages/block-editor/src/components/global-styles/test/typography-utils.js index 7860e27d1454f4..115de8cdf2563d 100644 --- a/packages/block-editor/src/components/global-styles/test/typography-utils.js +++ b/packages/block-editor/src/components/global-styles/test/typography-utils.js @@ -5,6 +5,7 @@ import { getTypographyFontSizeValue, getFluidTypographyOptionsFromSettings, getMergedFontFamiliesAndFontFamilyFaces, + findNearestFontWeight, } from '../typography-utils'; describe( 'typography utils', () => { @@ -895,6 +896,61 @@ describe( 'typography utils', () => { } ); } ); + describe( 'findNearestFontWeight', () => { + [ + { + message: + 'should return empty string when newFontWeightValue is `undefined`', + availableFontWeights: undefined, + newFontWeightValue: undefined, + expected: '', + }, + { + message: + 'should return newFontWeightValue value when availableFontWeights is empty', + availableFontWeights: [], + newFontWeightValue: '300', + expected: '300', + }, + { + message: 'should return correct nearest higher font weight', + availableFontWeights: [ + { name: 'Regular', value: '400' }, + { name: 'Bold', value: '700' }, + { name: 'Black', value: '900' }, + ], + newFontWeightValue: '300', + expected: '400', + }, + { + message: 'should return correct nearest lower font weight', + availableFontWeights: [ + { name: 'Thin', value: '100' }, + { name: 'Light', value: '300' }, + { name: 'Regular', value: '400' }, + ], + newFontWeightValue: '900', + expected: '400', + }, + ].forEach( + ( { + message, + availableFontWeights, + newFontWeightValue, + expected, + } ) => { + it( `${ message }`, () => { + expect( + findNearestFontWeight( + availableFontWeights, + newFontWeightValue + ) + ).toEqual( expected ); + } ); + } + ); + } ); + describe( 'typography utils', () => { [ { diff --git a/packages/block-editor/src/components/global-styles/typography-panel.js b/packages/block-editor/src/components/global-styles/typography-panel.js index 30d7ab0d3e64eb..62d0f49173ad74 100644 --- a/packages/block-editor/src/components/global-styles/typography-panel.js +++ b/packages/block-editor/src/components/global-styles/typography-panel.js @@ -23,7 +23,10 @@ import TextDecorationControl from '../text-decoration-control'; import WritingModeControl from '../writing-mode-control'; import { getValueFromVariable, TOOLSPANEL_DROPDOWNMENU_PROPS } from './utils'; import { setImmutably } from '../../utils/object'; -import { getMergedFontFamiliesAndFontFamilyFaces } from './typography-utils'; +import { + getMergedFontFamiliesAndFontFamilyFaces, + findNearestFontWeight, +} from './typography-utils'; import { getFontStylesAndWeights } from '../../utils/get-font-styles-and-weights'; const MIN_TEXT_COLUMNS = 1; @@ -262,12 +265,24 @@ export default function TypographyPanel( { ( { value: fw } ) => fw === fontWeight ); + // Try to set nearest available font weight + if ( ! hasFontWeight && fontWeight ) { + setFontAppearance( { + fontStyle, + fontWeight: findNearestFontWeight( fontWeights, fontWeight ), + } ); + } + + // Set the same weight and style values if the font family is a system font or if both are the same if ( isSystemFont || ( hasFontStyle && hasFontWeight ) ) { setFontAppearance( { fontStyle, fontWeight, } ); - } else { + } + + // Reset font appearance if the font family does not have the selected font style + if ( ! hasFontStyle ) { resetFontAppearance(); } }, [ fontFamily ] ); diff --git a/packages/block-editor/src/components/global-styles/typography-utils.js b/packages/block-editor/src/components/global-styles/typography-utils.js index f12f761152578b..0d4c1b29b8b662 100644 --- a/packages/block-editor/src/components/global-styles/typography-utils.js +++ b/packages/block-editor/src/components/global-styles/typography-utils.js @@ -148,3 +148,40 @@ export function getMergedFontFamiliesAndFontFamilyFaces( return { fontFamilies, fontFamilyFaces }; } + +/** + * Returns the nearest font weight value from the available font weight list based on the new font weight. + * The nearest font weight is the one with the smallest difference from the new font weight. + * + * @param {Array} availableFontWeights Array of available font weights + * @param {string} newFontWeightValue New font weight value + * @return {string} Nearest font weight + */ + +export function findNearestFontWeight( + availableFontWeights, + newFontWeightValue +) { + if ( ! newFontWeightValue || typeof newFontWeightValue !== 'string' ) { + return ''; + } + + if ( ! availableFontWeights || availableFontWeights.length === 0 ) { + return newFontWeightValue; + } + + const nearestFontWeight = availableFontWeights?.reduce( + ( nearest, { value: fw } ) => { + const currentDiff = Math.abs( + parseInt( fw ) - parseInt( newFontWeightValue ) + ); + const nearestDiff = Math.abs( + parseInt( nearest ) - parseInt( newFontWeightValue ) + ); + return currentDiff < nearestDiff ? fw : nearest; + }, + availableFontWeights[ 0 ]?.value + ); + + return nearestFontWeight; +} From d7bba77c9f0368a3b4176d3d87389b65eb86e65e Mon Sep 17 00:00:00 2001 From: Grant Kinney Date: Fri, 28 Jun 2024 14:12:29 -0500 Subject: [PATCH 38/39] Only adds faux bold if a weight of 600 or above is not already available --- .../block-editor/src/utils/get-font-styles-and-weights.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/utils/get-font-styles-and-weights.js b/packages/block-editor/src/utils/get-font-styles-and-weights.js index 0fb43178dd51ce..88b40a5aacfeb5 100644 --- a/packages/block-editor/src/utils/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/get-font-styles-and-weights.js @@ -131,8 +131,8 @@ export function getFontStylesAndWeights( fontFamilyFaces ) { } } ); - // If there is no font weight of 700, then include faux bold as an option. - if ( ! fontWeights.some( ( weight ) => weight.value === '700' ) ) { + // If there is no font weight of 600 or above, then include faux bold as an option. + if ( ! fontWeights.some( ( weight ) => weight.value >= '600' ) ) { fontWeights.push( { name: _x( 'Bold', 'font weight' ), value: '700', From f6aef40d203bf16cc785fe87e41462e03cd46938 Mon Sep 17 00:00:00 2001 From: Grant Kinney Date: Fri, 28 Jun 2024 14:22:16 -0500 Subject: [PATCH 39/39] Updates tests with new faux bold logic --- .../utils/test/get-font-styles-and-weights.js | 73 ++++++++++++++++--- 1 file changed, 61 insertions(+), 12 deletions(-) diff --git a/packages/block-editor/src/utils/test/get-font-styles-and-weights.js b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js index 2510bc417c34e2..ffc1a635aa1fb1 100644 --- a/packages/block-editor/src/utils/test/get-font-styles-and-weights.js +++ b/packages/block-editor/src/utils/test/get-font-styles-and-weights.js @@ -386,10 +386,6 @@ describe( 'getFontStylesAndWeights', () => { name: 'Light', value: '300', }, - { - name: 'Bold', - value: '700', - }, ], combinedStyleAndWeightOptions: [ { @@ -416,14 +412,6 @@ describe( 'getFontStylesAndWeights', () => { fontWeight: '300', }, }, - { - key: 'normal-700', - name: 'Bold', - style: { - fontStyle: 'normal', - fontWeight: '700', - }, - }, { key: 'italic-400', name: 'Regular Italic', @@ -448,6 +436,67 @@ describe( 'getFontStylesAndWeights', () => { fontWeight: '300', }, }, + ], + isSystemFont: false, + isVariableFont: false, + } ); + } ); + + it( 'should return available styles and weights for a regular font with faux bold added', () => { + const fontFamilyFaces = [ + { + fontFamily: 'Piazzolla', + fontStyle: 'normal', + fontWeight: '400', + src: 'http://www.wordpress.org/wp-content/uploads/fonts/N0b52SlTPu5rIkWIZjVKKtYtfxYqZ4RJBFzFfYUjkSDdlqZgy7LYxnL31AHfAAy5.woff2', + }, + ]; + expect( getFontStylesAndWeights( fontFamilyFaces ) ).toEqual( { + fontStyles: [ + { + name: 'Regular', + value: 'normal', + }, + { + name: 'Italic', + value: 'italic', + }, + ], + fontWeights: [ + { + name: 'Regular', + value: '400', + }, + { + name: 'Bold', + value: '700', + }, + ], + combinedStyleAndWeightOptions: [ + { + key: 'normal-400', + name: 'Regular', + style: { + fontStyle: 'normal', + fontWeight: '400', + }, + }, + { + key: 'normal-700', + name: 'Bold', + style: { + fontStyle: 'normal', + fontWeight: '700', + }, + }, + { + key: 'italic-400', + name: 'Regular Italic', + style: { + fontStyle: 'italic', + fontWeight: '400', + }, + }, { key: 'italic-700', name: 'Bold Italic',