Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Cherry Pick changes for WordPress 6.5 RC3 #59949

Merged
merged 9 commits into from
Mar 18, 2024
7 changes: 4 additions & 3 deletions packages/block-library/src/heading/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,16 @@ export const settings = {
const { content, level } = attributes;

const customName = attributes?.metadata?.name;
const hasContent = content?.length > 0;

// In the list view, use the block's content as the label.
// If the content is empty, fall back to the default label.
if ( context === 'list-view' && ( customName || content ) ) {
return attributes?.metadata?.name || content;
if ( context === 'list-view' && ( customName || hasContent ) ) {
return customName || content;
}

if ( context === 'accessibility' ) {
return ! content || content.length === 0
return ! hasContent
? sprintf(
/* translators: accessibility text. %s: heading level. */
__( 'Level %s. Empty.' ),
Expand Down
1 change: 1 addition & 0 deletions packages/block-library/src/navigation-link/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ export default function NavigationLinkEdit( {
isKeyboardEvent.primary( event, 'k' ) ||
( ( ! url || isDraft || isInvalid ) && event.keyCode === ENTER )
) {
event.preventDefault();
setIsLinkOpen( true );
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/block-library/src/navigation-submenu/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ export default function NavigationSubmenuEdit( {

function onKeyDown( event ) {
if ( isKeyboardEvent.primary( event, 'k' ) ) {
event.preventDefault();
setIsLinkOpen( true );
}
}
Expand Down
98 changes: 48 additions & 50 deletions packages/block-library/src/navigation/edit/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -342,16 +342,7 @@ function Navigation( {
const [ detectedOverlayColor, setDetectedOverlayColor ] = useState();

const onSelectClassicMenu = async ( classicMenu ) => {
const navMenu = await convertClassicMenu(
classicMenu.id,
classicMenu.name,
'draft'
);
if ( navMenu ) {
handleUpdateMenu( navMenu.id, {
focusNavigationBlock: true,
} );
}
return convertClassicMenu( classicMenu.id, classicMenu.name, 'draft' );
};

const onSelectNavigationMenu = ( menuId ) => {
Expand Down Expand Up @@ -402,6 +393,9 @@ function Navigation( {
showClassicMenuConversionNotice(
__( 'Classic menu imported successfully.' )
);
handleUpdateMenu( createNavigationMenuPost?.id, {
focusNavigationBlock: true,
} );
}

if ( classicMenuConversionStatus === CLASSIC_MENU_CONVERSION_ERROR ) {
Expand All @@ -414,6 +408,8 @@ function Navigation( {
classicMenuConversionError,
hideClassicMenuConversionNotice,
showClassicMenuConversionNotice,
createNavigationMenuPost?.id,
handleUpdateMenu,
] );

useEffect( () => {
Expand Down Expand Up @@ -866,50 +862,52 @@ function Navigation( {
</InspectorControls>
) }

{ isLoading && (
<TagName { ...blockProps }>
<TagName
{ ...blockProps }
aria-describedby={
! isPlaceholder && ! isLoading
? accessibleDescriptionId
: undefined
}
>
{ isLoading && (
<div className="wp-block-navigation__loading-indicator-container">
<Spinner className="wp-block-navigation__loading-indicator" />
</div>
</TagName>
) }
) }

{ ! isLoading && (
<TagName
{ ...blockProps }
aria-describedby={
! isPlaceholder
? accessibleDescriptionId
: undefined
}
>
<AccessibleMenuDescription
id={ accessibleDescriptionId }
/>
<ResponsiveWrapper
id={ clientId }
onToggle={ setResponsiveMenuVisibility }
hasIcon={ hasIcon }
icon={ icon }
isOpen={ isResponsiveMenuOpen }
isResponsive={ isResponsive }
isHiddenByDefault={ 'always' === overlayMenu }
overlayBackgroundColor={ overlayBackgroundColor }
overlayTextColor={ overlayTextColor }
>
{ isEntityAvailable && (
<NavigationInnerBlocks
clientId={ clientId }
hasCustomPlaceholder={
!! CustomPlaceholder
}
templateLock={ templateLock }
orientation={ orientation }
/>
) }
</ResponsiveWrapper>
</TagName>
) }
{ ! isLoading && (
<>
<AccessibleMenuDescription
id={ accessibleDescriptionId }
/>
<ResponsiveWrapper
id={ clientId }
onToggle={ setResponsiveMenuVisibility }
hasIcon={ hasIcon }
icon={ icon }
isOpen={ isResponsiveMenuOpen }
isResponsive={ isResponsive }
isHiddenByDefault={ 'always' === overlayMenu }
overlayBackgroundColor={
overlayBackgroundColor
}
overlayTextColor={ overlayTextColor }
>
{ isEntityAvailable && (
<NavigationInnerBlocks
clientId={ clientId }
hasCustomPlaceholder={
!! CustomPlaceholder
}
templateLock={ templateLock }
orientation={ orientation }
/>
) }
</ResponsiveWrapper>
</>
) }
</TagName>
</RecursionProvider>
</EntityProvider>
);
Expand Down
12 changes: 10 additions & 2 deletions packages/block-library/src/navigation/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,9 @@ private static function get_markup_for_inner_block( $inner_block ) {
if ( static::does_block_need_a_list_item_wrapper( $inner_block ) ) {
return '<li class="wp-block-navigation-item">' . $inner_block_content . '</li>';
}

return $inner_block_content;
}

return $inner_block_content;
}

/**
Expand Down Expand Up @@ -1464,6 +1464,14 @@ function block_core_navigation_set_ignored_hooked_blocks_metadata( $inner_blocks
* @return stdClass The updated post object.
*/
function block_core_navigation_update_ignore_hooked_blocks_meta( $post ) {
/*
* In this scenario the user has likely tried to create a navigation via the REST API.
* In which case we won't have a post ID to work with and store meta against.
*/
if ( empty( $post->ID ) ) {
return $post;
}

/*
* We run the Block Hooks mechanism to inject the `metadata.ignoredHookedBlocks` attribute into
* all anchor blocks. For the root level, we create a mock Navigation and extract them from there.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 2,
"name": "test/deferred-store",
"title": "E2E Interactivity tests - deferred store",
"category": "text",
"icon": "heart",
"description": "",
"supports": {
"interactivity": true
},
"textdomain": "e2e-interactivity",
"viewScriptModule": "file:./view.js",
"render": "file:./render.php"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php
/**
* HTML for testing scope restoration with generators.
*
* @package gutenberg-test-interactive-blocks
*/
?>

<div
data-wp-interactive="test/deferred-store"
<?php echo wp_interactivity_data_wp_context( array( 'text' => '!dlrow ,olleH' ) ); ?>
>
<span data-wp-text="state.reversedText" data-testid="result"></span>
<span data-wp-text="state.reversedTextGetter" data-testid="result-getter"></span>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?php return array( 'dependencies' => array( '@wordpress/interactivity' ) );
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* WordPress dependencies
*/
import { store, getContext } from '@wordpress/interactivity';

document.addEventListener( 'DOMContentLoaded', () => {
setTimeout( () => {
store( 'test/deferred-store', {
state: {
reversedText() {
return [ ...getContext().text ].reverse().join( '' );
},

get reversedTextGetter() {
return [ ...getContext().text ].reverse().join( '' );
},
},
} );
}, 50 );
} );
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
/**
* HTML for testing the directive `data-wp-bind`.
* HTML for testing the `store` function.
*
* @package gutenberg-test-interactive-blocks
*/
Expand All @@ -9,6 +9,7 @@
?>

<div data-wp-interactive="test/store">
<div data-wp-text="state.0" data-testid="state-0"></div>
<div
data-testid="non-plain object"
data-wp-text="state.isNotProxified"
Expand Down
11 changes: 7 additions & 4 deletions packages/e2e-tests/plugins/interactive-blocks/store/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,21 @@
*/
import { store, getElement } from '@wordpress/interactivity';

// A non-object state should never be allowed.
store( 'test/store', { state: [ 'wrong' ] } );

const { state } = store( 'test/store', {
state: {
0: 'right',
get isNotProxified() {
const { ref } = getElement();
return state.elementRef === ref;
}
},
},
callbacks: {
init() {
const { ref } = getElement();
state.elementRef = ref; // HTMLElement
}
}
} )
},
},
} );
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,22 @@ function FontLibraryProvider( { children } ) {
...alreadyInstalledFontFaces,
];
fontFamiliesToActivate.push( fontFamilyToInstall );
} else if ( isANewFontFamily ) {
// If the font family is new, delete it to avoid having font families without font faces.
}

// If it's a system font but was installed successfully, activate it.
if (
installedFontFamily &&
! fontFamilyToInstall?.fontFace?.length
) {
fontFamiliesToActivate.push( installedFontFamily );
}

// If the font family is new and is not a system font, delete it to avoid having font families without font faces.
if (
isANewFontFamily &&
fontFamilyToInstall?.fontFace?.length > 0 &&
sucessfullyInstalledFontFaces?.length === 0
) {
await fetchUninstallFontFamily( installedFontFamily.id );
}

Expand Down Expand Up @@ -411,15 +425,15 @@ function FontLibraryProvider( { children } ) {

const isFaceActivated = isFontActivated(
font.slug,
face.fontStyle,
face.fontWeight,
face?.fontStyle,
face?.fontWeight,
font.source
);

if ( isFaceActivated ) {
loadFontFaceInBrowser(
face,
getDisplaySrcFromFontFace( face.src ),
getDisplaySrcFromFontFace( face?.src ),
'all'
);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,9 @@ export function unloadFontFaceInBrowser( fontFace, removeFrom = 'all' ) {
const unloadFontFace = ( fonts ) => {
fonts.forEach( ( f ) => {
if (
f.family === formatFontFaceName( fontFace.fontFamily ) &&
f.weight === fontFace.fontWeight &&
f.style === fontFace.fontStyle
f.family === formatFontFaceName( fontFace?.fontFamily ) &&
f.weight === fontFace?.fontWeight &&
f.style === fontFace?.fontStyle
) {
fonts.delete( f );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ export function formatFontFamily( input ) {
* formatFontFaceName(", 'Open Sans', 'Helvetica Neue', sans-serif") => "Open Sans"
*/
export function formatFontFaceName( input ) {
if ( ! input ) {
return '';
}

let output = input.trim();
if ( output.includes( ',' ) ) {
output = output
Expand Down
2 changes: 2 additions & 0 deletions packages/interactivity/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

### Bug Fixes

- Prevent non-objects from being set in store state. ([#59886](https://github.com/WordPress/gutenberg/pull/59886))
- Ensure that stores are available for subscription before hydration. ([#59842](https://github.com/WordPress/gutenberg/pull/59842))
- Ensure scope is restored when catching exceptions thrown in async generator actions. ([#59708](https://github.com/WordPress/gutenberg/pull/59708))

## 5.2.0 (2024-03-06)
Expand Down
10 changes: 8 additions & 2 deletions packages/interactivity/src/hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import type { VNode, Context, RefObject } from 'preact';
/**
* Internal dependencies
*/
import { stores } from './store';
import { store, stores, universalUnlock } from './store';
interface DirectiveEntry {
value: string | Object;
namespace: string;
Expand Down Expand Up @@ -259,8 +259,14 @@ export const directive = (

// Resolve the path to some property of the store object.
const resolve = ( path, namespace ) => {
let resolvedStore = stores.get( namespace );
if ( typeof resolvedStore === 'undefined' ) {
resolvedStore = store( namespace, undefined, {
lock: universalUnlock,
} );
}
let current = {
...stores.get( namespace ),
...resolvedStore,
context: getScope().context[ namespace ],
};
path.split( '.' ).forEach( ( p ) => ( current = current[ p ] ) );
Expand Down
Loading
Loading