Skip to content

Commit

Permalink
Try another approach
Browse files Browse the repository at this point in the history
  • Loading branch information
kevin940726 committed Sep 13, 2024
1 parent 7ed5e9c commit 91dcb16
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 144 deletions.
96 changes: 62 additions & 34 deletions packages/block-editor/src/components/block-list/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
isReusableBlock,
getBlockDefaultClassName,
hasBlockSupport,
createBlock,
__experimentalGetBlockAttributesNamesByRole,
store as blocksStore,
privateApis as blocksPrivateApis,
Expand Down Expand Up @@ -311,6 +312,41 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => {
canInsertBlockType,
} = registry.select( blockEditorStore );

function isBlockEmpty( block ) {
const blockType = getBlockType( block.name );
const contentAttributes =
__experimentalGetBlockAttributesNamesByRole(
block.name,
'content'
);
return contentAttributes.every( ( attribute ) => {
const definition = blockType.attributes[ attribute ];
const value = block.attributes[ attribute ];
return isAttributeUnmodified( definition, value );
} );
}

/**
* Update the attributes to reset the block to the default state.
* @param {WPBlock} block The block to reset.
*/
function resetBlockToDefault( block ) {
// Instead of replacing the block, only update the default attributes
// to keep any metadata intact.
const defaultBlockType = getBlockType( block.name );
const defaultBlockAttributes = createBlock(
block.name
).attributes;
for ( const key of Object.keys(
defaultBlockType.attributes
) ) {
if ( ! defaultBlockAttributes.hasOwnProperty( key ) ) {
defaultBlockAttributes[ key ] = undefined;
}
}
updateBlockAttributes( block.clientId, defaultBlockAttributes );
}

function switchToDefaultOrRemove() {
const block = getBlock( clientId );
const defaultBlockName = getDefaultBlockName();
Expand All @@ -333,26 +369,6 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => {
}
}

/**
* Return true if the block content is empty.
* @param {string} blockClientId The block client ID.
* @return {boolean} Whether the block content is empty.
*/
function isBlockContentEmpty( blockClientId ) {
const block = getBlock( blockClientId );
const blockType = getBlockType( block.name );
const contentAttributes =
__experimentalGetBlockAttributesNamesByRole(
block.name,
'content'
);
return contentAttributes.every( ( key ) => {
const value = block.attributes[ key ];
const definition = blockType.attributes[ key ];
return isAttributeUnmodified( definition, value );
} );
}

/**
* Moves the block with clientId up one level. If the block type
* cannot be inserted at the new location, it will be attempted to
Expand All @@ -374,16 +390,16 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => {
removeBlock( _clientId );
} else {
registry.batch( () => {
const firstBlock = getBlock( firstClientId );
const isFirstBlockEmpty = isBlockEmpty( firstBlock );

// Step 1: Lift the block to the parent if it's not "empty".
if (
canInsertBlockType(
getBlockName( firstClientId ),
targetRootClientId
) &&
// Don't move the block if its content is considered empty.
// Note that for a modified non-empty block, we still try to transform
// it to a default block.
// Fix for https://github.com/WordPress/gutenberg/issues/65174.
! isBlockContentEmpty( firstClientId )
! isFirstBlockEmpty
) {
moveBlocksToPosition(
[ firstClientId ],
Expand All @@ -392,29 +408,41 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => {
getBlockIndex( _clientId )
);
} else {
const defaultBlockName = getDefaultBlockName();
const replacement = switchToBlockType(
getBlock( firstClientId ),
getDefaultBlockName()
firstBlock,
defaultBlockName
);

if (
replacement &&
replacement.length &&
const canTransformToDefaultBlock =
!! replacement?.length &&
replacement.every( ( block ) =>
canInsertBlockType(
block.name,
targetRootClientId
)
)
) {
);

// Step 2: Else, attempt to convert to the default block type.
if ( canTransformToDefaultBlock ) {
insertBlocks(
replacement,
getBlockIndex( _clientId ),
targetRootClientId,
changeSelection
);
removeBlock( firstClientId, false );
} else {
}
// Step 3: If the block is a default block but modified and "empty",
// transform it into an unmodified block.
else if (
firstBlock.name === defaultBlockName &&
! isUnmodifiedDefaultBlock( firstBlock ) &&
isFirstBlockEmpty
) {
resetBlockToDefault( firstBlock );
}
// Step 4: Otherwise, continue the default behavior.
else {
switchToDefaultOrRemove();
}
}
Expand Down
52 changes: 0 additions & 52 deletions packages/blocks/src/api/test/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
getBlockLabel,
__experimentalSanitizeBlockAttributes,
__experimentalGetBlockAttributesNamesByRole,
isAttributeUnmodified,
} from '../utils';

const noop = () => {};
Expand Down Expand Up @@ -397,54 +396,3 @@ describe( '__experimentalGetBlockAttributesNamesByRole', () => {
).toEqual( [] );
} );
} );

describe( 'isAttributeUnmodified', () => {
it( 'should return true if the block is unmodified', () => {
expect(
isAttributeUnmodified(
{ type: 'rich-text', __experimentalRole: 'content' },
''
)
).toBe( true );
expect(
isAttributeUnmodified(
{ type: 'rich-text', __experimentalRole: 'content' },
undefined
)
).toBe( true );
expect( isAttributeUnmodified( { type: 'string' }, undefined ) ).toBe(
true
);
expect(
isAttributeUnmodified(
{ type: 'string', default: 'default-value' },
'default-value'
)
).toBe( true );
} );

it( 'should return false if the block is modified', () => {
expect(
isAttributeUnmodified(
{ type: 'rich-text', __experimentalRole: 'content' },
'something else'
)
).toBe( false );
expect(
isAttributeUnmodified( { type: 'string' }, 'something else' )
).toBe( false );
expect( isAttributeUnmodified( { type: 'string' }, '' ) ).toBe( false );
expect(
isAttributeUnmodified(
{ type: 'string', default: 'default-value' },
''
)
).toBe( false );
expect(
isAttributeUnmodified(
{ type: 'string', default: 'default-value' },
undefined
)
).toBe( false );
} );
} );
23 changes: 11 additions & 12 deletions test/e2e/specs/editor/blocks/list.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1237,18 +1237,17 @@ test.describe( 'List (@firefox)', () => {
await page.keyboard.press( 'Backspace' );
await page.keyboard.press( 'Backspace' );

await expect.poll( editor.getBlocks ).toMatchObject( [
{ name: 'core/paragraph', attributes: { content: '' } },
{
name: 'core/list',
innerBlocks: [
{
name: 'core/list-item',
attributes: { content: '2' },
},
],
},
] );
await expect.poll( editor.getEditedPostContent ).toBe(
`<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->
<!-- wp:list -->
<ul class="wp-block-list"><!-- wp:list-item -->
<li>2</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list -->`
);
} );

test( 'should not change the contents when you change the list type to Ordered', async ( {
Expand Down
Loading

0 comments on commit 91dcb16

Please sign in to comment.