diff --git a/docs/reference-guides/data/data-core-block-editor.md b/docs/reference-guides/data/data-core-block-editor.md
index 38a93552bcbef..a0acea3ced683 100644
--- a/docs/reference-guides/data/data-core-block-editor.md
+++ b/docs/reference-guides/data/data-core-block-editor.md
@@ -846,6 +846,10 @@ _Returns_
- `string|false`: Block Template Lock
+### getUnsyncedPatterns
+
+Undocumented declaration.
+
### hasBlockMovingClientId
Returns whether block moving mode is enabled.
diff --git a/docs/reference-guides/data/data-core-blocks.md b/docs/reference-guides/data/data-core-blocks.md
index 084c9c1d7a5fb..0c3c95beb1f1b 100644
--- a/docs/reference-guides/data/data-core-blocks.md
+++ b/docs/reference-guides/data/data-core-blocks.md
@@ -246,6 +246,14 @@ _Returns_
- `(WPBlockVariation[]|void)`: Block variations.
+### getBootstrappedBlockType
+
+Undocumented declaration.
+
+### getBootstrappedBlockTypes
+
+Undocumented declaration.
+
### getCategories
Returns all the available block categories.
diff --git a/lib/blocks.php b/lib/blocks.php
index 698b5d6873748..fc20c98d37f6e 100644
--- a/lib/blocks.php
+++ b/lib/blocks.php
@@ -227,6 +227,13 @@ function gutenberg_deregister_core_block_and_assets( $block_name ) {
}
}
}
+ if ( ! empty( $block_type->editor_script_handles ) ) {
+ foreach ( $block_type->editor_script_handles as $editor_script_handle ) {
+ if ( str_starts_with( $editor_script_handle, 'wp-block-' ) ) {
+ wp_deregister_script( $editor_script_handle );
+ }
+ }
+ }
$registry->unregister( $block_name );
}
}
diff --git a/lib/init.php b/lib/init.php
index 71b6a276c60f3..3fa7fdbaece97 100644
--- a/lib/init.php
+++ b/lib/init.php
@@ -57,3 +57,55 @@ function gutenberg_menu() {
);
}
add_action( 'admin_menu', 'gutenberg_menu', 9 );
+
+// disable loading and enqueuing block editor scripts and styles
+add_filter( 'should_load_block_editor_scripts_and_styles', '__return_false', 11 );
+
+function get_block_importmap() {
+ $block_registry = WP_Block_Type_Registry::get_instance();
+ $scripts = wp_scripts();
+ $styles = wp_styles();
+ $blocks = array();
+
+ foreach ( $block_registry->get_all_registered() as $block_name => $block_type ) {
+ $imports = array();
+ if ( isset( $block_type->editor_script_handles ) ) {
+ foreach ( $block_type->editor_script_handles as $handle ) {
+ $spec = $scripts->registered[ $handle ];
+ $imports[] = array(
+ 'type' => 'script',
+ 'handle' => $spec->handle,
+ 'src' => $spec->src,
+ 'ver' => $spec->ver
+ );
+ }
+ }
+ if ( isset( $block_type->editor_style_handles ) ) {
+ foreach ( $block_type->editor_style_handles as $handle ) {
+ if ( ! isset( $styles->registered[ $handle ] ) ) {
+ continue;
+ }
+ $spec = $styles->registered[ $handle ];
+ $imports[] = array(
+ 'type' => 'style',
+ 'handle' => $spec->handle,
+ 'src' => $spec->src,
+ 'ver' => $spec->ver
+ );
+ }
+ }
+ if ( ! empty( $imports ) ) {
+ $blocks[ $block_name ] = $imports;
+ }
+ }
+
+ return $blocks;
+}
+
+function emit_importmap() {
+ wp_register_script( 'wp-importmap', '');
+ wp_add_inline_script( 'wp-importmap', 'wp.importmap = ' . wp_json_encode( get_block_importmap() ) . ';' );
+ wp_enqueue_script('wp-importmap');
+}
+
+add_action( 'enqueue_block_editor_assets', 'emit_importmap' );
\ No newline at end of file
diff --git a/packages/block-editor/src/autocompleters/block.js b/packages/block-editor/src/autocompleters/block.js
index bc06c9de5aaaf..e3539d7ba2e76 100644
--- a/packages/block-editor/src/autocompleters/block.js
+++ b/packages/block-editor/src/autocompleters/block.js
@@ -116,7 +116,7 @@ function createBlockCompleter() {
allowContext( before, after ) {
return ! ( /\S/.test( before ) || /\S/.test( after ) );
},
- getOptionCompletion( inserterItem ) {
+ async getOptionCompletion( inserterItem ) {
const {
name,
initialAttributes,
@@ -124,12 +124,11 @@ function createBlockCompleter() {
syncStatus,
content,
} = inserterItem;
-
return {
action: 'replace',
value:
syncStatus === 'unsynced'
- ? parse( content, {
+ ? await parse( content, {
__unstableSkipMigrationLogs: true,
} )
: createBlock(
diff --git a/packages/block-editor/src/components/block-actions/index.js b/packages/block-editor/src/components/block-actions/index.js
index 5d942d2b25c70..2f82cda208619 100644
--- a/packages/block-editor/src/components/block-actions/index.js
+++ b/packages/block-editor/src/components/block-actions/index.js
@@ -103,7 +103,7 @@ export default function BlockActions( {
selectBlock( clientIds[ 0 ] );
setBlockMovingClientId( clientIds[ 0 ] );
},
- onGroup() {
+ async onGroup() {
if ( ! blocks.length ) {
return;
}
@@ -111,7 +111,10 @@ export default function BlockActions( {
const groupingBlockName = getGroupingBlockName();
// Activate the `transform` on `core/group` which does the conversion.
- const newBlocks = switchToBlockType( blocks, groupingBlockName );
+ const newBlocks = await switchToBlockType(
+ blocks,
+ groupingBlockName
+ );
if ( ! newBlocks ) {
return;
diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js
index b38dcf3ef1f2e..d5c9b41987967 100644
--- a/packages/block-editor/src/components/block-list/block.js
+++ b/packages/block-editor/src/components/block-list/block.js
@@ -391,7 +391,7 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => {
) {
removeBlock( _clientId );
} else {
- registry.batch( () => {
+ registry.batch( async () => {
if (
canInsertBlockType(
getBlockName( firstClientId ),
@@ -405,7 +405,7 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => {
getBlockIndex( _clientId )
);
} else {
- const replacement = switchToBlockType(
+ const replacement = await switchToBlockType(
getBlock( firstClientId ),
getDefaultBlockName()
);
diff --git a/packages/block-editor/src/components/block-list/block.native.js b/packages/block-editor/src/components/block-list/block.native.js
index 70a66c445f58f..de7e9f2181574 100644
--- a/packages/block-editor/src/components/block-list/block.native.js
+++ b/packages/block-editor/src/components/block-list/block.native.js
@@ -482,7 +482,7 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => {
) {
removeBlock( _clientId );
} else {
- registry.batch( () => {
+ registry.batch( async () => {
if (
canInsertBlockType(
getBlockName( firstClientId ),
@@ -496,7 +496,7 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => {
getBlockIndex( _clientId )
);
} else {
- const replacement = switchToBlockType(
+ const replacement = await switchToBlockType(
getBlock( firstClientId ),
getDefaultBlockName()
);
diff --git a/packages/block-editor/src/components/block-styles/use-styles-for-block.js b/packages/block-editor/src/components/block-styles/use-styles-for-block.js
index 6d73dca557b05..d89557be05864 100644
--- a/packages/block-editor/src/components/block-styles/use-styles-for-block.js
+++ b/packages/block-editor/src/components/block-styles/use-styles-for-block.js
@@ -24,20 +24,13 @@ import { store as blockEditorStore } from '../../store';
*/
function useGenericPreviewBlock( block, type ) {
return useMemo( () => {
- const example = type?.example;
- const blockName = type?.name;
-
- if ( example && blockName ) {
- return getBlockFromExample( blockName, {
- attributes: example.attributes,
- innerBlocks: example.innerBlocks,
- } );
+ if ( type && type.blockName && type.example ) {
+ return getBlockFromExample( type.blockName, type.example );
}
-
if ( block ) {
return cloneBlock( block );
}
- }, [ type?.example ? block?.name : block, type ] );
+ }, [ type, type?.example ? block?.name : block ] );
}
/**
diff --git a/packages/block-editor/src/components/block-switcher/block-transformations-menu.js b/packages/block-editor/src/components/block-switcher/block-transformations-menu.js
index 033201d7facad..f89b1605391bc 100644
--- a/packages/block-editor/src/components/block-switcher/block-transformations-menu.js
+++ b/packages/block-editor/src/components/block-switcher/block-transformations-menu.js
@@ -7,7 +7,7 @@ import {
getBlockMenuDefaultClassName,
switchToBlockType,
} from '@wordpress/blocks';
-import { useState, useMemo } from '@wordpress/element';
+import { useEffect, useState, useMemo } from '@wordpress/element';
/**
* Internal dependencies
@@ -63,6 +63,21 @@ function useGroupedTransforms( possibleBlockTransformations ) {
return transformations;
}
+function Preview( { blocks, transformName } ) {
+ const [ switched, setSwitched ] = useState( null );
+ useEffect( () => {
+ switchToBlockType( blocks, transformName ).then( ( result ) =>
+ setSwitched( result )
+ );
+ }, [ blocks, transformName ] );
+
+ if ( ! switched ) {
+ return null;
+ }
+
+ return ;
+}
+
const BlockTransformationsMenu = ( {
className,
possibleBlockTransformations,
@@ -91,11 +106,10 @@ const BlockTransformationsMenu = ( {
<>
{ hoveredTransformItemName && (
-
) }
{ !! possibleBlockVariationTransformations?.length && (
diff --git a/packages/block-editor/src/components/block-switcher/block-transformations-menu.native.js b/packages/block-editor/src/components/block-switcher/block-transformations-menu.native.js
index 33952378f601f..a9ae04bcf90b3 100644
--- a/packages/block-editor/src/components/block-switcher/block-transformations-menu.native.js
+++ b/packages/block-editor/src/components/block-switcher/block-transformations-menu.native.js
@@ -55,10 +55,10 @@ const BlockTransformationsMenu = ( {
const getAnchor = () =>
anchorNodeRef ? findNodeHandle( anchorNodeRef ) : undefined;
- function onPickerSelect( value ) {
+ async function onPickerSelect( value ) {
replaceBlocks(
selectedBlockClientId,
- switchToBlockType( selectedBlock, value )
+ await switchToBlockType( selectedBlock, value )
);
const selectedItem = pickerOptions().find(
diff --git a/packages/block-editor/src/components/block-switcher/index.js b/packages/block-editor/src/components/block-switcher/index.js
index 0960dc87eaa49..136e987382e4d 100644
--- a/packages/block-editor/src/components/block-switcher/index.js
+++ b/packages/block-editor/src/components/block-switcher/index.js
@@ -13,9 +13,11 @@ import {
store as blocksStore,
isReusableBlock,
isTemplatePart,
+ getTransformItemsForBlocks,
} from '@wordpress/blocks';
import { useSelect, useDispatch } from '@wordpress/data';
import { copy } from '@wordpress/icons';
+import { useState, useEffect } from '@wordpress/element';
/**
* Internal dependencies
@@ -33,56 +35,58 @@ export const BlockSwitcherDropdownMenu = ( { clientIds, blocks } ) => {
const { replaceBlocks, multiSelect, updateBlockAttributes } =
useDispatch( blockEditorStore );
const blockInformation = useBlockDisplayInformation( blocks[ 0 ].clientId );
- const {
- possibleBlockTransformations,
- canRemove,
- hasBlockStyles,
- icon,
- patterns,
- } = useSelect(
- ( select ) => {
- const {
- getBlockRootClientId,
- getBlockTransformItems,
- __experimentalGetPatternTransformItems,
- canRemoveBlocks,
- } = select( blockEditorStore );
- const { getBlockStyles, getBlockType } = select( blocksStore );
- const rootClientId = getBlockRootClientId(
- Array.isArray( clientIds ) ? clientIds[ 0 ] : clientIds
- );
- const [ { name: firstBlockName } ] = blocks;
- const _isSingleBlockSelected = blocks.length === 1;
- const styles =
- _isSingleBlockSelected && getBlockStyles( firstBlockName );
- let _icon;
- if ( _isSingleBlockSelected ) {
- _icon = blockInformation?.icon; // Take into account active block variations.
- } else {
- const isSelectionOfSameType =
- new Set( blocks.map( ( { name } ) => name ) ).size === 1;
- // When selection consists of blocks of multiple types, display an
- // appropriate icon to communicate the non-uniformity.
- _icon = isSelectionOfSameType
- ? getBlockType( firstBlockName )?.icon
- : copy;
- }
- return {
- possibleBlockTransformations: getBlockTransformItems(
- blocks,
- rootClientId
- ),
- canRemove: canRemoveBlocks( clientIds, rootClientId ),
- hasBlockStyles: !! styles?.length,
- icon: _icon,
- patterns: __experimentalGetPatternTransformItems(
- blocks,
- rootClientId
- ),
- };
- },
- [ clientIds, blocks, blockInformation?.icon ]
- );
+ const { blockTransformations, canRemove, hasBlockStyles, icon, patterns } =
+ useSelect(
+ ( select ) => {
+ const {
+ getBlockRootClientId,
+ getBlockTransformItems,
+ __experimentalGetPatternTransformItems,
+ canRemoveBlocks,
+ } = select( blockEditorStore );
+ const { getBlockStyles, getBlockType } = select( blocksStore );
+ const rootClientId = getBlockRootClientId(
+ Array.isArray( clientIds ) ? clientIds[ 0 ] : clientIds
+ );
+ const [ { name: firstBlockName } ] = blocks;
+ const _isSingleBlockSelected = blocks.length === 1;
+ const styles =
+ _isSingleBlockSelected && getBlockStyles( firstBlockName );
+ let _icon;
+ if ( _isSingleBlockSelected ) {
+ _icon = blockInformation?.icon; // Take into account active block variations.
+ } else {
+ const isSelectionOfSameType =
+ new Set( blocks.map( ( { name } ) => name ) ).size ===
+ 1;
+ // When selection consists of blocks of multiple types, display an
+ // appropriate icon to communicate the non-uniformity.
+ _icon = isSelectionOfSameType
+ ? getBlockType( firstBlockName )?.icon
+ : copy;
+ }
+ return {
+ blockTransformations:
+ getBlockTransformItems( rootClientId ),
+ canRemove: canRemoveBlocks( clientIds, rootClientId ),
+ hasBlockStyles: !! styles?.length,
+ icon: _icon,
+ patterns: __experimentalGetPatternTransformItems(
+ blocks,
+ rootClientId
+ ),
+ };
+ },
+ [ clientIds, blocks, blockInformation?.icon ]
+ );
+
+ const [ possibleBlockTransformations, setPossibleBlockTransformations ] =
+ useState( null );
+ useEffect( () => {
+ getTransformItemsForBlocks( blockTransformations, blocks ).then(
+ ( result ) => setPossibleBlockTransformations( result )
+ );
+ }, [ blockTransformations, blocks ] );
const blockVariationTransformations = useBlockVariationTransforms( {
clientIds,
@@ -108,8 +112,8 @@ export const BlockSwitcherDropdownMenu = ( { clientIds, blocks } ) => {
}
// Simple block tranformation based on the `Block Transforms` API.
- function onBlockTransform( name ) {
- const newBlocks = switchToBlockType( blocks, name );
+ async function onBlockTransform( name ) {
+ const newBlocks = await switchToBlockType( blocks, name );
replaceBlocks( clientIds, newBlocks );
selectForMultipleBlocks( newBlocks );
}
@@ -134,7 +138,7 @@ export const BlockSwitcherDropdownMenu = ( { clientIds, blocks } ) => {
* by allowing to exclude blocks from wildcard transformations.
*/
const hasPossibleBlockTransformations =
- !! possibleBlockTransformations.length && canRemove && ! isTemplate;
+ possibleBlockTransformations?.length && canRemove && ! isTemplate;
const hasPossibleBlockVariationTransformations =
!! blockVariationTransformations?.length;
const hasPatternTransformation = !! patterns?.length && canRemove;
diff --git a/packages/block-editor/src/components/convert-to-group-buttons/index.js b/packages/block-editor/src/components/convert-to-group-buttons/index.js
index c2bb3fb25b845..1053f76ba7efe 100644
--- a/packages/block-editor/src/components/convert-to-group-buttons/index.js
+++ b/packages/block-editor/src/components/convert-to-group-buttons/index.js
@@ -23,9 +23,9 @@ function ConvertToGroupButton( {
onClose = () => {},
} ) {
const { replaceBlocks } = useDispatch( blockEditorStore );
- const onConvertToGroup = () => {
+ const onConvertToGroup = async () => {
// Activate the `transform` on the Grouping Block which does the conversion.
- const newBlocks = switchToBlockType(
+ const newBlocks = await switchToBlockType(
blocksSelection,
groupingBlockName
);
diff --git a/packages/block-editor/src/components/convert-to-group-buttons/toolbar.js b/packages/block-editor/src/components/convert-to-group-buttons/toolbar.js
index 38405fe3ee6ab..cde6fe11daec9 100644
--- a/packages/block-editor/src/components/convert-to-group-buttons/toolbar.js
+++ b/packages/block-editor/src/components/convert-to-group-buttons/toolbar.js
@@ -40,16 +40,12 @@ function BlockGroupToolbar() {
[ clientIds, groupingBlockName ]
);
- const onConvertToGroup = ( layout ) => {
- const newBlocks = switchToBlockType(
+ const onConvertToGroup = async ( layout ) => {
+ const newBlocks = await switchToBlockType(
blocksSelection,
groupingBlockName
);
- if ( typeof layout !== 'string' ) {
- layout = 'group';
- }
-
if ( newBlocks && newBlocks.length > 0 ) {
// Because the block is not in the store yet we can't use
// updateBlockAttributes so need to manually update attributes.
@@ -69,10 +65,10 @@ function BlockGroupToolbar() {
return null;
}
- const canInsertRow = !! variations.find(
+ const canInsertRow = variations?.some(
( { name } ) => name === 'group-row'
);
- const canInsertStack = !! variations.find(
+ const canInsertStack = variations?.some(
( { name } ) => name === 'group-stack'
);
@@ -81,7 +77,7 @@ function BlockGroupToolbar() {
onConvertToGroup( 'group' ) }
/>
{ canInsertRow && (
( {
+ item: select( blocksStore ).getBlockType( name ),
+ } ),
+ [ name ]
+ );
+
+ const itemIconStyle = item?.icon
? {
backgroundColor: item.icon.background,
color: item.icon.foreground,
}
: {};
+
const blocks = useMemo( () => {
+ if ( ! item ) {
+ return [];
+ }
return [
createBlock(
item.name,
@@ -47,7 +61,11 @@ function InserterListItem( {
createBlocksFromInnerBlocksTemplate( item.innerBlocks )
),
];
- }, [ item.name, item.initialAttributes, item.initialAttributes ] );
+ }, [ item ] );
+
+ if ( ! item ) {
+ return null;
+ }
const isSynced =
( isReusableBlock( item ) && item.syncStatus !== 'unsynced' ) ||
@@ -55,7 +73,7 @@ function InserterListItem( {
return (
@@ -89,7 +107,7 @@ function InserterListItem( {
'block-editor-block-types-list__item',
className
) }
- disabled={ item.isDisabled }
+ disabled={ isDisabled }
onClick={ ( event ) => {
event.preventDefault();
onSelect(
diff --git a/packages/block-editor/src/components/inserter/hooks/use-block-types-state.js b/packages/block-editor/src/components/inserter/hooks/use-block-types-state.js
index 2faa503632783..b618e287f9d69 100644
--- a/packages/block-editor/src/components/inserter/hooks/use-block-types-state.js
+++ b/packages/block-editor/src/components/inserter/hooks/use-block-types-state.js
@@ -23,34 +23,35 @@ import { store as blockEditorStore } from '../../../store';
* @return {Array} Returns the block types state. (block types, categories, collections, onSelect handler)
*/
const useBlockTypesState = ( rootClientId, onInsert ) => {
- const { categories, collections, items } = useSelect(
- ( select ) => {
- const { getInserterItems } = select( blockEditorStore );
- const { getCategories, getCollections } = select( blocksStore );
-
- return {
- categories: getCategories(),
- collections: getCollections(),
- items: getInserterItems( rootClientId ),
- };
- },
+ const { items } = useSelect(
+ ( select ) => ( {
+ items: select( blockEditorStore ).getInserterItems( rootClientId ),
+ } ),
[ rootClientId ]
);
+ const { categories, collections } = useSelect( ( select ) => {
+ const { getCategories, getCollections } = select( blocksStore );
+
+ return {
+ categories: getCategories(),
+ collections: getCollections(),
+ };
+ } );
+
const onSelectItem = useCallback(
- (
- { name, initialAttributes, innerBlocks, syncStatus, content },
- shouldFocusBlock
- ) => {
+ async ( item, shouldFocusBlock ) => {
const insertedBlock =
- syncStatus === 'unsynced'
- ? parse( content, {
+ item.syncStatus === 'unsynced'
+ ? await parse( item.content, {
__unstableSkipMigrationLogs: true,
} )
: createBlock(
- name,
- initialAttributes,
- createBlocksFromInnerBlocksTemplate( innerBlocks )
+ item.name,
+ item.initialAttributes,
+ createBlocksFromInnerBlocksTemplate(
+ item.innerBlocks
+ )
);
onInsert( insertedBlock, undefined, shouldFocusBlock );
diff --git a/packages/block-editor/src/components/inserter/menu.js b/packages/block-editor/src/components/inserter/menu.js
index ae4f6875e4c9b..69beb31e8ffdb 100644
--- a/packages/block-editor/src/components/inserter/menu.js
+++ b/packages/block-editor/src/components/inserter/menu.js
@@ -208,13 +208,17 @@ function InserterMenu(
},
} ) );
+ const readyToShow = showPatterns !== null;
+
const showPatternPanel =
selectedTab === 'patterns' &&
! delayedFilterValue &&
selectedPatternCategory;
+
const showAsTabs =
! delayedFilterValue &&
( showPatterns || hasReusableBlocks || showMedia );
+
const showMediaPanel =
selectedTab === 'media' &&
! delayedFilterValue &&
@@ -247,7 +251,7 @@ function InserterMenu(
placeholder={ __( 'Search' ) }
ref={ searchRef }
/>
- { !! delayedFilterValue && (
+ { readyToShow && delayedFilterValue && (
) }
- { showAsTabs && (
+ { readyToShow && showAsTabs && (
) }
- { ! delayedFilterValue && ! showAsTabs && (
+ { readyToShow && ! delayedFilterValue && ! showAsTabs && (
{ blocksTab }
diff --git a/packages/block-editor/src/components/inserter/quick-inserter.js b/packages/block-editor/src/components/inserter/quick-inserter.js
index 540b51a4757e0..9edc1d7001f83 100644
--- a/packages/block-editor/src/components/inserter/quick-inserter.js
+++ b/packages/block-editor/src/components/inserter/quick-inserter.js
@@ -68,7 +68,7 @@ export default function QuickInserter( {
);
const showPatterns =
- patterns.length && ( !! filterValue || prioritizePatterns );
+ patterns?.length && ( !! filterValue || prioritizePatterns );
const showSearch =
( showPatterns && patterns.length > SEARCH_THRESHOLD ) ||
blockTypes.length > SEARCH_THRESHOLD;
diff --git a/packages/block-editor/src/components/media-placeholder/index.js b/packages/block-editor/src/components/media-placeholder/index.js
index 41b1d3fe37c56..a1f588b25cdcb 100644
--- a/packages/block-editor/src/components/media-placeholder/index.js
+++ b/packages/block-editor/src/components/media-placeholder/index.js
@@ -290,7 +290,7 @@ export function MediaPlaceholder( {
}
async function onHTMLDrop( HTML ) {
- const blocks = pasteHandler( { HTML } );
+ const blocks = await pasteHandler( { HTML } );
return await handleBlocksDrop( blocks );
}
diff --git a/packages/block-editor/src/components/rich-text/index.native.js b/packages/block-editor/src/components/rich-text/index.native.js
index acadfb24a7221..911c5809d3268 100644
--- a/packages/block-editor/src/components/rich-text/index.native.js
+++ b/packages/block-editor/src/components/rich-text/index.native.js
@@ -300,16 +300,17 @@ export function RichTextWrapper(
);
const onEnter = useCallback(
- ( { value, onChange, shiftKey } ) => {
+ async ( { value, onChange, shiftKey } ) => {
const canSplit = onReplace && onSplit;
if ( onReplace ) {
- const transforms = getBlockTransforms( 'from' ).filter(
- ( { type } ) => type === 'enter'
+ const transforms = await getBlockTransforms( 'from' );
+ const enterTransforms = transforms.filter(
+ ( t ) => t.type === 'enter'
+ );
+ const transformation = findTransform( enterTransforms, ( t ) =>
+ t.regExp.test( value.text )
);
- const transformation = findTransform( transforms, ( item ) => {
- return item.regExp.test( value.text );
- } );
if ( transformation ) {
onReplace( [
@@ -364,7 +365,7 @@ export function RichTextWrapper(
);
const onPaste = useCallback(
- ( {
+ async ( {
value,
onChange,
html,
@@ -394,7 +395,7 @@ export function RichTextWrapper(
// Only process file if no HTML is present.
// Note: a pasted file may have the URL as plain text.
if ( files && files.length && ! html ) {
- const content = pasteHandler( {
+ const content = await pasteHandler( {
HTML: filePasteHandler( files ),
mode: 'BLOCKS',
tagName,
@@ -433,7 +434,7 @@ export function RichTextWrapper(
mode = 'BLOCKS';
}
- const content = pasteHandler( {
+ const content = await pasteHandler( {
HTML: html,
plainText,
mode,
@@ -486,7 +487,7 @@ export function RichTextWrapper(
);
const inputRule = useCallback(
- ( value, valueToFormat ) => {
+ async ( value, valueToFormat ) => {
if ( ! onReplace ) {
return;
}
@@ -503,14 +504,12 @@ export function RichTextWrapper(
}
const trimmedTextBefore = text.slice( 0, startPosition ).trim();
- const prefixTransforms = getBlockTransforms( 'from' ).filter(
- ( { type } ) => type === 'prefix'
- );
+ const prefixTransforms = (
+ await getBlockTransforms( 'from' )
+ ).filter( ( { type } ) => type === 'prefix' );
const transformation = findTransform(
prefixTransforms,
- ( { prefix } ) => {
- return trimmedTextBefore === prefix;
- }
+ ( { prefix } ) => trimmedTextBefore === prefix
);
if ( ! transformation ) {
diff --git a/packages/block-editor/src/components/rich-text/use-enter.js b/packages/block-editor/src/components/rich-text/use-enter.js
index 40d4f9be4759f..6bb6db1d3c870 100644
--- a/packages/block-editor/src/components/rich-text/use-enter.js
+++ b/packages/block-editor/src/components/rich-text/use-enter.js
@@ -20,7 +20,7 @@ export function useEnter( props ) {
const propsRef = useRef( props );
propsRef.current = props;
return useRefEffect( ( element ) => {
- function onKeyDown( event ) {
+ async function onKeyDown( event ) {
if ( event.defaultPrevented ) {
return;
}
@@ -47,9 +47,9 @@ export function useEnter( props ) {
const canSplit = onReplace && onSplit;
if ( onReplace ) {
- const transforms = getBlockTransforms( 'from' ).filter(
- ( { type } ) => type === 'enter'
- );
+ const transforms = (
+ await getBlockTransforms( 'from' )
+ ).filter( ( { type } ) => type === 'enter' );
const transformation = findTransform( transforms, ( item ) => {
return item.regExp.test( _value.text );
} );
diff --git a/packages/block-editor/src/components/rich-text/use-input-rules.js b/packages/block-editor/src/components/rich-text/use-input-rules.js
index 5640a85f5f269..1e7b3986c5198 100644
--- a/packages/block-editor/src/components/rich-text/use-input-rules.js
+++ b/packages/block-editor/src/components/rich-text/use-input-rules.js
@@ -83,7 +83,7 @@ export function useInputRules( props ) {
const propsRef = useRef( props );
propsRef.current = props;
return useRefEffect( ( element ) => {
- function inputRule() {
+ async function inputRule() {
const { getValue, onReplace, selectionChange } = propsRef.current;
if ( ! onReplace ) {
@@ -102,14 +102,12 @@ export function useInputRules( props ) {
}
const trimmedTextBefore = text.slice( 0, start ).trim();
- const prefixTransforms = getBlockTransforms( 'from' ).filter(
- ( { type } ) => type === 'prefix'
- );
+ const prefixTransforms = (
+ await getBlockTransforms( 'from' )
+ ).filter( ( { type } ) => type === 'prefix' );
const transformation = findTransform(
prefixTransforms,
- ( { prefix } ) => {
- return trimmedTextBefore === prefix;
- }
+ ( { prefix } ) => trimmedTextBefore === prefix
);
if ( ! transformation ) {
@@ -128,7 +126,7 @@ export function useInputRules( props ) {
return true;
}
- function onInput( event ) {
+ async function onInput( event ) {
const { inputType, type } = event;
const {
getValue,
@@ -142,8 +140,8 @@ export function useInputRules( props ) {
return;
}
- if ( __unstableAllowPrefixTransformations && inputRule ) {
- if ( inputRule() ) return;
+ if ( __unstableAllowPrefixTransformations ) {
+ if ( await inputRule() ) return;
}
const value = getValue();
diff --git a/packages/block-editor/src/components/rich-text/use-paste-handler.js b/packages/block-editor/src/components/rich-text/use-paste-handler.js
index 1302e2d0dce46..78382eb8d12b1 100644
--- a/packages/block-editor/src/components/rich-text/use-paste-handler.js
+++ b/packages/block-editor/src/components/rich-text/use-paste-handler.js
@@ -24,7 +24,7 @@ export function usePasteHandler( props ) {
const propsRef = useRef( props );
propsRef.current = props;
return useRefEffect( ( element ) => {
- function _onPaste( event ) {
+ async function _onPaste( event ) {
const {
isSelected,
disableFormats,
@@ -78,7 +78,7 @@ export function usePasteHandler( props ) {
// eslint-disable-next-line no-console
window.console.log( 'Received items:\n\n', files );
- const fromTransforms = getBlockTransforms( 'from' );
+ const fromTransforms = await getBlockTransforms( 'from' );
const blocks = files
.reduce( ( accumulator, file ) => {
const transformation = findTransform(
@@ -127,7 +127,7 @@ export function usePasteHandler( props ) {
mode = 'BLOCKS';
}
- const content = pasteHandler( {
+ const content = await pasteHandler( {
HTML: html,
plainText,
mode,
diff --git a/packages/block-editor/src/components/use-on-block-drop/index.js b/packages/block-editor/src/components/use-on-block-drop/index.js
index ab0da8ad99e2a..134eb4adf9e87 100644
--- a/packages/block-editor/src/components/use-on-block-drop/index.js
+++ b/packages/block-editor/src/components/use-on-block-drop/index.js
@@ -149,13 +149,13 @@ export function onFilesDrop(
canInsertBlockType,
insertOrReplaceBlocks
) {
- return ( files ) => {
+ return async ( files ) => {
if ( ! hasUploadPermissions ) {
return;
}
const transformation = findTransform(
- getBlockTransforms( 'from' ),
+ await getBlockTransforms( 'from' ),
( transform ) =>
transform.type === 'files' &&
canInsertBlockType( transform.blockName, targetRootClientId ) &&
@@ -186,8 +186,8 @@ export function onHTMLDrop(
targetBlockIndex,
insertOrReplaceBlocks
) {
- return ( HTML ) => {
- const blocks = pasteHandler( { HTML, mode: 'BLOCKS' } );
+ return async ( HTML ) => {
+ const blocks = await pasteHandler( { HTML, mode: 'BLOCKS' } );
if ( blocks.length ) {
insertOrReplaceBlocks( blocks );
diff --git a/packages/block-editor/src/components/writing-flow/use-clipboard-handler.js b/packages/block-editor/src/components/writing-flow/use-clipboard-handler.js
index 5b78d2f8656b6..f8a2652b694b4 100644
--- a/packages/block-editor/src/components/writing-flow/use-clipboard-handler.js
+++ b/packages/block-editor/src/components/writing-flow/use-clipboard-handler.js
@@ -46,7 +46,7 @@ export default function useClipboardHandler() {
const notifyCopy = useNotifyCopy();
return useRefEffect( ( node ) => {
- function handler( event ) {
+ async function handler( event ) {
if ( event.defaultPrevented ) {
// This was likely already handled in rich-text/use-paste-handler.js.
return;
@@ -157,7 +157,7 @@ export default function useClipboardHandler() {
let blocks = [];
if ( files.length ) {
- const fromTransforms = getBlockTransforms( 'from' );
+ const fromTransforms = await getBlockTransforms( 'from' );
blocks = files
.reduce( ( accumulator, file ) => {
const transformation = findTransform(
@@ -175,7 +175,7 @@ export default function useClipboardHandler() {
}, [] )
.flat();
} else {
- blocks = pasteHandler( {
+ blocks = await pasteHandler( {
HTML: html,
plainText,
mode: 'BLOCKS',
diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js
index b21436161cb8c..3df8eddaf5b07 100644
--- a/packages/block-editor/src/store/actions.js
+++ b/packages/block-editor/src/store/actions.js
@@ -703,7 +703,7 @@ export const synchronizeTemplate =
*/
export const __unstableDeleteSelection =
( isForward ) =>
- ( { registry, select, dispatch } ) => {
+ async ( { registry, select, dispatch } ) => {
const selectionAnchor = select.getSelectionStart();
const selectionFocus = select.getSelectionEnd();
@@ -784,7 +784,10 @@ export const __unstableDeleteSelection =
const blocksWithTheSameType =
blockA.name === blockB.name
? [ followingBlock ]
- : switchToBlockType( followingBlock, targetBlockType.name );
+ : await switchToBlockType(
+ followingBlock,
+ targetBlockType.name
+ );
// If the block types can not match, do nothing
if ( ! blocksWithTheSameType || ! blocksWithTheSameType.length ) {
@@ -957,7 +960,7 @@ export const __unstableExpandSelection =
*/
export const mergeBlocks =
( firstBlockClientId, secondBlockClientId ) =>
- ( { registry, select, dispatch } ) => {
+ async ( { registry, select, dispatch } ) => {
const blocks = [ firstBlockClientId, secondBlockClientId ];
dispatch( { type: 'MERGE_BLOCKS', blocks } );
@@ -975,7 +978,7 @@ export const mergeBlocks =
) {
// If there's no merge function defined, attempt merging inner
// blocks.
- const blocksWithTheSameType = switchToBlockType(
+ const blocksWithTheSameType = await switchToBlockType(
blockB,
blockAType.name
);
@@ -1112,7 +1115,7 @@ export const mergeBlocks =
const blocksWithTheSameType =
blockA.name === blockB.name
? [ cloneB ]
- : switchToBlockType( cloneB, blockA.name );
+ : await switchToBlockType( cloneB, blockA.name );
// If the block types can not match, do nothing.
if ( ! blocksWithTheSameType || ! blocksWithTheSameType.length ) {
diff --git a/packages/block-editor/src/store/index.js b/packages/block-editor/src/store/index.js
index 0bcc00cb5f6ae..fc999278ed68c 100644
--- a/packages/block-editor/src/store/index.js
+++ b/packages/block-editor/src/store/index.js
@@ -11,6 +11,7 @@ import * as selectors from './selectors';
import * as privateActions from './private-actions';
import * as privateSelectors from './private-selectors';
import * as actions from './actions';
+import * as resolvers from './resolvers';
import { STORE_NAME } from './constants';
import { unlock } from '../lock-unlock';
@@ -23,6 +24,7 @@ export const storeConfig = {
reducer,
selectors,
actions,
+ resolvers,
};
/**
diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js
index 5319a3b255365..6572277217eb0 100644
--- a/packages/block-editor/src/store/reducer.js
+++ b/packages/block-editor/src/store/reducer.js
@@ -1991,6 +1991,17 @@ export function lastFocus( state = false, action ) {
return state;
}
+export function parsedPatterns( state = {}, action ) {
+ switch ( action.type ) {
+ case 'SET_PARSED_PATTERN':
+ return {
+ ...state,
+ [ action.patternName ]: action.parsedPattern,
+ };
+ }
+ return state;
+}
+
const combinedReducers = combineReducers( {
blocks,
isTyping,
@@ -2020,6 +2031,7 @@ const combinedReducers = combineReducers( {
blockRemovalRules,
openedBlockSettingsMenu,
registeredInserterMediaCategories,
+ parsedPatterns,
} );
function withAutomaticChangeReset( reducer ) {
diff --git a/packages/block-editor/src/store/resolvers.js b/packages/block-editor/src/store/resolvers.js
new file mode 100644
index 0000000000000..f072b6689706a
--- /dev/null
+++ b/packages/block-editor/src/store/resolvers.js
@@ -0,0 +1,69 @@
+/**
+ * WordPress dependencies
+ */
+import { parse } from '@wordpress/blocks';
+
+export const __experimentalGetParsedPattern =
+ ( patternName ) =>
+ async ( { select, dispatch } ) => {
+ const patterns = select(
+ ( state ) => state.root.settings.__experimentalBlockPatterns
+ );
+ const unsyncedPatterns = select.getUnsyncedPatterns();
+
+ const pattern = [ ...patterns, ...unsyncedPatterns ].find(
+ ( { name } ) => name === patternName
+ );
+
+ if ( ! pattern ) {
+ return;
+ }
+
+ const blocks = await parse( pattern.content, {
+ __unstableSkipMigrationLogs: true,
+ } );
+
+ const parsedPattern = { ...pattern, blocks };
+
+ dispatch( {
+ type: 'SET_PARSED_PATTERN',
+ patternName: pattern.name,
+ parsedPattern,
+ } );
+ };
+
+export const __experimentalGetAllowedPatterns =
+ () =>
+ async ( { select, dispatch } ) => {
+ const patterns = select(
+ ( state ) => state.root.settings.__experimentalBlockPatterns
+ );
+ const unsyncedPatterns = select.getUnsyncedPatterns();
+
+ const inserterPatterns = [ ...patterns, ...unsyncedPatterns ].filter(
+ ( { inserter = true } ) => inserter
+ );
+
+ for ( const pattern of inserterPatterns ) {
+ const blocks = await parse( pattern.content, {
+ __unstableSkipMigrationLogs: true,
+ } );
+
+ const parsedPattern = { ...pattern, blocks };
+
+ dispatch( {
+ type: 'SET_PARSED_PATTERN',
+ patternName: pattern.name,
+ parsedPattern,
+ } );
+ }
+ };
+
+__experimentalGetAllowedPatterns.shouldInvalidate = ( action ) => {
+ return (
+ action.type === 'UPDATE_SETTINGS' &&
+ action.settings.__experimentalBlockPatterns
+ );
+};
+
+export const getPatternsByBlockTypes = __experimentalGetAllowedPatterns;
diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js
index b6d455333c7a5..3eb7ccd25866a 100644
--- a/packages/block-editor/src/store/selectors.js
+++ b/packages/block-editor/src/store/selectors.js
@@ -8,10 +8,10 @@ import createSelector from 'rememo';
*/
import {
getBlockType,
- getBlockTypes,
+ getBootstrappedBlockType,
+ getBootstrappedBlockTypes,
getBlockVariations,
hasBlockSupport,
- getPossibleBlockTransformations,
parse,
switchToBlockType,
store as blocksStore,
@@ -1508,7 +1508,7 @@ const canInsertBlockTypeUnmemoized = (
blockType = blockName;
blockName = blockType.name;
} else {
- blockType = getBlockType( blockName );
+ blockType = getBootstrappedBlockType( blockName );
}
if ( ! blockType ) {
return false;
@@ -1975,7 +1975,7 @@ export const getInserterItems = createSelector(
buildScope: 'inserter',
} );
- const blockTypeInserterItems = getBlockTypes()
+ const blockTypeInserterItems = getBootstrappedBlockTypes()
.filter( ( blockType ) =>
canIncludeBlockTypeInInserter( state, blockType, rootClientId )
)
@@ -1987,10 +1987,9 @@ export const getInserterItems = createSelector(
if ( ! variations.some( ( { isDefault } ) => isDefault ) ) {
accumulator.push( item );
}
- if ( variations.length ) {
- const variationMapper = getItemFromVariation( state, item );
- accumulator.push( ...variations.map( variationMapper ) );
- }
+ accumulator.push(
+ ...variations.map( getItemFromVariation( state, item ) )
+ );
return accumulator;
}, [] );
@@ -1999,18 +1998,10 @@ export const getInserterItems = createSelector(
// the core blocks (usually by using the `init` action),
// thus affecting the display order.
// We don't sort reusable blocks as they are handled differently.
- const groupByType = ( blocks, block ) => {
- const { core, noncore } = blocks;
- const type = block.name.startsWith( 'core/' ) ? core : noncore;
-
- type.push( block );
- return blocks;
- };
- const { core: coreItems, noncore: nonCoreItems } = items.reduce(
- groupByType,
- { core: [], noncore: [] }
+ const sortedBlockTypes = orderBy(
+ items,
+ ( block ) => ! block.name.startsWith( 'core/' ) // false < true
);
- const sortedBlockTypes = [ ...coreItems, ...nonCoreItems ];
return [ ...sortedBlockTypes, ...syncedPatternInserterItems ];
},
( state, rootClientId ) => [
@@ -2021,7 +2012,7 @@ export const getInserterItems = createSelector(
state.settings.allowedBlockTypes,
state.settings.templateLock,
getReusableBlocks( state ),
- getBlockTypes(),
+ getBootstrappedBlockTypes(),
]
);
@@ -2052,37 +2043,18 @@ export const getInserterItems = createSelector(
* @property {number} frecency Heuristic that combines frequency and recency.
*/
export const getBlockTransformItems = createSelector(
- ( state, blocks, rootClientId = null ) => {
- const normalizedBlocks = Array.isArray( blocks ) ? blocks : [ blocks ];
+ ( state, rootClientId = null ) => {
const buildBlockTypeTransformItem = buildBlockTypeItem( state, {
buildScope: 'transform',
} );
- const blockTypeTransformItems = getBlockTypes()
+ const blockTypeTransformItems = getBootstrappedBlockTypes()
.filter( ( blockType ) =>
canIncludeBlockTypeInInserter( state, blockType, rootClientId )
)
- .map( buildBlockTypeTransformItem );
-
- const itemsByName = Object.fromEntries(
- Object.entries( blockTypeTransformItems ).map( ( [ , value ] ) => [
- value.name,
- value,
- ] )
- );
+ .map( buildBlockTypeTransformItem )
+ .map( ( value ) => [ value.name, value ] );
- const possibleTransforms = getPossibleBlockTransformations(
- normalizedBlocks
- ).reduce( ( accumulator, block ) => {
- if ( itemsByName[ block?.name ] ) {
- accumulator.push( itemsByName[ block.name ] );
- }
- return accumulator;
- }, [] );
- return orderBy(
- possibleTransforms,
- ( block ) => itemsByName[ block.name ].frecency,
- 'desc'
- );
+ return Object.fromEntries( blockTypeTransformItems );
},
( state, blocks, rootClientId ) => [
state.blockListSettings[ rootClientId ],
@@ -2090,7 +2062,7 @@ export const getBlockTransformItems = createSelector(
state.preferences.insertUsage,
state.settings.allowedBlockTypes,
state.settings.templateLock,
- getBlockTypes(),
+ getBootstrappedBlockTypes(),
]
);
@@ -2102,29 +2074,21 @@ export const getBlockTransformItems = createSelector(
*
* @return {boolean} Items that appear in inserter.
*/
-export const hasInserterItems = createSelector(
- ( state, rootClientId = null ) => {
- const hasBlockType = getBlockTypes().some( ( blockType ) =>
- canIncludeBlockTypeInInserter( state, blockType, rootClientId )
- );
- if ( hasBlockType ) {
- return true;
- }
- const hasReusableBlock =
- canInsertBlockTypeUnmemoized( state, 'core/block', rootClientId ) &&
- getReusableBlocks( state ).length > 0;
+export const hasInserterItems = ( state, rootClientId = null ) => {
+ const hasBlockType = getBootstrappedBlockTypes().some( ( blockType ) =>
+ canIncludeBlockTypeInInserter( state, blockType, rootClientId )
+ );
- return hasReusableBlock;
- },
- ( state, rootClientId ) => [
- state.blockListSettings[ rootClientId ],
- state.blocks.byClientId,
- state.settings.allowedBlockTypes,
- state.settings.templateLock,
- getReusableBlocks( state ),
- getBlockTypes(),
- ]
-);
+ if ( hasBlockType ) {
+ return true;
+ }
+
+ const hasReusableBlock =
+ canInsertBlockTypeUnmemoized( state, 'core/block', rootClientId ) &&
+ getReusableBlocks( state ).length > 0;
+
+ return hasReusableBlock;
+};
/**
* Returns the list of allowed inserter blocks for inner blocks children.
@@ -2140,9 +2104,10 @@ export const getAllowedBlocks = createSelector(
return;
}
- const blockTypes = getBlockTypes().filter( ( blockType ) =>
+ const blockTypes = getBootstrappedBlockTypes().filter( ( blockType ) =>
canIncludeBlockTypeInInserter( state, blockType, rootClientId )
);
+
const hasReusableBlock =
canInsertBlockTypeUnmemoized( state, 'core/block', rootClientId ) &&
getReusableBlocks( state ).length > 0;
@@ -2158,7 +2123,7 @@ export const getAllowedBlocks = createSelector(
state.settings.allowedBlockTypes,
state.settings.templateLock,
getReusableBlocks( state ),
- getBlockTypes(),
+ getBootstrappedBlockTypes(),
]
);
@@ -2321,6 +2286,7 @@ export const __experimentalGetAllowedPatterns = createSelector(
state.settings.templateLock,
state.blockListSettings[ rootClientId ],
state.blocks.byClientId.get( rootClientId ),
+ state.parsedPatterns,
]
);
@@ -2344,6 +2310,11 @@ export const getPatternsByBlockTypes = createSelector(
state,
rootClientId
);
+
+ if ( ! patterns ) {
+ return null;
+ }
+
const normalizedBlockNames = Array.isArray( blockNames )
? blockNames
: [ blockNames ];
diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js
index b74079b2b8b79..bcbe08538a26c 100644
--- a/packages/block-library/src/image/image.js
+++ b/packages/block-library/src/image/image.js
@@ -324,10 +324,10 @@ export default function Image( {
const canEditImage = id && naturalWidth && naturalHeight && imageEditing;
const allowCrop = ! multiImageSelection && canEditImage && ! isEditingImage;
- function switchToCover() {
+ async function switchToCover() {
replaceBlocks(
clientId,
- switchToBlockType( getBlock( clientId ), 'core/cover' )
+ await switchToBlockType( getBlock( clientId ), 'core/cover' )
);
}
diff --git a/packages/block-library/src/list-item/edit.js b/packages/block-library/src/list-item/edit.js
index 3f26840ad345f..a529d192986cb 100644
--- a/packages/block-library/src/list-item/edit.js
+++ b/packages/block-library/src/list-item/edit.js
@@ -90,9 +90,9 @@ export default function ListItemEdit( {
onMerge={ onMerge }
onReplace={
onReplace
- ? ( blocks, ...args ) => {
+ ? async ( blocks, ...args ) => {
onReplace(
- convertToListItems( blocks ),
+ await convertToListItems( blocks ),
...args
);
}
diff --git a/packages/block-library/src/list-item/edit.native.js b/packages/block-library/src/list-item/edit.native.js
index cf2e77c08d2e8..b8b3690a41fa8 100644
--- a/packages/block-library/src/list-item/edit.native.js
+++ b/packages/block-library/src/list-item/edit.native.js
@@ -130,12 +130,12 @@ export default function ListItemEdit( {
[ clientId, onSplit ]
);
const onReplaceList = useCallback(
- ( blocks, ...args ) => {
+ async ( blocks, ...args ) => {
if ( ! preventDefault.current ) {
- onReplace( convertToListItems( blocks ), ...args );
+ onReplace( await convertToListItems( blocks ), ...args );
}
},
- [ clientId, onReplace, convertToListItems ]
+ [ onReplace ]
);
const onLayout = useCallback( ( { nativeEvent } ) => {
setContentWidth( ( prevState ) => {
diff --git a/packages/block-library/src/list-item/utils.js b/packages/block-library/src/list-item/utils.js
index 5e5b51a8af680..29252fb4f2a12 100644
--- a/packages/block-library/src/list-item/utils.js
+++ b/packages/block-library/src/list-item/utils.js
@@ -3,19 +3,19 @@
*/
import { switchToBlockType } from '@wordpress/blocks';
-function convertBlockToList( block ) {
- const list = switchToBlockType( block, 'core/list' );
+async function convertBlockToList( block ) {
+ const list = await switchToBlockType( block, 'core/list' );
if ( list ) {
return list;
}
- const paragraph = switchToBlockType( block, 'core/paragraph' );
+ const paragraph = await switchToBlockType( block, 'core/paragraph' );
if ( ! paragraph ) {
return null;
}
- return switchToBlockType( paragraph, 'core/list' );
+ return await switchToBlockType( paragraph, 'core/list' );
}
-export function convertToListItems( blocks ) {
+export async function convertToListItems( blocks ) {
const listItems = [];
for ( let block of blocks ) {
@@ -23,7 +23,7 @@ export function convertToListItems( blocks ) {
listItems.push( block );
} else if ( block.name === 'core/list' ) {
listItems.push( ...block.innerBlocks );
- } else if ( ( block = convertBlockToList( block ) ) ) {
+ } else if ( ( block = await convertBlockToList( block ) ) ) {
for ( const { innerBlocks } of block ) {
listItems.push( ...innerBlocks );
}
diff --git a/packages/block-library/src/navigation-link/link-ui.js b/packages/block-library/src/navigation-link/link-ui.js
index 3c3d91e7b0a05..3b8259e1fb7c1 100644
--- a/packages/block-library/src/navigation-link/link-ui.js
+++ b/packages/block-library/src/navigation-link/link-ui.js
@@ -113,10 +113,10 @@ function LinkControlTransforms( { clientId } ) {
return (