Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Apply keyboard shortcut conversions between paragraphs and headings to all editor instances #47972

Merged
merged 11 commits into from
Feb 21, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,14 @@ export const textFormattingShortcuts = [
keyCombination: { modifier: 'access', character: 'x' },
description: __( 'Make the selected text inline code.' ),
},
{
keyCombination: { modifier: 'access', character: '0' },
description: __( 'Convert the current heading to a paragraph.' ),
},
{
keyCombination: { modifier: 'access', character: '1-6' },
description: __(
'Convert the current paragraph or heading to a heading of level 1 to 6.'
),
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,44 @@ import {
store as keyboardShortcutsStore,
} from '@wordpress/keyboard-shortcuts';
import { isAppleOS } from '@wordpress/keycodes';
import { useDispatch } from '@wordpress/data';
import { useDispatch, useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { store as blockEditorStore } from '@wordpress/block-editor';
import { createBlock } from '@wordpress/blocks';

function KeyboardShortcuts( { undo, redo, save } ) {
const { replaceBlocks } = useDispatch( blockEditorStore );
const { getBlockName, getSelectedBlockClientId, getBlockAttributes } =
useSelect( blockEditorStore );

const handleTextLevelShortcut = ( event, level ) => {
event.preventDefault();
const destinationBlockName =
level === 0 ? 'core/paragraph' : 'core/heading';
const currentClientId = getSelectedBlockClientId();
if ( currentClientId === null ) {
return;
}
const blockName = getBlockName( currentClientId );
if ( blockName !== 'core/paragraph' && blockName !== 'core/heading' ) {
return;
}
const attributes = getBlockAttributes( currentClientId );
const textAlign =
blockName === 'core/paragraph' ? 'align' : 'textAlign';
const destinationTextAlign =
destinationBlockName === 'core/paragraph' ? 'align' : 'textAlign';

replaceBlocks(
currentClientId,
createBlock( destinationBlockName, {
level,
content: attributes.content,
...{ [ destinationTextAlign ]: attributes[ textAlign ] },
} )
);
};

useShortcut( 'core/customize-widgets/undo', ( event ) => {
undo();
event.preventDefault();
Expand All @@ -26,6 +60,21 @@ function KeyboardShortcuts( { undo, redo, save } ) {
save();
} );

useShortcut(
'core/customize-widgets/transform-heading-to-paragraph',
( event ) => handleTextLevelShortcut( event, 0 )
);

[ 1, 2, 3, 4, 5, 6 ].forEach( ( level ) => {
//the loop is based off on a constant therefore
//the hook will execute the same way every time
//eslint-disable-next-line react-hooks/rules-of-hooks
useShortcut(
`core/customize-widgets/transform-paragraph-to-heading-${ level }`,
( event ) => handleTextLevelShortcut( event, level )
);
} );

return null;
}

Expand Down Expand Up @@ -77,6 +126,28 @@ function KeyboardShortcutsRegister() {
},
} );

registerShortcut( {
name: `core/customize-widgets/transform-heading-to-paragraph`,
category: 'block-library',
description: __( 'Transform heading to paragraph.' ),
keyCombination: {
modifier: 'access',
character: `0`,
},
} );

[ 1, 2, 3, 4, 5, 6 ].forEach( ( level ) => {
registerShortcut( {
name: `core/customize-widgets/transform-paragraph-to-heading-${ level }`,
category: 'block-library',
description: __( 'Transform paragraph to heading.' ),
keyCombination: {
modifier: 'access',
character: `${ level }`,
},
} );
} );

return () => {
unregisterShortcut( 'core/customize-widgets/undo' );
unregisterShortcut( 'core/customize-widgets/redo' );
Expand Down
13 changes: 5 additions & 8 deletions packages/e2e-test-utils-playwright/src/editor/get-blocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,11 @@ export async function getBlocks( this: Editor ) {
const blocks = window.wp.data.select( 'core/block-editor' ).getBlocks();

// The editor might still contain an unmodified empty block even when it's technically "empty".
if ( blocks.length === 1 ) {
const blockName = blocks[ 0 ].name;
if (
blockName === window.wp.blocks.getDefaultBlockName() ||
blockName === window.wp.blocks.getFreeformContentHandlerName()
) {
return [];
}
if (
blocks.length === 1 &&
window.wp.blocks.isUnmodifiedDefaultBlock( blocks[ 0 ] )
) {
return [];
}

return blocks;
Expand Down
24 changes: 13 additions & 11 deletions packages/edit-post/src/components/keyboard-shortcuts/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,18 @@ function KeyboardShortcuts() {
if ( blockName !== 'core/paragraph' && blockName !== 'core/heading' ) {
return;
}
const currentAttributes = getBlockAttributes( currentClientId );
const { content: currentContent, align: currentAlign } =
currentAttributes;
const attributes = getBlockAttributes( currentClientId );
const textAlign =
blockName === 'core/paragraph' ? 'align' : 'textAlign';
const destinationTextAlign =
destinationBlockName === 'core/paragraph' ? 'align' : 'textAlign';

replaceBlocks(
currentClientId,
createBlock( destinationBlockName, {
level,
content: currentContent,
align: currentAlign,
content: attributes.content,
...{ [ destinationTextAlign ]: attributes[ textAlign ] },
Comment on lines +74 to +84
Copy link
Contributor Author

@t-hamano t-hamano Feb 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heading block and paragraph block have different property name for text alignment:

  • Heading Block: textAlign
  • Paragraph Block: align

Therefore, property name and value must be properly mapped.

} )
);
};
Expand Down Expand Up @@ -181,7 +184,7 @@ function KeyboardShortcuts() {
} );

registerShortcut( {
name: `core/block-editor/transform-heading-to-paragraph`,
name: `core/edit-post/transform-heading-to-paragraph`,
Comment on lines -184 to +187
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the namespace should be unified.

category: 'block-library',
description: __( 'Transform heading to paragraph.' ),
keyCombination: {
Expand All @@ -192,7 +195,7 @@ function KeyboardShortcuts() {

[ 1, 2, 3, 4, 5, 6 ].forEach( ( level ) => {
registerShortcut( {
name: `core/block-editor/transform-paragraph-to-heading-${ level }`,
name: `core/edit-post/transform-paragraph-to-heading-${ level }`,
category: 'block-library',
description: __( 'Transform paragraph to heading.' ),
keyCombination: {
Expand Down Expand Up @@ -257,17 +260,16 @@ function KeyboardShortcuts() {
}
} );

useShortcut(
'core/block-editor/transform-heading-to-paragraph',
( event ) => handleTextLevelShortcut( event, 0 )
useShortcut( 'core/edit-post/transform-heading-to-paragraph', ( event ) =>
handleTextLevelShortcut( event, 0 )
);

[ 1, 2, 3, 4, 5, 6 ].forEach( ( level ) => {
//the loop is based off on a constant therefore
//the hook will execute the same way every time
//eslint-disable-next-line react-hooks/rules-of-hooks
useShortcut(
`core/block-editor/transform-paragraph-to-heading-${ level }`,
`core/edit-post/transform-paragraph-to-heading-${ level }`,
( event ) => handleTextLevelShortcut( event, level )
);
} );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,14 @@ export const textFormattingShortcuts = [
keyCombination: { modifier: 'access', character: 'x' },
description: __( 'Make the selected text inline code.' ),
},
{
keyCombination: { modifier: 'access', character: '0' },
description: __( 'Convert the current heading to a paragraph.' ),
},
{
keyCombination: { modifier: 'access', character: '1-6' },
description: __(
'Convert the current paragraph or heading to a heading of level 1 to 6.'
),
},
];
70 changes: 70 additions & 0 deletions packages/edit-site/src/components/keyboard-shortcuts/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import { isAppleOS } from '@wordpress/keycodes';
import { useDispatch, useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { store as coreStore } from '@wordpress/core-data';
import { store as blockEditorStore } from '@wordpress/block-editor';
import { store as interfaceStore } from '@wordpress/interface';
import { createBlock } from '@wordpress/blocks';

/**
* Internal dependencies
Expand Down Expand Up @@ -41,6 +43,38 @@ function KeyboardShortcuts() {
useDispatch( interfaceStore );
const { setIsSaveViewOpened } = useDispatch( editSiteStore );

const { replaceBlocks } = useDispatch( blockEditorStore );
const { getBlockName, getSelectedBlockClientId, getBlockAttributes } =
useSelect( blockEditorStore );

const handleTextLevelShortcut = ( event, level ) => {
event.preventDefault();
const destinationBlockName =
level === 0 ? 'core/paragraph' : 'core/heading';
const currentClientId = getSelectedBlockClientId();
if ( currentClientId === null ) {
return;
}
const blockName = getBlockName( currentClientId );
if ( blockName !== 'core/paragraph' && blockName !== 'core/heading' ) {
return;
}
const attributes = getBlockAttributes( currentClientId );
const textAlign =
blockName === 'core/paragraph' ? 'align' : 'textAlign';
const destinationTextAlign =
destinationBlockName === 'core/paragraph' ? 'align' : 'textAlign';

replaceBlocks(
currentClientId,
createBlock( destinationBlockName, {
level,
content: attributes.content,
...{ [ destinationTextAlign ]: attributes[ textAlign ] },
} )
);
};

useShortcut( 'core/edit-site/save', ( event ) => {
event.preventDefault();

Expand Down Expand Up @@ -85,6 +119,20 @@ function KeyboardShortcuts() {
switchEditorMode( getEditorMode() === 'visual' ? 'text' : 'visual' );
} );

useShortcut( 'core/edit-site/transform-heading-to-paragraph', ( event ) =>
handleTextLevelShortcut( event, 0 )
);

[ 1, 2, 3, 4, 5, 6 ].forEach( ( level ) => {
//the loop is based off on a constant therefore
//the hook will execute the same way every time
//eslint-disable-next-line react-hooks/rules-of-hooks
useShortcut(
`core/edit-site/transform-paragraph-to-heading-${ level }`,
( event ) => handleTextLevelShortcut( event, level )
);
} );

return null;
}

Expand Down Expand Up @@ -208,6 +256,28 @@ function KeyboardShortcutsRegister() {
character: 'm',
},
} );

registerShortcut( {
name: `core/edit-site/transform-heading-to-paragraph`,
category: 'block-library',
description: __( 'Transform heading to paragraph.' ),
keyCombination: {
modifier: 'access',
character: `0`,
},
} );

[ 1, 2, 3, 4, 5, 6 ].forEach( ( level ) => {
registerShortcut( {
name: `core/edit-site/transform-paragraph-to-heading-${ level }`,
category: 'block-library',
description: __( 'Transform paragraph to heading.' ),
keyCombination: {
modifier: 'access',
character: `${ level }`,
},
} );
} );
}, [ registerShortcut ] );

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,14 @@ export const textFormattingShortcuts = [
keyCombination: { modifier: 'access', character: 'x' },
description: __( 'Make the selected text inline code.' ),
},
{
keyCombination: { modifier: 'access', character: '0' },
description: __( 'Convert the current heading to a paragraph.' ),
},
{
keyCombination: { modifier: 'access', character: '1-6' },
description: __(
'Convert the current paragraph or heading to a heading of level 1 to 6.'
),
},
];
Loading