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 c053235c2d0d3..de89fd6cd8cf5 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -307,7 +307,7 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => { ) { removeBlock( _clientId ); } else { - registry.batch( () => { + registry.batch( async () => { if ( canInsertBlockType( getBlockName( firstClientId ), @@ -321,7 +321,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 027ed12a7483a..5adb68d7c1764 100644 --- a/packages/block-editor/src/components/block-list/block.native.js +++ b/packages/block-editor/src/components/block-list/block.native.js @@ -500,7 +500,7 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => { ) { removeBlock( _clientId ); } else { - registry.batch( () => { + registry.batch( async () => { if ( canInsertBlockType( getBlockName( firstClientId ), @@ -514,7 +514,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 <PreviewBlockPopover blocks={ blocks } />; +} + const BlockTransformationsMenu = ( { className, possibleBlockTransformations, @@ -91,11 +106,10 @@ const BlockTransformationsMenu = ( { <> <MenuGroup label={ __( 'Transform to' ) } className={ className }> { hoveredTransformItemName && ( - <PreviewBlockPopover - blocks={ switchToBlockType( - blocks, - hoveredTransformItemName - ) } + <Preview + key={ hoveredTransformItemName } + blocks={ blocks } + transformName={ 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 8117c6f539b4f..eb58a1dc1e1d9 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() { <ToolbarButton icon={ group } label={ _x( 'Group', 'verb' ) } - onClick={ onConvertToGroup } + onClick={ () => onConvertToGroup( 'group' ) } /> { canInsertRow && ( <ToolbarButton diff --git a/packages/block-editor/src/components/inserter-list-item/index.js b/packages/block-editor/src/components/inserter-list-item/index.js index 5cc59dfbac005..033db5a9456ef 100644 --- a/packages/block-editor/src/components/inserter-list-item/index.js +++ b/packages/block-editor/src/components/inserter-list-item/index.js @@ -6,8 +6,10 @@ import classnames from 'classnames'; /** * WordPress dependencies */ +import { useSelect } from '@wordpress/data'; import { useMemo, useRef, memo } from '@wordpress/element'; import { + store as blocksStore, createBlock, createBlocksFromInnerBlocksTemplate, isReusableBlock, @@ -26,29 +28,44 @@ import InserterDraggableBlocks from '../inserter-draggable-blocks'; function InserterListItem( { className, isFirst, - item, + item: { name, isDisabled }, onSelect, onHover, isDraggable, ...props } ) { const isDragging = useRef( false ); - const itemIconStyle = item.icon + + const { item } = useSelect( + ( select ) => ( { + item: select( blocksStore ).getBlockType( name ), + } ), + [ name ] + ); + + const itemIconStyle = item?.icon ? { backgroundColor: item.icon.background, color: item.icon.foreground, } : {}; - const blocks = useMemo( - () => [ + + const blocks = useMemo( () => { + if ( ! item ) { + return []; + } + return [ createBlock( item.name, item.initialAttributes, createBlocksFromInnerBlocksTemplate( item.innerBlocks ) ), - ], - [ item.name, item.initialAttributes, item.innerBlocks ] - ); + ]; + }, [ item ] ); + + if ( ! item ) { + return null; + } const isSynced = ( isReusableBlock( item ) && item.syncStatus !== 'unsynced' ) || @@ -89,7 +106,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 566d0476fbd0f..914a76276725d 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 @@ -36,19 +36,18 @@ const useBlockTypesState = ( rootClientId, onInsert ) => { }, [] ); 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 24c099869ae0d..6123fdc8866fc 100644 --- a/packages/block-editor/src/components/inserter/menu.js +++ b/packages/block-editor/src/components/inserter/menu.js @@ -199,6 +199,8 @@ function InserterMenu( }, } ) ); + const readyToShow = showPatterns !== null; + const showPatternPanel = selectedTab === 'patterns' && ! delayedFilterValue && @@ -236,7 +238,7 @@ function InserterMenu( placeholder={ __( 'Search' ) } ref={ searchRef } /> - { !! delayedFilterValue && ( + { readyToShow && delayedFilterValue && ( <div className="block-editor-inserter__no-tab-container"> <InserterSearchResults filterValue={ delayedFilterValue } @@ -254,7 +256,7 @@ function InserterMenu( /> </div> ) } - { showAsTabs && ( + { readyToShow && showAsTabs && ( <InserterTabs showPatterns={ showPatterns } showMedia={ showMedia } @@ -263,7 +265,7 @@ function InserterMenu( tabsContents={ inserterTabsContents } /> ) } - { ! delayedFilterValue && ! showAsTabs && ( + { readyToShow && ! delayedFilterValue && ! showAsTabs && ( <div className="block-editor-inserter__no-tab-container"> { blocksTab } </div> 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 c49af2f80fca2..3d5a608f5a07b 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 ( ! getSettings().mediaUpload ) { 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/archives/block.json b/packages/block-library/src/archives/block.json index 7e0f5181d2c3d..5e8d4c4ce992f 100644 --- a/packages/block-library/src/archives/block.json +++ b/packages/block-library/src/archives/block.json @@ -49,5 +49,6 @@ } } }, - "editorStyle": "wp-block-archives-editor" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css" } diff --git a/packages/block-library/src/audio/block.json b/packages/block-library/src/audio/block.json index 04df268a74a63..901edf1fe03d5 100644 --- a/packages/block-library/src/audio/block.json +++ b/packages/block-library/src/audio/block.json @@ -56,6 +56,7 @@ } } }, - "editorStyle": "wp-block-audio-editor", - "style": "wp-block-audio" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/avatar/block.json b/packages/block-library/src/avatar/block.json index fa86541b2963f..1cf3b2deb5fc4 100644 --- a/packages/block-library/src/avatar/block.json +++ b/packages/block-library/src/avatar/block.json @@ -55,6 +55,7 @@ "selectors": { "border": ".wp-block-avatar img" }, - "editorStyle": "wp-block-avatar-editor", - "style": "wp-block-avatar" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/block/block.json b/packages/block-library/src/block/block.json index aeccdbfc1051d..f6f5aee72a502 100644 --- a/packages/block-library/src/block/block.json +++ b/packages/block-library/src/block/block.json @@ -15,7 +15,9 @@ "supports": { "customClassName": false, "html": false, - "inserter": false, - "renaming": false - } + "inserter": false, + "renaming": false +}, + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css" } diff --git a/packages/block-library/src/button/block.json b/packages/block-library/src/button/block.json index 3c232700a876e..c758617d47425 100644 --- a/packages/block-library/src/button/block.json +++ b/packages/block-library/src/button/block.json @@ -124,6 +124,7 @@ { "name": "fill", "label": "Fill", "isDefault": true }, { "name": "outline", "label": "Outline" } ], - "editorStyle": "wp-block-button-editor", - "style": "wp-block-button" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/buttons/block.json b/packages/block-library/src/buttons/block.json index 4dc420bd41885..8f47da58f2196 100644 --- a/packages/block-library/src/buttons/block.json +++ b/packages/block-library/src/buttons/block.json @@ -40,6 +40,7 @@ } } }, - "editorStyle": "wp-block-buttons-editor", - "style": "wp-block-buttons" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/calendar/block.json b/packages/block-library/src/calendar/block.json index 974d47ff8ec2c..4b7b1eb56aff4 100644 --- a/packages/block-library/src/calendar/block.json +++ b/packages/block-library/src/calendar/block.json @@ -39,5 +39,7 @@ } } }, - "style": "wp-block-calendar" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/categories/block.json b/packages/block-library/src/categories/block.json index 5014da8298049..4a93be19f82dc 100644 --- a/packages/block-library/src/categories/block.json +++ b/packages/block-library/src/categories/block.json @@ -53,6 +53,7 @@ } } }, - "editorStyle": "wp-block-categories-editor", - "style": "wp-block-categories" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/code/block.json b/packages/block-library/src/code/block.json index bd5db3c918b96..5c9fda719d241 100644 --- a/packages/block-library/src/code/block.json +++ b/packages/block-library/src/code/block.json @@ -58,5 +58,7 @@ } } }, - "style": "wp-block-code" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/column/block.json b/packages/block-library/src/column/block.json index 7f61f307fab15..ce1d1e3a55190 100644 --- a/packages/block-library/src/column/block.json +++ b/packages/block-library/src/column/block.json @@ -69,5 +69,6 @@ } }, "layout": true - } + }, + "editorScript": "file:./editor.min.js" } diff --git a/packages/block-library/src/columns/block.json b/packages/block-library/src/columns/block.json index dff9c45ae2dde..7386411001a99 100644 --- a/packages/block-library/src/columns/block.json +++ b/packages/block-library/src/columns/block.json @@ -80,6 +80,7 @@ } } }, - "editorStyle": "wp-block-columns-editor", - "style": "wp-block-columns" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/comment-author-avatar/block.json b/packages/block-library/src/comment-author-avatar/block.json index 050d87c3b4634..cb288b97d72a4 100644 --- a/packages/block-library/src/comment-author-avatar/block.json +++ b/packages/block-library/src/comment-author-avatar/block.json @@ -40,5 +40,7 @@ "margin": true, "padding": true } - } + }, + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css" } diff --git a/packages/block-library/src/comment-author-name/block.json b/packages/block-library/src/comment-author-name/block.json index 93350779fc8bd..e6e2b7379b43d 100644 --- a/packages/block-library/src/comment-author-name/block.json +++ b/packages/block-library/src/comment-author-name/block.json @@ -49,5 +49,6 @@ "fontSize": true } } - } + }, + "editorScript": "file:./editor.min.js" } diff --git a/packages/block-library/src/comment-content/block.json b/packages/block-library/src/comment-content/block.json index 9ac4b5453365b..a42ac9f646813 100644 --- a/packages/block-library/src/comment-content/block.json +++ b/packages/block-library/src/comment-content/block.json @@ -42,5 +42,8 @@ } }, "html": false - } + }, + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/comment-date/block.json b/packages/block-library/src/comment-date/block.json index 7e4776c68ff2f..a16c74e0afeb0 100644 --- a/packages/block-library/src/comment-date/block.json +++ b/packages/block-library/src/comment-date/block.json @@ -45,5 +45,6 @@ "fontSize": true } } - } + }, + "editorScript": "file:./editor.min.js" } diff --git a/packages/block-library/src/comment-edit-link/block.json b/packages/block-library/src/comment-edit-link/block.json index 505305f60987a..844bc43b53811 100644 --- a/packages/block-library/src/comment-edit-link/block.json +++ b/packages/block-library/src/comment-edit-link/block.json @@ -45,5 +45,6 @@ "fontSize": true } } - } + }, + "editorScript": "file:./editor.min.js" } diff --git a/packages/block-library/src/comment-reply-link/block.json b/packages/block-library/src/comment-reply-link/block.json index c10129412145c..6accfffa4b70a 100644 --- a/packages/block-library/src/comment-reply-link/block.json +++ b/packages/block-library/src/comment-reply-link/block.json @@ -41,5 +41,6 @@ } }, "html": false - } + }, + "editorScript": "file:./editor.min.js" } diff --git a/packages/block-library/src/comment-template/block.json b/packages/block-library/src/comment-template/block.json index 7b9bfc5e0340f..59129c0efda74 100644 --- a/packages/block-library/src/comment-template/block.json +++ b/packages/block-library/src/comment-template/block.json @@ -30,5 +30,7 @@ } } }, - "style": "wp-block-comment-template" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/comments-pagination-next/block.json b/packages/block-library/src/comments-pagination-next/block.json index d619865ebd6f5..3328a2f55fc66 100644 --- a/packages/block-library/src/comments-pagination-next/block.json +++ b/packages/block-library/src/comments-pagination-next/block.json @@ -36,5 +36,6 @@ "fontSize": true } } - } + }, + "editorScript": "file:./editor.min.js" } diff --git a/packages/block-library/src/comments-pagination-numbers/block.json b/packages/block-library/src/comments-pagination-numbers/block.json index fcebb52763870..fe4d86e83e99d 100644 --- a/packages/block-library/src/comments-pagination-numbers/block.json +++ b/packages/block-library/src/comments-pagination-numbers/block.json @@ -31,5 +31,7 @@ "fontSize": true } } - } + }, + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css" } diff --git a/packages/block-library/src/comments-pagination-previous/block.json b/packages/block-library/src/comments-pagination-previous/block.json index 2dab1e9dd7367..da9e127b4cbb7 100644 --- a/packages/block-library/src/comments-pagination-previous/block.json +++ b/packages/block-library/src/comments-pagination-previous/block.json @@ -36,5 +36,6 @@ "fontSize": true } } - } + }, + "editorScript": "file:./editor.min.js" } diff --git a/packages/block-library/src/comments-pagination/block.json b/packages/block-library/src/comments-pagination/block.json index a11decd201e94..5f9043a7eb450 100644 --- a/packages/block-library/src/comments-pagination/block.json +++ b/packages/block-library/src/comments-pagination/block.json @@ -50,6 +50,7 @@ } } }, - "editorStyle": "wp-block-comments-pagination-editor", - "style": "wp-block-comments-pagination" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/comments-title/block.json b/packages/block-library/src/comments-title/block.json index 4107f5d590cde..796f9f96c4e07 100644 --- a/packages/block-library/src/comments-title/block.json +++ b/packages/block-library/src/comments-title/block.json @@ -62,5 +62,7 @@ "__experimentalFontWeight": true } } - } + }, + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css" } diff --git a/packages/block-library/src/comments/block.json b/packages/block-library/src/comments/block.json index b35ea3505c816..3f6af4aef1156 100644 --- a/packages/block-library/src/comments/block.json +++ b/packages/block-library/src/comments/block.json @@ -47,6 +47,7 @@ } } }, - "editorStyle": "wp-block-comments-editor", - "usesContext": [ "postId", "postType" ] + "usesContext": [ "postId", "postType" ], + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css" } diff --git a/packages/block-library/src/cover/block.json b/packages/block-library/src/cover/block.json index d2c55dd26b4d7..78a1914f528ad 100644 --- a/packages/block-library/src/cover/block.json +++ b/packages/block-library/src/cover/block.json @@ -131,6 +131,7 @@ "allowJustification": false } }, - "editorStyle": "wp-block-cover-editor", - "style": "wp-block-cover" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/details/block.json b/packages/block-library/src/details/block.json index a71d3af2a5ed3..4d74f629a2da0 100644 --- a/packages/block-library/src/details/block.json +++ b/packages/block-library/src/details/block.json @@ -60,6 +60,7 @@ "allowEditing": false } }, - "editorStyle": "wp-block-details-editor", - "style": "wp-block-details" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/embed/block.json b/packages/block-library/src/embed/block.json index 5aac8bbd6b8ca..eb0c6b6e499be 100644 --- a/packages/block-library/src/embed/block.json +++ b/packages/block-library/src/embed/block.json @@ -46,6 +46,7 @@ "margin": true } }, - "editorStyle": "wp-block-embed-editor", - "style": "wp-block-embed" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/file/block.json b/packages/block-library/src/file/block.json index 9dc6677e4adce..f18c47f875c70 100644 --- a/packages/block-library/src/file/block.json +++ b/packages/block-library/src/file/block.json @@ -73,6 +73,7 @@ "interactivity": true }, "viewScript": "file:./view.min.js", - "editorStyle": "wp-block-file-editor", - "style": "wp-block-file" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:/style.css" } diff --git a/packages/block-library/src/footnotes/block.json b/packages/block-library/src/footnotes/block.json index 3192df7796978..018933d991313 100644 --- a/packages/block-library/src/footnotes/block.json +++ b/packages/block-library/src/footnotes/block.json @@ -57,5 +57,7 @@ } } }, - "style": "wp-block-footnotes" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/freeform/block.json b/packages/block-library/src/freeform/block.json index d40e8ea13dc11..42257f88be075 100644 --- a/packages/block-library/src/freeform/block.json +++ b/packages/block-library/src/freeform/block.json @@ -17,5 +17,6 @@ "customClassName": false, "reusable": false }, - "editorStyle": "wp-block-freeform-editor" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css" } diff --git a/packages/block-library/src/gallery/block.json b/packages/block-library/src/gallery/block.json index fad92aed59bf7..f2e14a116058f 100644 --- a/packages/block-library/src/gallery/block.json +++ b/packages/block-library/src/gallery/block.json @@ -134,6 +134,7 @@ } } }, - "editorStyle": "wp-block-gallery-editor", - "style": "wp-block-gallery" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/group/block.json b/packages/block-library/src/group/block.json index 92bbc1b0d1135..9c4e73acce23d 100644 --- a/packages/block-library/src/group/block.json +++ b/packages/block-library/src/group/block.json @@ -85,6 +85,7 @@ "allowSizingOnChildren": true } }, - "editorStyle": "wp-block-group-editor", - "style": "wp-block-group" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/heading/block.json b/packages/block-library/src/heading/block.json index 72cc67caddd9e..bac67ab9489c8 100644 --- a/packages/block-library/src/heading/block.json +++ b/packages/block-library/src/heading/block.json @@ -62,6 +62,7 @@ "__unstablePasteTextInline": true, "__experimentalSlashInserter": true }, - "editorStyle": "wp-block-heading-editor", - "style": "wp-block-heading" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/home-link/block.json b/packages/block-library/src/home-link/block.json index a9827b7718b9b..8eaa42c989fbb 100644 --- a/packages/block-library/src/home-link/block.json +++ b/packages/block-library/src/home-link/block.json @@ -38,6 +38,5 @@ } } }, - "editorStyle": "wp-block-home-link-editor", - "style": "wp-block-home-link" + "editorScript": "file:./editor.min.js" } diff --git a/packages/block-library/src/html/block.json b/packages/block-library/src/html/block.json index b1a2ad60625d1..4c4b010624ae0 100644 --- a/packages/block-library/src/html/block.json +++ b/packages/block-library/src/html/block.json @@ -18,5 +18,6 @@ "className": false, "html": false }, - "editorStyle": "wp-block-html-editor" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css" } diff --git a/packages/block-library/src/image/block.json b/packages/block-library/src/image/block.json index c5191e3dd8654..806f1fb5341a8 100644 --- a/packages/block-library/src/image/block.json +++ b/packages/block-library/src/image/block.json @@ -128,7 +128,8 @@ }, { "name": "rounded", "label": "Rounded" } ], - "editorStyle": "wp-block-image-editor", - "style": "wp-block-image", + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css", "viewScript": "file:./view.min.js" } 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/latest-comments/block.json b/packages/block-library/src/latest-comments/block.json index 0b213e9b7903a..23dc1038abd7e 100644 --- a/packages/block-library/src/latest-comments/block.json +++ b/packages/block-library/src/latest-comments/block.json @@ -48,6 +48,7 @@ } } }, - "editorStyle": "wp-block-latest-comments-editor", - "style": "wp-block-latest-comments" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/latest-posts/block.json b/packages/block-library/src/latest-posts/block.json index f36164614dd50..83cae6049bb48 100644 --- a/packages/block-library/src/latest-posts/block.json +++ b/packages/block-library/src/latest-posts/block.json @@ -112,6 +112,7 @@ } } }, - "editorStyle": "wp-block-latest-posts-editor", - "style": "wp-block-latest-posts" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/list-item/block.json b/packages/block-library/src/list-item/block.json index 06997c2ac23f8..ba7dbb5595f4b 100644 --- a/packages/block-library/src/list-item/block.json +++ b/packages/block-library/src/list-item/block.json @@ -42,5 +42,6 @@ "fontSize": true } } - } + }, + "editorScript": "file:./editor.min.js" } diff --git a/packages/block-library/src/list-item/edit.js b/packages/block-library/src/list-item/edit.js index 7733a76280752..d31f26555eefc 100644 --- a/packages/block-library/src/list-item/edit.js +++ b/packages/block-library/src/list-item/edit.js @@ -106,9 +106,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/list/block.json b/packages/block-library/src/list/block.json index e2fb9e4c9e3b0..e3b2f055fe719 100644 --- a/packages/block-library/src/list/block.json +++ b/packages/block-library/src/list/block.json @@ -72,6 +72,7 @@ "__experimentalOnMerge": true, "__experimentalSlashInserter": true }, - "editorStyle": "wp-block-list-editor", - "style": "wp-block-list" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/loginout/block.json b/packages/block-library/src/loginout/block.json index 59fceec596e37..178ab12544ee3 100644 --- a/packages/block-library/src/loginout/block.json +++ b/packages/block-library/src/loginout/block.json @@ -40,5 +40,6 @@ "fontSize": true } } - } + }, + "editorScript": "file:./editor.min.js" } diff --git a/packages/block-library/src/media-text/block.json b/packages/block-library/src/media-text/block.json index cdeb4ce13e8f5..227417cd5723b 100644 --- a/packages/block-library/src/media-text/block.json +++ b/packages/block-library/src/media-text/block.json @@ -125,6 +125,7 @@ } } }, - "editorStyle": "wp-block-media-text-editor", - "style": "wp-block-media-text" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/missing/block.json b/packages/block-library/src/missing/block.json index 242a1d2c6b21a..0aef889ad0f33 100644 --- a/packages/block-library/src/missing/block.json +++ b/packages/block-library/src/missing/block.json @@ -24,5 +24,6 @@ "inserter": false, "html": false, "reusable": false - } + }, + "editorScript": "file:./editor.min.js" } diff --git a/packages/block-library/src/more/block.json b/packages/block-library/src/more/block.json index bfd95652ea176..5e4c115da9bd9 100644 --- a/packages/block-library/src/more/block.json +++ b/packages/block-library/src/more/block.json @@ -22,5 +22,6 @@ "html": false, "multiple": false }, - "editorStyle": "wp-block-more-editor" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css" } diff --git a/packages/block-library/src/navigation-link/block.json b/packages/block-library/src/navigation-link/block.json index d8f2fe31aef9d..352c4f8a21c97 100644 --- a/packages/block-library/src/navigation-link/block.json +++ b/packages/block-library/src/navigation-link/block.json @@ -74,6 +74,7 @@ }, "renaming": false }, - "editorStyle": "wp-block-navigation-link-editor", - "style": "wp-block-navigation-link" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } 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 ( <Button key={ `transform-${ index }` } - onClick={ () => + onClick={ async () => replaceBlock( clientId, - switchToBlockType( + await switchToBlockType( getBlock( clientId ), item.name ) diff --git a/packages/block-library/src/navigation-submenu/block.json b/packages/block-library/src/navigation-submenu/block.json index 91364109ea740..17deaccf7220f 100644 --- a/packages/block-library/src/navigation-submenu/block.json +++ b/packages/block-library/src/navigation-submenu/block.json @@ -60,6 +60,6 @@ "reusable": false, "html": false }, - "editorStyle": "wp-block-navigation-submenu-editor", - "style": "wp-block-navigation-submenu" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css" } diff --git a/packages/block-library/src/navigation/block.json b/packages/block-library/src/navigation/block.json index 9ec919ae38d1f..bfc9bbd351398 100644 --- a/packages/block-library/src/navigation/block.json +++ b/packages/block-library/src/navigation/block.json @@ -137,6 +137,7 @@ "renaming": false }, "viewScript": "file:./view.min.js", - "editorStyle": "wp-block-navigation-editor", - "style": "wp-block-navigation" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/nextpage/block.json b/packages/block-library/src/nextpage/block.json index ab88d4a7be4f0..bfd9a4ca516b0 100644 --- a/packages/block-library/src/nextpage/block.json +++ b/packages/block-library/src/nextpage/block.json @@ -13,5 +13,6 @@ "className": false, "html": false }, - "editorStyle": "wp-block-nextpage-editor" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css" } diff --git a/packages/block-library/src/page-list-item/block.json b/packages/block-library/src/page-list-item/block.json index abd86924949ab..40ceb51e3bfb8 100644 --- a/packages/block-library/src/page-list-item/block.json +++ b/packages/block-library/src/page-list-item/block.json @@ -47,6 +47,5 @@ "inserter": false, "__experimentalToolbar": false }, - "editorStyle": "wp-block-page-list-editor", - "style": "wp-block-page-list" + "editorScript": "file:./editor.min.js" } diff --git a/packages/block-library/src/page-list/block.json b/packages/block-library/src/page-list/block.json index 7f4f2ce86c425..d58b2bf8a070a 100644 --- a/packages/block-library/src/page-list/block.json +++ b/packages/block-library/src/page-list/block.json @@ -49,6 +49,7 @@ } } }, - "editorStyle": "wp-block-page-list-editor", - "style": "wp-block-page-list" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/page-list/edit.js b/packages/block-library/src/page-list/edit.js index 8f21f781396c6..214e93d73a8f6 100644 --- a/packages/block-library/src/page-list/edit.js +++ b/packages/block-library/src/page-list/edit.js @@ -113,6 +113,31 @@ function BlockContent( { } } +function getBlockList( parentId, pagesByParentId ) { + const childPages = pagesByParentId.get( parentId ); + + if ( ! childPages?.length ) { + return []; + } + + return childPages.map( ( page ) => { + const hasChildren = pagesByParentId.has( page.id ); + const pageProps = { + id: page.id, + label: + // translators: displayed when a page has an empty title. + page.title?.rendered?.trim() !== '' + ? page.title?.rendered + : __( '(no title)' ), + title: page.title?.rendered, + link: page.url, + hasChildren, + }; + const children = getBlockList( page.id, pagesByParentId ); + return createBlock( 'core/page-list-item', pageProps, children ); + } ); +} + export default function PageListEdit( { context, clientId, @@ -209,39 +234,8 @@ export default function PageListEdit( { ); const blockList = useMemo( - function getBlockList( parentId = parentPageID ) { - const childPages = pagesByParentId.get( parentId ); - - if ( ! childPages?.length ) { - return []; - } - - return childPages.reduce( ( template, page ) => { - const hasChildren = pagesByParentId.has( page.id ); - const pageProps = { - id: page.id, - label: - // translators: displayed when a page has an empty title. - page.title?.rendered?.trim() !== '' - ? page.title?.rendered - : __( '(no title)' ), - title: page.title?.rendered, - link: page.url, - hasChildren, - }; - let item = null; - const children = getBlockList( page.id ); - item = createBlock( - 'core/page-list-item', - pageProps, - children - ); - template.push( item ); - - return template; - }, [] ); - }, - [ pagesByParentId, parentPageID ] + () => getBlockList( parentPageID, pagesByParentId ), + [ parentPageID, pagesByParentId ] ); const { diff --git a/packages/block-library/src/paragraph/block.json b/packages/block-library/src/paragraph/block.json index 3fe4fbb34e102..7aeb77fe8e9cd 100644 --- a/packages/block-library/src/paragraph/block.json +++ b/packages/block-library/src/paragraph/block.json @@ -67,6 +67,7 @@ "__experimentalSelector": "p", "__unstablePasteTextInline": true }, - "editorStyle": "wp-block-paragraph-editor", - "style": "wp-block-paragraph" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/pattern/block.json b/packages/block-library/src/pattern/block.json index da02f7b72747e..2770f99de1dfb 100644 --- a/packages/block-library/src/pattern/block.json +++ b/packages/block-library/src/pattern/block.json @@ -15,5 +15,6 @@ "slug": { "type": "string" } - } + }, + "editorScript": "file:./editor.min.js" } diff --git a/packages/block-library/src/post-author-biography/block.json b/packages/block-library/src/post-author-biography/block.json index 5d7a4d4585747..6612f278f42a4 100644 --- a/packages/block-library/src/post-author-biography/block.json +++ b/packages/block-library/src/post-author-biography/block.json @@ -38,5 +38,6 @@ "fontSize": true } } - } + }, + "editorScript": "file:./editor.min.js" } diff --git a/packages/block-library/src/post-author-name/block.json b/packages/block-library/src/post-author-name/block.json index 89e4b38de2c28..a70ac2047bb09 100644 --- a/packages/block-library/src/post-author-name/block.json +++ b/packages/block-library/src/post-author-name/block.json @@ -48,5 +48,6 @@ "fontSize": true } } - } + }, + "editorScript": "file:./editor.min.js" } diff --git a/packages/block-library/src/post-author/block.json b/packages/block-library/src/post-author/block.json index 47dceef55604f..6d75ca1f08371 100644 --- a/packages/block-library/src/post-author/block.json +++ b/packages/block-library/src/post-author/block.json @@ -63,5 +63,6 @@ } } }, - "style": "wp-block-post-author" + "editorScript": "file:./editor.min.js", + "style": "file:./style.css" } diff --git a/packages/block-library/src/post-comment/block.json b/packages/block-library/src/post-comment/block.json index 85bdb7dd6cf32..9cae6b88750c8 100644 --- a/packages/block-library/src/post-comment/block.json +++ b/packages/block-library/src/post-comment/block.json @@ -18,5 +18,6 @@ "supports": { "html": false, "inserter": false - } + }, + "editorScript": "file:./editor.min.js" } diff --git a/packages/block-library/src/post-comments-count/block.json b/packages/block-library/src/post-comments-count/block.json index 43c1aaf713776..ab78b46044848 100644 --- a/packages/block-library/src/post-comments-count/block.json +++ b/packages/block-library/src/post-comments-count/block.json @@ -39,5 +39,6 @@ "fontSize": true } } - } + }, + "editorScript": "file:./editor.min.js" } diff --git a/packages/block-library/src/post-comments-form/block.json b/packages/block-library/src/post-comments-form/block.json index ff157beb5ced9..ed04ce0cf4a41 100644 --- a/packages/block-library/src/post-comments-form/block.json +++ b/packages/block-library/src/post-comments-form/block.json @@ -39,10 +39,7 @@ } } }, - "editorStyle": "wp-block-post-comments-form-editor", - "style": [ - "wp-block-post-comments-form", - "wp-block-buttons", - "wp-block-button" - ] + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": [ "file:./style.css", "wp-block-buttons", "wp-block-button" ] } diff --git a/packages/block-library/src/post-comments-link/block.json b/packages/block-library/src/post-comments-link/block.json index 74e268c3c20b1..7cbe667d1e64f 100644 --- a/packages/block-library/src/post-comments-link/block.json +++ b/packages/block-library/src/post-comments-link/block.json @@ -40,5 +40,6 @@ "fontSize": true } } - } + }, + "editorScript": "file:./editor.min.js" } diff --git a/packages/block-library/src/post-content/block.json b/packages/block-library/src/post-content/block.json index b0e0487a0b824..c4b4fc5b896d8 100644 --- a/packages/block-library/src/post-content/block.json +++ b/packages/block-library/src/post-content/block.json @@ -39,5 +39,5 @@ } } }, - "editorStyle": "wp-block-post-content-editor" + "editorScript": "file:./editor.min.js" } diff --git a/packages/block-library/src/post-date/block.json b/packages/block-library/src/post-date/block.json index 11ebc32d9cabe..1efddccc0baa6 100644 --- a/packages/block-library/src/post-date/block.json +++ b/packages/block-library/src/post-date/block.json @@ -51,5 +51,7 @@ "fontSize": true } } - } + }, + "editorScript": "file:./editor.min.js", + "style": "file:./style.css" } diff --git a/packages/block-library/src/post-excerpt/block.json b/packages/block-library/src/post-excerpt/block.json index 33b7818ebed9f..a38491c618d0a 100644 --- a/packages/block-library/src/post-excerpt/block.json +++ b/packages/block-library/src/post-excerpt/block.json @@ -52,6 +52,7 @@ } } }, - "editorStyle": "wp-block-post-excerpt-editor", - "style": "wp-block-post-excerpt" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/post-featured-image/block.json b/packages/block-library/src/post-featured-image/block.json index 34e3bd6b2325f..2b62692bd2c10 100644 --- a/packages/block-library/src/post-featured-image/block.json +++ b/packages/block-library/src/post-featured-image/block.json @@ -79,6 +79,7 @@ "padding": true } }, - "editorStyle": "wp-block-post-featured-image-editor", - "style": "wp-block-post-featured-image" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/post-navigation-link/block.json b/packages/block-library/src/post-navigation-link/block.json index e1b6d4fa90a40..fa7467108d0c1 100644 --- a/packages/block-library/src/post-navigation-link/block.json +++ b/packages/block-library/src/post-navigation-link/block.json @@ -51,5 +51,6 @@ } } }, - "style": "wp-block-post-navigation-link" + "editorScript": "file:./editor.min.js", + "style": "file:./style.css" } diff --git a/packages/block-library/src/post-template/block.json b/packages/block-library/src/post-template/block.json index d2f7c09693121..d08d6aebaaf29 100644 --- a/packages/block-library/src/post-template/block.json +++ b/packages/block-library/src/post-template/block.json @@ -50,6 +50,7 @@ } } }, - "style": "wp-block-post-template", - "editorStyle": "wp-block-post-template-editor" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/post-terms/block.json b/packages/block-library/src/post-terms/block.json index 0da7fb02f8134..f8a5108ae4857 100644 --- a/packages/block-library/src/post-terms/block.json +++ b/packages/block-library/src/post-terms/block.json @@ -56,5 +56,6 @@ } } }, - "style": "wp-block-post-terms" + "editorScript": "file:./editor.min.js", + "style": "file:./style.css" } diff --git a/packages/block-library/src/post-time-to-read/block.json b/packages/block-library/src/post-time-to-read/block.json index 281e9bb1f1b21..396748e5a28fa 100644 --- a/packages/block-library/src/post-time-to-read/block.json +++ b/packages/block-library/src/post-time-to-read/block.json @@ -43,5 +43,7 @@ "fontSize": true } } - } + }, + "editorScript": "file:./editor.min.js", + "style": "file:./style.css" } diff --git a/packages/block-library/src/post-title/block.json b/packages/block-library/src/post-title/block.json index 75a4fa3c3a60f..37e8cd9a52568 100644 --- a/packages/block-library/src/post-title/block.json +++ b/packages/block-library/src/post-title/block.json @@ -59,5 +59,6 @@ } } }, - "style": "wp-block-post-title" + "editorScript": "file:./editor.min.js", + "style": "file:./style.css" } diff --git a/packages/block-library/src/preformatted/block.json b/packages/block-library/src/preformatted/block.json index def870e7ad2fb..b8ab601764f81 100644 --- a/packages/block-library/src/preformatted/block.json +++ b/packages/block-library/src/preformatted/block.json @@ -42,5 +42,6 @@ } } }, - "style": "wp-block-preformatted" + "editorScript": "file:./editor.min.js", + "style": "file:./style.css" } diff --git a/packages/block-library/src/pullquote/block.json b/packages/block-library/src/pullquote/block.json index 7fc81d5683bd1..92f0b8645a6e3 100644 --- a/packages/block-library/src/pullquote/block.json +++ b/packages/block-library/src/pullquote/block.json @@ -67,6 +67,7 @@ } } }, - "editorStyle": "wp-block-pullquote-editor", - "style": "wp-block-pullquote" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/query-no-results/block.json b/packages/block-library/src/query-no-results/block.json index 32088752bb060..8656db22b4a90 100644 --- a/packages/block-library/src/query-no-results/block.json +++ b/packages/block-library/src/query-no-results/block.json @@ -29,5 +29,6 @@ "fontSize": true } } - } + }, + "editorScript": "file:./editor.min.js" } diff --git a/packages/block-library/src/query-pagination-next/block.json b/packages/block-library/src/query-pagination-next/block.json index 95b1169dc992f..de5c921abb605 100644 --- a/packages/block-library/src/query-pagination-next/block.json +++ b/packages/block-library/src/query-pagination-next/block.json @@ -42,5 +42,6 @@ "fontSize": true } } - } + }, + "editorScript": "file:./editor.min.js" } diff --git a/packages/block-library/src/query-pagination-numbers/block.json b/packages/block-library/src/query-pagination-numbers/block.json index f22d88115d68c..caba49d73800c 100644 --- a/packages/block-library/src/query-pagination-numbers/block.json +++ b/packages/block-library/src/query-pagination-numbers/block.json @@ -38,5 +38,6 @@ } } }, - "editorStyle": "wp-block-query-pagination-numbers-editor" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css" } diff --git a/packages/block-library/src/query-pagination-previous/block.json b/packages/block-library/src/query-pagination-previous/block.json index fbaac543c1da3..68a0912c2e49b 100644 --- a/packages/block-library/src/query-pagination-previous/block.json +++ b/packages/block-library/src/query-pagination-previous/block.json @@ -42,5 +42,6 @@ "fontSize": true } } - } + }, + "editorScript": "file:./editor.min.js" } diff --git a/packages/block-library/src/query-pagination/block.json b/packages/block-library/src/query-pagination/block.json index e32a9ba9b495f..db55e141ab4d3 100644 --- a/packages/block-library/src/query-pagination/block.json +++ b/packages/block-library/src/query-pagination/block.json @@ -56,6 +56,7 @@ } } }, - "editorStyle": "wp-block-query-pagination-editor", - "style": "wp-block-query-pagination" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/query-title/block.json b/packages/block-library/src/query-title/block.json index 65eb03d310c12..0f30f8b8342ce 100644 --- a/packages/block-library/src/query-title/block.json +++ b/packages/block-library/src/query-title/block.json @@ -54,5 +54,6 @@ } } }, - "style": "wp-block-query-title" + "editorScript": "file:./editor.min.js", + "style": "file:./style.css" } diff --git a/packages/block-library/src/query/block.json b/packages/block-library/src/query/block.json index d30eccf376579..a81b6361b784f 100644 --- a/packages/block-library/src/query/block.json +++ b/packages/block-library/src/query/block.json @@ -51,7 +51,7 @@ "html": false, "layout": true }, - "editorStyle": "wp-block-query-editor", - "style": "wp-block-query", + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", "viewScript": "file:./view.min.js" } diff --git a/packages/block-library/src/quote/block.json b/packages/block-library/src/quote/block.json index 9deca000efe06..83abf63892df8 100644 --- a/packages/block-library/src/quote/block.json +++ b/packages/block-library/src/quote/block.json @@ -66,8 +66,11 @@ "label": "Default", "isDefault": true }, - { "name": "plain", "label": "Plain" } + { + "name": "plain", + "label": "Plain" + } ], - "editorStyle": "wp-block-quote-editor", - "style": "wp-block-quote" + "editorScript": "file:./editor.min.js", + "style": "file:./style.css" } diff --git a/packages/block-library/src/read-more/block.json b/packages/block-library/src/read-more/block.json index d3386a49d66b8..bf762a264be3d 100644 --- a/packages/block-library/src/read-more/block.json +++ b/packages/block-library/src/read-more/block.json @@ -52,5 +52,6 @@ } } }, - "style": "wp-block-read-more" + "editorScript": "file:./editor.min.js", + "style": "file:./style.css" } diff --git a/packages/block-library/src/rss/block.json b/packages/block-library/src/rss/block.json index 2535eda5946fb..7aa549f54a275 100644 --- a/packages/block-library/src/rss/block.json +++ b/packages/block-library/src/rss/block.json @@ -45,6 +45,7 @@ "align": true, "html": false }, - "editorStyle": "wp-block-rss-editor", - "style": "wp-block-rss" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/search/block.json b/packages/block-library/src/search/block.json index 5669a9089d0e0..a56ced7ca9818 100644 --- a/packages/block-library/src/search/block.json +++ b/packages/block-library/src/search/block.json @@ -92,6 +92,7 @@ "html": false }, "viewScript": "file:./view.min.js", - "editorStyle": "wp-block-search-editor", - "style": "wp-block-search" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/separator/block.json b/packages/block-library/src/separator/block.json index 970f6b5cbb582..0e301c50ccc08 100644 --- a/packages/block-library/src/separator/block.json +++ b/packages/block-library/src/separator/block.json @@ -31,10 +31,21 @@ } }, "styles": [ - { "name": "default", "label": "Default", "isDefault": true }, - { "name": "wide", "label": "Wide Line" }, - { "name": "dots", "label": "Dots" } + { + "name": "default", + "label": "Default", + "isDefault": true + }, + { + "name": "wide", + "label": "Wide Line" + }, + { + "name": "dots", + "label": "Dots" + } ], - "editorStyle": "wp-block-separator-editor", - "style": "wp-block-separator" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/shortcode/block.json b/packages/block-library/src/shortcode/block.json index 22d838a7198e1..186e15ec0d6a1 100644 --- a/packages/block-library/src/shortcode/block.json +++ b/packages/block-library/src/shortcode/block.json @@ -17,5 +17,6 @@ "customClassName": false, "html": false }, - "editorStyle": "wp-block-shortcode-editor" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css" } diff --git a/packages/block-library/src/site-logo/block.json b/packages/block-library/src/site-logo/block.json index d1e3d1b20c3da..68ef12956bce8 100644 --- a/packages/block-library/src/site-logo/block.json +++ b/packages/block-library/src/site-logo/block.json @@ -53,8 +53,12 @@ "label": "Default", "isDefault": true }, - { "name": "rounded", "label": "Rounded" } + { + "name": "rounded", + "label": "Rounded" + } ], - "editorStyle": "wp-block-site-logo-editor", - "style": "wp-block-site-logo" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/site-tagline/block.json b/packages/block-library/src/site-tagline/block.json index 22fb59aab5ead..46cc79876b1b6 100644 --- a/packages/block-library/src/site-tagline/block.json +++ b/packages/block-library/src/site-tagline/block.json @@ -45,5 +45,6 @@ } } }, - "editorStyle": "wp-block-site-tagline-editor" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css" } diff --git a/packages/block-library/src/site-title/block.json b/packages/block-library/src/site-title/block.json index 4a2685e6941fc..f8e07a92bd6b4 100644 --- a/packages/block-library/src/site-title/block.json +++ b/packages/block-library/src/site-title/block.json @@ -60,6 +60,6 @@ } } }, - "editorStyle": "wp-block-site-title-editor", - "style": "wp-block-site-title" + "editorScript": "file:./editor.min.js", + "style": "file:./style.css" } diff --git a/packages/block-library/src/social-link/block.json b/packages/block-library/src/social-link/block.json index 50e95efedb630..e1c76c2c311db 100644 --- a/packages/block-library/src/social-link/block.json +++ b/packages/block-library/src/social-link/block.json @@ -33,5 +33,6 @@ "reusable": false, "html": false }, - "editorStyle": "wp-block-social-link-editor" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css" } diff --git a/packages/block-library/src/social-links/block.json b/packages/block-library/src/social-links/block.json index 20206511a4c96..3dc3e8444e4c9 100644 --- a/packages/block-library/src/social-links/block.json +++ b/packages/block-library/src/social-links/block.json @@ -80,10 +80,21 @@ } }, "styles": [ - { "name": "default", "label": "Default", "isDefault": true }, - { "name": "logos-only", "label": "Logos Only" }, - { "name": "pill-shape", "label": "Pill Shape" } + { + "name": "default", + "label": "Default", + "isDefault": true + }, + { + "name": "logos-only", + "label": "Logos Only" + }, + { + "name": "pill-shape", + "label": "Pill Shape" + } ], - "editorStyle": "wp-block-social-links-editor", - "style": "wp-block-social-links" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/spacer/block.json b/packages/block-library/src/spacer/block.json index a9da8d537f1b6..3fa552b181b20 100644 --- a/packages/block-library/src/spacer/block.json +++ b/packages/block-library/src/spacer/block.json @@ -25,6 +25,7 @@ } } }, - "editorStyle": "wp-block-spacer-editor", - "style": "wp-block-spacer" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/table-of-contents/block.json b/packages/block-library/src/table-of-contents/block.json index 5fa7e37e6acbd..db1db3a47bdcb 100644 --- a/packages/block-library/src/table-of-contents/block.json +++ b/packages/block-library/src/table-of-contents/block.json @@ -47,5 +47,6 @@ } } }, - "example": {} + "example": {}, + "editorScript": "file:./editor.min.js" } diff --git a/packages/block-library/src/table/block.json b/packages/block-library/src/table/block.json index 470886a1247fe..eb16dc9afd99c 100644 --- a/packages/block-library/src/table/block.json +++ b/packages/block-library/src/table/block.json @@ -205,6 +205,7 @@ }, { "name": "stripes", "label": "Stripes" } ], - "editorStyle": "wp-block-table-editor", - "style": "wp-block-table" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/tag-cloud/block.json b/packages/block-library/src/tag-cloud/block.json index 9481dc945666a..1f62518635eba 100644 --- a/packages/block-library/src/tag-cloud/block.json +++ b/packages/block-library/src/tag-cloud/block.json @@ -50,5 +50,6 @@ "__experimentalLetterSpacing": true } }, - "editorStyle": "wp-block-tag-cloud-editor" + "editorScript": "file:./editor.min.js", + "style": "file:./style.css" } diff --git a/packages/block-library/src/template-part/block.json b/packages/block-library/src/template-part/block.json index 3b0946718bcb9..2cd4c04a7a88f 100644 --- a/packages/block-library/src/template-part/block.json +++ b/packages/block-library/src/template-part/block.json @@ -26,5 +26,6 @@ "reusable": false, "renaming": false }, - "editorStyle": "wp-block-template-part-editor" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css" } diff --git a/packages/block-library/src/template-part/edit/utils/transformers.js b/packages/block-library/src/template-part/edit/utils/transformers.js index 7932a00572941..449e914d5f793 100644 --- a/packages/block-library/src/template-part/edit/utils/transformers.js +++ b/packages/block-library/src/template-part/edit/utils/transformers.js @@ -70,31 +70,31 @@ export function transformWidgetToBlock( widget ) { * @param {Object} block Legacy Widget block object * @return {Object|undefined} a block */ -function switchLegacyWidgetType( block ) { - const transforms = getPossibleBlockTransformations( [ block ] ).filter( - ( item ) => { - // The block without any transformations can't be a wildcard. - if ( ! item.transforms ) { - return true; - } +async function switchLegacyWidgetType( block ) { + const transforms = ( + await getPossibleBlockTransformations( [ block ] ) + ).filter( ( item ) => { + // The block without any transformations can't be a wildcard. + if ( ! item.transforms ) { + return true; + } - const hasWildCardFrom = item.transforms?.from?.find( - ( from ) => from.blocks && from.blocks.includes( '*' ) - ); - const hasWildCardTo = item.transforms?.to?.find( - ( to ) => to.blocks && to.blocks.includes( '*' ) - ); + const hasWildCardFrom = item.transforms.from?.some( ( from ) => + from.blocks?.includes( '*' ) + ); + const hasWildCardTo = item.transforms.to?.find( + ( to ) => to.blocks && to.blocks.includes( '*' ) + ); - // Skip wildcard transformations. - return ! hasWildCardFrom && ! hasWildCardTo; - } - ); + // Skip wildcard transformations. + return ! hasWildCardFrom && ! hasWildCardTo; + } ); if ( ! transforms.length ) { return undefined; } - return switchToBlockType( block, transforms[ 0 ].name ); + return await switchToBlockType( block, transforms[ 0 ].name ); } function transformInnerBlocks( innerBlocks = [] ) { diff --git a/packages/block-library/src/term-description/block.json b/packages/block-library/src/term-description/block.json index fc91a4aff4c48..4739962774217 100644 --- a/packages/block-library/src/term-description/block.json +++ b/packages/block-library/src/term-description/block.json @@ -38,5 +38,7 @@ "fontSize": true } } - } + }, + "editorScript": "file:./editor.min.js", + "style": "file:./style.css" } diff --git a/packages/block-library/src/text-columns/block.json b/packages/block-library/src/text-columns/block.json index 3af169fadbb3b..0cd8a1963bfc2 100644 --- a/packages/block-library/src/text-columns/block.json +++ b/packages/block-library/src/text-columns/block.json @@ -31,6 +31,7 @@ "supports": { "inserter": false }, - "editorStyle": "wp-block-text-columns-editor", - "style": "wp-block-text-columns" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/block-library/src/verse/block.json b/packages/block-library/src/verse/block.json index 846a1dc99caaf..f9cff98235e28 100644 --- a/packages/block-library/src/verse/block.json +++ b/packages/block-library/src/verse/block.json @@ -57,6 +57,6 @@ "style": true } }, - "style": "wp-block-verse", - "editorStyle": "wp-block-verse-editor" + "editorScript": "file:./editor.min.js", + "style": "file:./style.css" } diff --git a/packages/block-library/src/video/block.json b/packages/block-library/src/video/block.json index 5d4680f39e79a..adfd1321bdd9a 100644 --- a/packages/block-library/src/video/block.json +++ b/packages/block-library/src/video/block.json @@ -90,6 +90,7 @@ } } }, - "editorStyle": "wp-block-video-editor", - "style": "wp-block-video" + "editorScript": "file:./editor.min.js", + "editorStyle": "file:./editor.css", + "style": "file:./style.css" } diff --git a/packages/blocks/README.md b/packages/blocks/README.md index 8e6fdc9d900db..0022738d67c8d 100644 --- a/packages/blocks/README.md +++ b/packages/blocks/README.md @@ -198,6 +198,14 @@ _Returns_ - `Array`: Block settings. +### getBootstrappedBlockType + +Undocumented declaration. + +### getBootstrappedBlockTypes + +Undocumented declaration. + ### getChildBlockNames Returns an array with the child blocks of a given block. @@ -278,6 +286,10 @@ _Returns_ - `Object|string`: Save element or raw HTML string. +### getTransformItemsForBlocks + +Undocumented declaration. + ### getUnregisteredTypeHandlerName Retrieves name of block handling unregistered block types, or undefined if no handler has been defined. diff --git a/packages/blocks/src/api/factory.js b/packages/blocks/src/api/factory.js index 53333ef688085..2846164be5c3f 100644 --- a/packages/blocks/src/api/factory.js +++ b/packages/blocks/src/api/factory.js @@ -13,7 +13,8 @@ import { createHooks, applyFilters } from '@wordpress/hooks'; */ import { getBlockType, - getBlockTypes, + loadBlockType, + loadBlockTypes, getGroupingBlockName, } from './registration'; import { @@ -153,6 +154,11 @@ export function cloneBlock( block, mergeAttributes = {}, newInnerBlocks ) { * @return {boolean} Is the transform possible? */ const isPossibleTransformForSource = ( transform, direction, blocks ) => { + // Only consider 'block' type transforms as valid. + if ( transform.type !== 'block' ) { + return false; + } + if ( ! blocks.length ) { return false; } @@ -160,38 +166,29 @@ const isPossibleTransformForSource = ( transform, direction, blocks ) => { // If multiple blocks are selected, only multi block transforms // or wildcard transforms are allowed. const isMultiBlock = blocks.length > 1; - const firstBlockName = blocks[ 0 ].name; - const isValidForMultiBlocks = - isWildcardBlockTransform( transform ) || - ! isMultiBlock || - transform.isMultiBlock; - if ( ! isValidForMultiBlocks ) { + const isWildcardTransform = isWildcardBlockTransform( transform ); + if ( isMultiBlock && ! isWildcardTransform && ! transform.isMultiBlock ) { return false; } // Check non-wildcard transforms to ensure that transform is valid // for a block selection of multiple blocks of different types. + const firstBlockName = blocks[ 0 ].name; if ( - ! isWildcardBlockTransform( transform ) && + ! isWildcardTransform && ! blocks.every( ( block ) => block.name === firstBlockName ) ) { return false; } - // Only consider 'block' type transforms as valid. - const isBlockType = transform.type === 'block'; - if ( ! isBlockType ) { - return false; - } - // Check if the transform's block name matches the source block (or is a wildcard) // only if this is a transform 'from'. const sourceBlock = blocks[ 0 ]; - const hasMatchingName = - direction !== 'from' || - transform.blocks.indexOf( sourceBlock.name ) !== -1 || - isWildcardBlockTransform( transform ); - if ( ! hasMatchingName ) { + if ( + direction === 'from' && + ! isWildcardTransform && + ! transform.blocks.includes( sourceBlock.name ) + ) { return false; } @@ -222,25 +219,22 @@ const isPossibleTransformForSource = ( transform, direction, blocks ) => { * * @return {Array} Block types that the blocks can be transformed into. */ -const getBlockTypesForPossibleFromTransforms = ( blocks ) => { +const getBlockTypesForPossibleFromTransforms = async ( blocks ) => { if ( ! blocks.length ) { return []; } - const allBlockTypes = getBlockTypes(); - + const allBlockTypes = await loadBlockTypes(); + const fromTransforms = await getBlockTransforms( 'from' ); // filter all blocks to find those with a 'from' transform. const blockTypesWithPossibleFromTransforms = allBlockTypes.filter( - ( blockType ) => { - const fromTransforms = getBlockTransforms( 'from', blockType.name ); - return !! findTransform( fromTransforms, ( transform ) => { - return isPossibleTransformForSource( - transform, - 'from', - blocks - ); - } ); - } + ( blockType ) => + findTransform( + fromTransforms, + ( transform ) => + transform.blockName === blockType.name && + isPossibleTransformForSource( transform, 'from', blocks ) + ) ); return blockTypesWithPossibleFromTransforms; @@ -254,28 +248,26 @@ const getBlockTypesForPossibleFromTransforms = ( blocks ) => { * * @return {Array} Block types that the source can be transformed into. */ -const getBlockTypesForPossibleToTransforms = ( blocks ) => { +const getBlockTypesForPossibleToTransforms = async ( blocks ) => { if ( ! blocks.length ) { return []; } const sourceBlock = blocks[ 0 ]; - const blockType = getBlockType( sourceBlock.name ); + const blockType = await loadBlockType( sourceBlock.name ); const transformsTo = blockType - ? getBlockTransforms( 'to', blockType.name ) + ? await getBlockTransforms( 'to', blockType.name ) : []; // filter all 'to' transforms to find those that are possible. - const possibleTransforms = transformsTo.filter( ( transform ) => { - return ( - transform && isPossibleTransformForSource( transform, 'to', blocks ) - ); - } ); + const possibleTransforms = transformsTo.filter( ( transform ) => + isPossibleTransformForSource( transform, 'to', blocks ) + ); // Build a list of block names using the possible 'to' transforms. - const blockNames = possibleTransforms - .map( ( transformation ) => transformation.blocks ) - .flat(); + const blockNames = possibleTransforms.flatMap( + ( transformation ) => transformation.blocks + ); // Map block names to block types. return blockNames.map( getBlockType ); @@ -316,22 +308,36 @@ export const isContainerGroupBlock = ( name ) => * * @return {Array} Block types that the blocks argument can be transformed to. */ -export function getPossibleBlockTransformations( blocks ) { +export async function getPossibleBlockTransformations( blocks ) { if ( ! blocks.length ) { return []; } const blockTypesForFromTransforms = - getBlockTypesForPossibleFromTransforms( blocks ); + await getBlockTypesForPossibleFromTransforms( blocks ); const blockTypesForToTransforms = - getBlockTypesForPossibleToTransforms( blocks ); + await getBlockTypesForPossibleToTransforms( blocks ); - return [ - ...new Set( [ + return Array.from( + new Set( [ ...blockTypesForFromTransforms, ...blockTypesForToTransforms, - ] ), - ]; + ] ) + ); +} + +export async function getTransformItemsForBlocks( items, blocks ) { + const normalizedBlocks = Array.isArray( blocks ) ? blocks : [ blocks ]; + const possibleTransforms = ( + await getPossibleBlockTransformations( normalizedBlocks ) + ).reduce( ( accumulator, block ) => { + if ( items[ block?.name ] ) { + accumulator.push( items[ block.name ] ); + } + return accumulator; + }, [] ); + + return possibleTransforms; } /** @@ -378,12 +384,16 @@ export function findTransform( transforms, predicate ) { * * @return {Array} Block transforms for direction. */ -export function getBlockTransforms( direction, blockTypeOrName ) { +export async function getBlockTransforms( direction, blockTypeOrName ) { // When retrieving transforms for all block types, recurse into self. if ( blockTypeOrName === undefined ) { - return getBlockTypes() - .map( ( { name } ) => getBlockTransforms( direction, name ) ) - .flat(); + const blockTypes = await loadBlockTypes(); + const blockTransforms = await Promise.all( + blockTypes.map( ( { name } ) => + getBlockTransforms( direction, name ) + ) + ); + return blockTransforms.flat(); } // Validate that block type exists and has array of direction. @@ -455,7 +465,7 @@ function maybeCheckTransformIsMatch( transform, blocks ) { * * @return {?Array} Array of blocks or null. */ -export function switchToBlockType( blocks, name ) { +export async function switchToBlockType( blocks, name ) { const blocksArray = Array.isArray( blocks ) ? blocks : [ blocks ]; const isMultiBlock = blocksArray.length > 1; const firstBlock = blocksArray[ 0 ]; @@ -463,8 +473,8 @@ export function switchToBlockType( blocks, name ) { // Find the right transformation by giving priority to the "to" // transformation. - const transformationsFrom = getBlockTransforms( 'from', name ); - const transformationsTo = getBlockTransforms( 'to', sourceName ); + const transformationsFrom = await getBlockTransforms( 'from', name ); + const transformationsTo = await getBlockTransforms( 'to', sourceName ); const transformation = findTransform( @@ -581,13 +591,13 @@ export function switchToBlockType( blocks, name ) { */ export const getBlockFromExample = ( name, example ) => { try { - return createBlock( - name, - example.attributes, - ( example.innerBlocks ?? [] ).map( ( innerBlock ) => + let innerBlocks = []; + if ( example.innerBlocks ) { + innerBlocks = example.innerBlocks.map( ( innerBlock ) => getBlockFromExample( innerBlock.name, innerBlock ) - ) - ); + ); + } + return createBlock( name, example.attributes, innerBlocks ); } catch { return createBlock( 'core/missing', { originalName: name, diff --git a/packages/blocks/src/api/index.js b/packages/blocks/src/api/index.js index 2ddeb3a60f0ab..c96c2dc389612 100644 --- a/packages/blocks/src/api/index.js +++ b/packages/blocks/src/api/index.js @@ -14,6 +14,7 @@ export { getBlockTransforms, findTransform, getBlockFromExample, + getTransformItemsForBlocks, } from './factory'; // The block tree is composed of a collection of block nodes. Blocks contained @@ -125,6 +126,8 @@ export { getBlockSupport, hasBlockSupport, getBlockVariations, + getBootstrappedBlockType, + getBootstrappedBlockTypes, isReusableBlock, isTemplatePart, getChildBlockNames, diff --git a/packages/blocks/src/api/parser/index.js b/packages/blocks/src/api/parser/index.js index f8ff0c68964dc..ca4859d133ddc 100644 --- a/packages/blocks/src/api/parser/index.js +++ b/packages/blocks/src/api/parser/index.js @@ -10,7 +10,7 @@ import { autop } from '@wordpress/autop'; import { getFreeformContentHandlerName, getUnregisteredTypeHandlerName, - getBlockType, + loadBlockType, } from '../registration'; import { getSaveContent } from '../serializer'; import { validateBlock } from '../validation'; @@ -193,7 +193,7 @@ function applyBlockValidation( unvalidatedBlock, blockType ) { * * @return {WPBlock | undefined} Fully parsed block. */ -export function parseRawBlock( rawBlock, options ) { +export async function parseRawBlock( rawBlock, options ) { let normalizedBlock = normalizeRawBlock( rawBlock, options ); // During the lifecycle of the project, we renamed some old blocks @@ -202,12 +202,12 @@ export function parseRawBlock( rawBlock, options ) { normalizedBlock = convertLegacyBlocks( normalizedBlock ); // Try finding the type for known block name. - let blockType = getBlockType( normalizedBlock.blockName ); + let blockType = await loadBlockType( normalizedBlock.blockName ); // If not blockType is found for the specified name, fallback to the "unregistedBlockType". if ( ! blockType ) { normalizedBlock = createMissingBlockType( normalizedBlock ); - blockType = getBlockType( normalizedBlock.blockName ); + blockType = await loadBlockType( normalizedBlock.blockName ); } // If it's an empty freeform block or there's no blockType (no missing block handler) @@ -223,8 +223,13 @@ export function parseRawBlock( rawBlock, options ) { } // Parse inner blocks recursively. - const parsedInnerBlocks = normalizedBlock.innerBlocks - .map( ( innerBlock ) => parseRawBlock( innerBlock, options ) ) + const parsedInnerBlocks = ( + await Promise.all( + normalizedBlock.innerBlocks.map( ( innerBlock ) => + parseRawBlock( innerBlock, options ) + ) + ) + ) // See https://github.com/WordPress/gutenberg/pull/17164. .filter( ( innerBlock ) => !! innerBlock ); @@ -307,12 +312,13 @@ export function parseRawBlock( rawBlock, options ) { * * @return {Array} Block list. */ -export default function parse( content, options ) { - return grammarParse( content ).reduce( ( accumulator, rawBlock ) => { - const block = parseRawBlock( rawBlock, options ); +export default async function parse( content, options ) { + const blocks = []; + for ( const rawBlock of grammarParse( content ) ) { + const block = await parseRawBlock( rawBlock, options ); if ( block ) { - accumulator.push( block ); + blocks.push( block ); } - return accumulator; - }, [] ); + } + return blocks; } diff --git a/packages/blocks/src/api/raw-handling/get-raw-transforms.js b/packages/blocks/src/api/raw-handling/get-raw-transforms.js index 060c72d00f847..32d3009baea1c 100644 --- a/packages/blocks/src/api/raw-handling/get-raw-transforms.js +++ b/packages/blocks/src/api/raw-handling/get-raw-transforms.js @@ -3,8 +3,9 @@ */ import { getBlockTransforms } from '../factory'; -export function getRawTransforms() { - return getBlockTransforms( 'from' ) +export async function getRawTransforms() { + const transforms = await getBlockTransforms( 'from' ); + return transforms .filter( ( { type } ) => type === 'raw' ) .map( ( transform ) => { return transform.isMatch diff --git a/packages/blocks/src/api/raw-handling/index.js b/packages/blocks/src/api/raw-handling/index.js index afd68a4a9e1e7..a8a80e9271402 100644 --- a/packages/blocks/src/api/raw-handling/index.js +++ b/packages/blocks/src/api/raw-handling/index.js @@ -35,7 +35,7 @@ export function deprecatedGetPhrasingContentSchema( context ) { * * @return {Array} A list of blocks. */ -export function rawHandler( { HTML = '' } ) { +export async function rawHandler( { HTML = '' } ) { // If we detect block delimiters, parse entirely as blocks. if ( HTML.indexOf( '<!-- wp:' ) !== -1 ) { return parse( HTML ); @@ -43,7 +43,7 @@ export function rawHandler( { HTML = '' } ) { // An array of HTML strings and block objects. The blocks replace matched // shortcodes. - const pieces = shortcodeConverter( HTML ); + const pieces = await shortcodeConverter( HTML ); const blockContentSchema = getBlockContentSchema(); return pieces diff --git a/packages/blocks/src/api/raw-handling/paste-handler.js b/packages/blocks/src/api/raw-handling/paste-handler.js index d0bf3e05979c6..e80472e036b5c 100644 --- a/packages/blocks/src/api/raw-handling/paste-handler.js +++ b/packages/blocks/src/api/raw-handling/paste-handler.js @@ -76,7 +76,7 @@ function filterInlineHTML( HTML ) { * * @return {Array|string} A list of blocks or a string, depending on `handlerMode`. */ -export function pasteHandler( { +export async function pasteHandler( { HTML = '', plainText = '', mode = 'AUTO', @@ -100,7 +100,7 @@ export function pasteHandler( { const content = HTML ? HTML : plainText; if ( content.indexOf( '<!-- wp:' ) !== -1 ) { - return parse( content ); + return await parse( content ); } } @@ -135,7 +135,7 @@ export function pasteHandler( { // An array of HTML strings and block objects. The blocks replace matched // shortcodes. - const pieces = shortcodeConverter( HTML ); + const pieces = await shortcodeConverter( HTML ); // The call to shortcodeConverter will always return more than one element // if shortcodes are matched. The reason is when shortcodes are matched diff --git a/packages/blocks/src/api/raw-handling/shortcode-converter.js b/packages/blocks/src/api/raw-handling/shortcode-converter.js index 3434717553a98..bff65cced76bf 100644 --- a/packages/blocks/src/api/raw-handling/shortcode-converter.js +++ b/packages/blocks/src/api/raw-handling/shortcode-converter.js @@ -14,19 +14,19 @@ import { applyBuiltInValidationFixes } from '../parser/apply-built-in-validation const castArray = ( maybeArray ) => Array.isArray( maybeArray ) ? maybeArray : [ maybeArray ]; -function segmentHTMLToShortcodeBlock( +async function segmentHTMLToShortcodeBlock( HTML, lastIndex = 0, excludedBlockNames = [] ) { // Get all matches. - const transformsFrom = getBlockTransforms( 'from' ); + const transformsFrom = await getBlockTransforms( 'from' ); const transformation = findTransform( transformsFrom, ( transform ) => - excludedBlockNames.indexOf( transform.blockName ) === -1 && transform.type === 'shortcode' && + ! excludedBlockNames.includes( transform.blockName ) && castArray( transform.tag ).some( ( tag ) => regexp( tag ).test( HTML ) ) @@ -60,7 +60,7 @@ function segmentHTMLToShortcodeBlock( /^\s*(\n|<\/p>)/.test( afterHTML ) ) ) { - return segmentHTMLToShortcodeBlock( HTML, lastIndex ); + return await segmentHTMLToShortcodeBlock( HTML, lastIndex ); } // If a transformation's `isMatch` predicate fails for the inbound @@ -75,7 +75,7 @@ function segmentHTMLToShortcodeBlock( transformation.isMatch && ! transformation.isMatch( match.shortcode.attrs ) ) { - return segmentHTMLToShortcodeBlock( HTML, previousIndex, [ + return await segmentHTMLToShortcodeBlock( HTML, previousIndex, [ ...excludedBlockNames, transformation.blockName, ] ); @@ -143,9 +143,9 @@ function segmentHTMLToShortcodeBlock( } return [ - ...segmentHTMLToShortcodeBlock( beforeHTML ), + ...( await segmentHTMLToShortcodeBlock( beforeHTML ) ), ...blocks, - ...segmentHTMLToShortcodeBlock( afterHTML ), + ...( await segmentHTMLToShortcodeBlock( afterHTML ) ), ]; } diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index b1dbee47b9b7c..6659ef6a34247 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -3,7 +3,7 @@ /** * WordPress dependencies */ -import { select, dispatch } from '@wordpress/data'; +import { select, resolveSelect, dispatch } from '@wordpress/data'; import { _x } from '@wordpress/i18n'; /** @@ -234,20 +234,16 @@ export function registerBlockType( blockNameOrMetadata, settings ) { ); return; } - if ( select( blocksStore ).getBlockType( name ) ) { - console.error( 'Block "' + name + '" is already registered.' ); - return; - } const { addBootstrappedBlockType, addUnprocessedBlockType } = unlock( dispatch( blocksStore ) ); - if ( isObject( blockNameOrMetadata ) ) { - const metadata = getBlockSettingsFromMetadata( blockNameOrMetadata ); - addBootstrappedBlockType( name, metadata ); - } + const metadata = isObject( blockNameOrMetadata ) + ? getBlockSettingsFromMetadata( blockNameOrMetadata ) + : getBlockSettingsFromMetadata( settings ); + addBootstrappedBlockType( name, metadata ); addUnprocessedBlockType( name, settings ); return select( blocksStore ).getBlockType( name ); @@ -501,9 +497,16 @@ export function getDefaultBlockName() { * @return {?Object} Block type. */ export function getBlockType( name ) { - return select( blocksStore )?.getBlockType( name ); + return select( blocksStore ).getBlockType( name ); +} + +export function getBootstrappedBlockType( name ) { + return select( blocksStore ).getBootstrappedBlockType( name ); } +export function loadBlockType( name ) { + return resolveSelect( blocksStore ).getBlockType( name ); +} /** * Returns all registered blocks. * @@ -513,6 +516,17 @@ export function getBlockTypes() { return select( blocksStore ).getBlockTypes(); } +export function getBootstrappedBlockTypes() { + return select( blocksStore ).getBootstrappedBlockTypes(); +} + +export async function loadBlockTypes() { + await Promise.all( + getBootstrappedBlockTypes().map( ( { name } ) => loadBlockType( name ) ) + ); + return getBlockTypes(); +} + /** * Returns the block support value for a feature, if defined. * diff --git a/packages/blocks/src/api/utils.js b/packages/blocks/src/api/utils.js index 0d17836faea7e..db41453bcdfb6 100644 --- a/packages/blocks/src/api/utils.js +++ b/packages/blocks/src/api/utils.js @@ -17,7 +17,11 @@ import { RichTextData } from '@wordpress/rich-text'; * Internal dependencies */ import { BLOCK_ICON_DEFAULT } from './constants'; -import { getBlockType, getDefaultBlockName } from './registration'; +import { + getBlockType, + getBootstrappedBlockType, + getDefaultBlockName, +} from './registration'; extend( [ namesPlugin, a11yPlugin ] ); @@ -38,26 +42,26 @@ const ICON_COLORS = [ '#191e23', '#f8f9f9' ]; * @return {boolean} Whether the block is an unmodified block. */ export function isUnmodifiedBlock( block ) { - return Object.entries( getBlockType( block.name )?.attributes ?? {} ).every( - ( [ key, definition ] ) => { - const value = block.attributes[ key ]; - - // Every attribute that has a default must match the default. - if ( definition.hasOwnProperty( 'default' ) ) { - return value === definition.default; - } - - // The rich text type is a bit different from the rest because it - // has an implicit default value of an empty RichTextData instance, - // so check the length of the value. - if ( definition.type === 'rich-text' ) { - return ! value?.length; - } + return Object.entries( + getBootstrappedBlockType( block.name )?.attributes ?? {} + ).every( ( [ key, definition ] ) => { + const value = block.attributes[ key ]; + + // Every attribute that has a default must match the default. + if ( definition.hasOwnProperty( 'default' ) ) { + return value === definition.default; + } - // Every attribute that doesn't have a default should be undefined. - return value === undefined; + // The rich text type is a bit different from the rest because it + // has an implicit default value of an empty RichTextData instance, + // so check the length of the value. + if ( definition.type === 'rich-text' ) { + return ! value?.length; } - ); + + // Every attribute that doesn't have a default should be undefined. + return value === undefined; + } ); } /** @@ -271,7 +275,7 @@ export function getDefault( attributeSchema ) { */ export function __experimentalSanitizeBlockAttributes( name, attributes ) { // Get the type definition associated with a registered block. - const blockType = getBlockType( name ); + const blockType = getBootstrappedBlockType( name ); if ( undefined === blockType ) { throw new Error( `Block type '${ name }' is not registered.` ); diff --git a/packages/blocks/src/store/index.js b/packages/blocks/src/store/index.js index ffda3ffe00026..97610167c127e 100644 --- a/packages/blocks/src/store/index.js +++ b/packages/blocks/src/store/index.js @@ -11,6 +11,7 @@ import * as selectors from './selectors'; import * as privateSelectors from './private-selectors'; import * as actions from './actions'; import * as privateActions from './private-actions'; +import * as resolvers from './resolvers'; import { STORE_NAME } from './constants'; import { unlock } from '../lock-unlock'; @@ -25,6 +26,7 @@ export const store = createReduxStore( STORE_NAME, { reducer, selectors, actions, + resolvers, } ); register( store ); diff --git a/packages/blocks/src/store/private-selectors.js b/packages/blocks/src/store/private-selectors.js index 7e4311658c869..82e97ad55e713 100644 --- a/packages/blocks/src/store/private-selectors.js +++ b/packages/blocks/src/store/private-selectors.js @@ -153,18 +153,6 @@ export const getSupportedStyles = createSelector( ( state, name ) => [ state.blockTypes[ name ] ] ); -/** - * Returns the bootstrapped block type metadata for a give block name. - * - * @param {Object} state Data state. - * @param {string} name Block name. - * - * @return {Object} Bootstrapped block type metadata for a block. - */ -export function getBootstrappedBlockType( state, name ) { - return state.bootstrappedBlockTypes[ name ]; -} - /** * Returns all the unprocessed (before applying the `registerBlockType` filter) * block type settings as passed during block registration. diff --git a/packages/blocks/src/store/resolvers.js b/packages/blocks/src/store/resolvers.js new file mode 100644 index 0000000000000..a5fd486b7c4e0 --- /dev/null +++ b/packages/blocks/src/store/resolvers.js @@ -0,0 +1,46 @@ +function loaderElement( type, src ) { + if ( type === 'script' ) { + const script = document.createElement( 'script' ); + script.src = src; + return script; + } + + if ( type === 'style' ) { + const link = document.createElement( 'link' ); + link.rel = 'stylesheet'; + link.type = 'text/css'; + link.href = src; + return link; + } + + return null; +} + +export const getBlockType = ( name ) => async () => { + const mods = window.wp.importmap[ name ]; + if ( ! mods ) { + return; + } + + await Promise.all( + mods + .filter( ( mod ) => mod.src ) + .map( + ( mod ) => + new Promise( ( resolve, reject ) => { + const node = loaderElement( mod.type, mod.src ); + node.onload = () => { + resolve(); + }; + node.onerror = () => { + reject( + new Error( + `Failed to load ${ mod.type } ${ name } ${ mod.handle } ${ mod.src }` + ) + ); + }; + document.body.appendChild( node ); + } ) + ) + ); +}; diff --git a/packages/blocks/src/store/selectors.js b/packages/blocks/src/store/selectors.js index b2b8ab8106f09..5018b8be2743c 100644 --- a/packages/blocks/src/store/selectors.js +++ b/packages/blocks/src/store/selectors.js @@ -29,7 +29,7 @@ import { getValueFromObjectPath } from './utils'; */ const getNormalizedBlockType = ( state, nameOrType ) => 'string' === typeof nameOrType - ? getBlockType( state, nameOrType ) + ? getBootstrappedBlockType( state, nameOrType ) : nameOrType; /** @@ -65,6 +65,15 @@ export const getBlockTypes = createSelector( ( state ) => [ state.blockTypes ] ); +export const getBootstrappedBlockTypes = createSelector( + ( state ) => Object.values( state.bootstrappedBlockTypes ), + ( state ) => [ state.bootstrappedBlockTypes ] +); + +export const getBootstrappedBlockType = ( state, name ) => { + return state.bootstrappedBlockTypes[ name ]; +}; + /** * Returns a block type by name. * @@ -301,11 +310,7 @@ export function getActiveBlockVariation( state, blockName, attributes, scope ) { export function getDefaultBlockVariation( state, blockName, scope ) { const variations = getBlockVariations( state, blockName, scope ); - const defaultVariation = [ ...variations ] - .reverse() - .find( ( { isDefault } ) => !! isDefault ); - - return defaultVariation || variations[ 0 ]; + return variations.findLast( ( v, i ) => v.isDefault || i === 0 ); } /** diff --git a/packages/components/src/autocomplete/index.tsx b/packages/components/src/autocomplete/index.tsx index b76e8548c08f2..abfa674f7f210 100644 --- a/packages/components/src/autocomplete/index.tsx +++ b/packages/components/src/autocomplete/index.tsx @@ -108,7 +108,7 @@ export function useAutocomplete( { onChange( insert( record, toInsert, start, end ) ); } - function select( option: KeyedOption ) { + async function select( option: KeyedOption ) { const { getOptionCompletion } = autocompleter || {}; if ( option.isDisabled ) { @@ -116,7 +116,10 @@ export function useAutocomplete( { } if ( getOptionCompletion ) { - const completion = getOptionCompletion( option.value, filterValue ); + const completion = await getOptionCompletion( + option.value, + filterValue + ); const isCompletionObject = ( obj: OptionCompletion diff --git a/packages/core-data/src/entity-provider.js b/packages/core-data/src/entity-provider.js index 4b82b62e318bc..372c6e8789bb5 100644 --- a/packages/core-data/src/entity-provider.js +++ b/packages/core-data/src/entity-provider.js @@ -5,7 +5,8 @@ import { createContext, useContext, useCallback, - useMemo, + useState, + useEffect, } from '@wordpress/element'; import { useSelect, useDispatch } from '@wordpress/data'; import { parse, __unstableSerializeAndClean } from '@wordpress/blocks'; @@ -171,19 +172,30 @@ export function useEntityBlockEditor( kind, name, { id: _id } = {} ) { const { __unstableCreateUndoLevel, editEntityRecord } = useDispatch( STORE_NAME ); - const blocks = useMemo( () => { - if ( ! id ) { - return undefined; - } + const [ blocks, setBlocks ] = useState( EMPTY_ARRAY ); + useEffect( () => { + let mounted = true; if ( editedBlocks ) { - return editedBlocks; + setBlocks( editedBlocks ); } - return content && typeof content !== 'function' - ? parse( content ) - : EMPTY_ARRAY; - }, [ id, editedBlocks, content ] ); + // Load the blocks from the content if not already in state + // Guard against other instances that might have + // set content to a function already or the blocks are already in state. + if ( content && typeof content !== 'function' ) { + parse( content ).then( ( parsedBlocks ) => { + // Don't set if another `editedBlocks` or `content` value arrived during parsing. + if ( mounted ) { + setBlocks( parsedBlocks ); + } + } ); + } + + return () => { + mounted = false; + }; + }, [ editedBlocks, content ] ); const updateFootnotes = useCallback( ( _blocks ) => updateFootnotesFromMeta( _blocks, meta ), diff --git a/packages/e2e-test-utils-playwright/src/editor/transform-block-to.ts b/packages/e2e-test-utils-playwright/src/editor/transform-block-to.ts index 75102983069d4..b1a6c1126ed47 100644 --- a/packages/e2e-test-utils-playwright/src/editor/transform-block-to.ts +++ b/packages/e2e-test-utils-playwright/src/editor/transform-block-to.ts @@ -15,7 +15,7 @@ export async function transformBlockTo( this: Editor, name: string ) { ); await this.page.evaluate( - ( [ blockName ] ) => { + async ( [ blockName ] ) => { const clientIds = window.wp.data .select( 'core/block-editor' ) .getSelectedBlockClientIds(); @@ -26,7 +26,10 @@ export async function transformBlockTo( this: Editor, name: string ) { .dispatch( 'core/block-editor' ) .replaceBlocks( clientIds, - window.wp.blocks.switchToBlockType( blocks, blockName ) + await window.wp.blocks.switchToBlockType( + blocks, + blockName + ) ); }, [ name ] diff --git a/packages/e2e-tests/specs/editor/various/inserting-blocks.test.js b/packages/e2e-tests/specs/editor/various/inserting-blocks.test.js index 4285a410f891e..b54147aafd742 100644 --- a/packages/e2e-tests/specs/editor/various/inserting-blocks.test.js +++ b/packages/e2e-tests/specs/editor/various/inserting-blocks.test.js @@ -159,6 +159,9 @@ describe( 'Inserting blocks', () => { it( 'should insert block with the slash inserter when using multiple words', async () => { await page.keyboard.press( 'Enter' ); + await canvas().waitForSelector( + '[data-type="core/paragraph"][data-empty="true"' + ); await page.keyboard.type( '/tag cloud' ); await page.waitForXPath( `//*[contains(@class, "components-autocomplete__result") and contains(@class, "is-selected") and contains(text(), 'Tag Cloud')]` diff --git a/packages/edit-post/src/components/start-page-options/index.js b/packages/edit-post/src/components/start-page-options/index.js index 0ef3e166e8ee1..872594a260f33 100644 --- a/packages/edit-post/src/components/start-page-options/index.js +++ b/packages/edit-post/src/components/start-page-options/index.js @@ -21,28 +21,35 @@ function useStartPatterns() { // A pattern is a start pattern if it includes 'core/post-content' in its blockTypes, // and it has no postTypes declared and the current post type is page or if // the current post type is part of the postTypes declared. - const { blockPatternsWithPostContentBlockType, postType } = useSelect( - ( select ) => { - const { getPatternsByBlockTypes } = select( blockEditorStore ); - const { getCurrentPostType } = select( editorStore ); - return { - blockPatternsWithPostContentBlockType: - getPatternsByBlockTypes( 'core/post-content' ), - postType: getCurrentPostType(), - }; - }, + const [ blockPatternsWithPostContentBlockType ] = useSelect( + ( select ) => [ + select( blockEditorStore ).getPatternsByBlockTypes( + 'core/post-content' + ), + ], + [] + ); + + const [ postType ] = useSelect( + ( select ) => [ select( editorStore ).getCurrentPostType() ], [] ); return useMemo( () => { + if ( ! blockPatternsWithPostContentBlockType ) { + return null; + } + // filter patterns without postTypes declared if the current postType is page // or patterns that declare the current postType in its post type array. return blockPatternsWithPostContentBlockType.filter( ( pattern ) => { - return ( - ( postType === 'page' && ! pattern.postTypes ) || - ( Array.isArray( pattern.postTypes ) && - pattern.postTypes.includes( postType ) ) - ); + if ( ! pattern.postTypes ) { + return postType === 'page'; + } + if ( Array.isArray( pattern.postTypes ) ) { + return pattern.postTypes.includes( postType ); + } + return false; } ); }, [ postType, blockPatternsWithPostContentBlockType ] ); } diff --git a/packages/edit-post/src/editor.js b/packages/edit-post/src/editor.js index 5dbc28ea85947..4c53660283ea8 100644 --- a/packages/edit-post/src/editor.js +++ b/packages/edit-post/src/editor.js @@ -51,7 +51,7 @@ function Editor( { postId, postType, settings, initialEdits, ...props } ) { const { getEntityRecord, getPostType, getEntityRecords, canUser } = select( coreStore ); const { getEditorSettings } = select( editorStore ); - const { getBlockTypes } = select( blocksStore ); + const { getBootstrappedBlockTypes } = select( blocksStore ); const isTemplate = [ 'wp_template', 'wp_template_part' ].includes( postType ); @@ -84,7 +84,7 @@ function Editor( { postId, postType, settings, initialEdits, ...props } ) { 'preferredStyleVariations' ), hiddenBlockTypes: getHiddenBlockTypes(), - blockTypes: getBlockTypes(), + blockTypes: getBootstrappedBlockTypes(), keepCaretInsideBlock: isFeatureActive( 'keepCaretInsideBlock' ), template: supportsTemplateMode && isViewable && canEditTemplate diff --git a/packages/edit-post/src/index.js b/packages/edit-post/src/index.js index ffe55e50efab0..46f5f9e732813 100644 --- a/packages/edit-post/src/index.js +++ b/packages/edit-post/src/index.js @@ -1,20 +1,18 @@ /** * WordPress dependencies */ -import { store as blocksStore } from '@wordpress/blocks'; import { - registerCoreBlocks, - __experimentalRegisterExperimentalCoreBlocks, -} from '@wordpress/block-library'; + store as blocksStore, + setDefaultBlockName, + setFreeformContentHandlerName, + setUnregisteredTypeHandlerName, + setGroupingBlockName, +} from '@wordpress/blocks'; import deprecated from '@wordpress/deprecated'; import { createRoot } from '@wordpress/element'; import { dispatch, select } from '@wordpress/data'; import { addFilter } from '@wordpress/hooks'; import { store as preferencesStore } from '@wordpress/preferences'; -import { - registerLegacyWidgetBlock, - registerWidgetGroupBlock, -} from '@wordpress/widgets'; import { privateApis as editorPrivateApis, store as editorStore, @@ -82,14 +80,12 @@ export function initializeEditor( dispatch( editPostStore ).setIsListViewOpened( true ); } - registerCoreBlocks(); - registerLegacyWidgetBlock( { inserter: false } ); - registerWidgetGroupBlock( { inserter: false } ); - if ( process.env.IS_GUTENBERG_PLUGIN ) { - __experimentalRegisterExperimentalCoreBlocks( { - enableFSEBlocks: settings.__unstableEnableFullSiteEditingBlocks, - } ); + setDefaultBlockName( 'core/paragraph' ); + if ( window.wp && window.wp.oldEditor ) { + setFreeformContentHandlerName( 'core/freeform' ); } + setUnregisteredTypeHandlerName( 'core/missing' ); + setGroupingBlockName( 'core/group' ); /* * Prevent adding template part in the post editor. diff --git a/packages/edit-site/src/components/style-book/index.js b/packages/edit-site/src/components/style-book/index.js index 19508f0a59f8e..8274c44323f89 100644 --- a/packages/edit-site/src/components/style-book/index.js +++ b/packages/edit-site/src/components/style-book/index.js @@ -14,7 +14,7 @@ import { import { __, sprintf } from '@wordpress/i18n'; import { getCategories, - getBlockTypes, + getBootstrappedBlockTypes, getBlockFromExample, createBlock, } from '@wordpress/blocks'; @@ -149,7 +149,7 @@ function getExamples() { ], }; - const otherExamples = getBlockTypes() + const otherExamples = getBootstrappedBlockTypes() .filter( ( blockType ) => { const { name, example, supports } = blockType; return ( diff --git a/packages/edit-site/src/store/actions.js b/packages/edit-site/src/store/actions.js index 6397a31af120b..41564e57fdbf2 100644 --- a/packages/edit-site/src/store/actions.js +++ b/packages/edit-site/src/store/actions.js @@ -116,7 +116,7 @@ export const addTemplate = 'postType', TEMPLATE_POST_TYPE, newTemplate.id, - { blocks: parse( template.content ) }, + { blocks: await parse( template.content ) }, { undoIgnore: true } ); } diff --git a/packages/editor/src/components/local-autosave-monitor/index.js b/packages/editor/src/components/local-autosave-monitor/index.js index 185497710f35f..f21254a86ffb3 100644 --- a/packages/editor/src/components/local-autosave-monitor/index.js +++ b/packages/editor/src/components/local-autosave-monitor/index.js @@ -112,13 +112,13 @@ function useAutosaveNotice() { actions: [ { label: __( 'Restore the backup' ), - onClick() { + async onClick() { const { content: editsContent, ...editsWithoutContent } = edits; editPost( editsWithoutContent ); - resetEditorBlocks( parse( edits.content ) ); + resetEditorBlocks( await parse( edits.content ) ); removeNotice( id ); }, }, diff --git a/packages/widgets/src/blocks/legacy-widget/block.json b/packages/widgets/src/blocks/legacy-widget/block.json index 6b0c1e2a916fd..2bd2751703c5c 100644 --- a/packages/widgets/src/blocks/legacy-widget/block.json +++ b/packages/widgets/src/blocks/legacy-widget/block.json @@ -23,6 +23,5 @@ "html": false, "customClassName": false, "reusable": false - }, - "editorStyle": "wp-block-legacy-widget-editor" + } } diff --git a/packages/widgets/src/blocks/widget-group/block.json b/packages/widgets/src/blocks/widget-group/block.json index c29e811554ac1..73fbcded608d2 100644 --- a/packages/widgets/src/blocks/widget-group/block.json +++ b/packages/widgets/src/blocks/widget-group/block.json @@ -13,6 +13,5 @@ "customClassName": true, "reusable": false }, - "editorStyle": "wp-block-widget-group-editor", "style": "wp-block-widget-group" } diff --git a/test/performance/fixtures/perf-utils.ts b/test/performance/fixtures/perf-utils.ts index d17eec2c935b1..d6a02f072c25d 100644 --- a/test/performance/fixtures/perf-utils.ts +++ b/test/performance/fixtures/perf-utils.ts @@ -132,10 +132,10 @@ export class PerfUtils { () => window?.wp?.blocks && window?.wp?.data ); - return await this.page.evaluate( ( html: string ) => { + return await this.page.evaluate( async ( html: string ) => { const { parse } = window.wp.blocks; const { dispatch } = window.wp.data; - const blocks = parse( html ); + const blocks = await parse( html ); blocks.forEach( ( block: any ) => { if ( block.name === 'core/image' ) { diff --git a/tools/webpack/blocks.js b/tools/webpack/blocks.js index d599980b951a9..d72acbc4e78e3 100644 --- a/tools/webpack/blocks.js +++ b/tools/webpack/blocks.js @@ -75,6 +75,25 @@ const createEntrypoints = () => { }, {} ); }; +const createEditorEntrypoints = () => { + const blockInitScriptPaths = fastGlob.sync( + './packages/block-library/build-module/**/init.js' + ); + + const entrypoints = {}; + for ( const scriptPath of blockInitScriptPaths ) { + const result = scriptPath.match( + /build-module\/(?<filename>.*)\/init\.js$/ + ); + if ( ! result ) { + continue; + } + entrypoints[ result.groups.filename + '/editor' ] = scriptPath; + } + + return entrypoints; +}; + module.exports = [ { ...baseConfig, @@ -220,4 +239,17 @@ module.exports = [ } ), ].filter( Boolean ), }, + { + ...baseConfig, + name: 'editor', + entry: createEditorEntrypoints(), + output: { + devtoolNamespace: 'wp', + filename: './build/block-library/blocks/[name].min.js', + path: join( __dirname, '..', '..' ), + }, + plugins: [ ...plugins, new DependencyExtractionWebpackPlugin() ].filter( + Boolean + ), + }, ];