diff --git a/packages/editor/src/components/rich-text/index.js b/packages/editor/src/components/rich-text/index.js index b048c442f594ed..abc8b71528b86d 100644 --- a/packages/editor/src/components/rich-text/index.js +++ b/packages/editor/src/components/rich-text/index.js @@ -42,6 +42,8 @@ import { getSelectionEnd, remove, isCollapsed, + LINE_SEPARATOR, + charAt, } from '@wordpress/rich-text'; import { decodeEntities } from '@wordpress/html-entities'; @@ -492,8 +494,6 @@ export class RichText extends Component { * @link https://en.wikipedia.org/wiki/Caret_navigation * * @param {KeyboardEvent} event Keydown event. - * - * @return {?boolean} True if the event was handled. */ onDeleteKeyDown( event ) { const { onMerge, onRemove } = this.props; @@ -533,7 +533,7 @@ export class RichText extends Component { onRemove( ! isReverse ); } - return true; + event.preventDefault(); } /** @@ -545,32 +545,46 @@ export class RichText extends Component { const { keyCode } = event; if ( keyCode === DELETE || keyCode === BACKSPACE ) { - event.preventDefault(); + const value = this.createRecord(); + const start = getSelectionStart( value ); + const end = getSelectionEnd( value ); - if ( this.onDeleteKeyDown( event ) ) { + // Always handle uncollapsed selections ourselves. + if ( ! isCollapsed( value ) ) { + this.onChange( remove( value ) ); + event.preventDefault(); return; } - const value = this.createRecord(); - const start = getSelectionStart( value ); - const end = getSelectionEnd( value ); + if ( this.multilineTag ) { + let newValue; + + if ( keyCode === BACKSPACE ) { + if ( charAt( value, start - 1 ) === LINE_SEPARATOR ) { + newValue = remove( + value, + // Only remove the line if the selection is + // collapsed. + isCollapsed( value ) ? start - 1 : start, + end + ); + } + } else if ( charAt( value, end ) === LINE_SEPARATOR ) { + newValue = remove( + value, + start, + // Only remove the line if the selection is collapsed. + isCollapsed( value ) ? end + 1 : end, + ); + } - if ( keyCode === BACKSPACE ) { - this.onChange( remove( - value, - // Only remove the line if the selection is - // collapsed. - isCollapsed( value ) ? start - 1 : start, - end - ) ); - } else { - this.onChange( remove( - value, - start, - // Only remove the line if the selection is collapsed. - isCollapsed( value ) ? end + 1 : end, - ) ); + if ( newValue ) { + this.onChange( newValue ); + event.preventDefault(); + } } + + this.onDeleteKeyDown( event ); } else if ( keyCode === ENTER ) { event.preventDefault(); diff --git a/packages/editor/src/components/rich-text/tinymce.js b/packages/editor/src/components/rich-text/tinymce.js index e3dfb4145a67c0..8fa0f18ea3e4f1 100644 --- a/packages/editor/src/components/rich-text/tinymce.js +++ b/packages/editor/src/components/rich-text/tinymce.js @@ -252,9 +252,11 @@ export default class TinyMCE extends Component { onKeyDown( event ) { const { keyCode } = event; + const { startContainer, startOffset, endContainer, endOffset } = getSelection().getRangeAt( 0 ); + const isCollapsed = startContainer === endContainer && startOffset === endOffset; // Disables TinyMCE behaviour. - if ( keyCode === ENTER || keyCode === BACKSPACE || keyCode === DELETE ) { + if ( keyCode === ENTER || ( ! isCollapsed && ( keyCode === DELETE || keyCode === BACKSPACE ) ) ) { event.preventDefault(); // For some reason this is needed to also prevent the insertion of // line breaks. diff --git a/test/e2e/specs/writing-flow.test.js b/test/e2e/specs/writing-flow.test.js index 67c91280ba4107..aa7456533ec58c 100644 --- a/test/e2e/specs/writing-flow.test.js +++ b/test/e2e/specs/writing-flow.test.js @@ -223,4 +223,22 @@ describe( 'adding blocks', () => { ) ); expect( isInBlock ).toBe( true ); } ); + + it( 'should not delete trailing spaces when deleting a word with backspace', async () => { + await clickBlockAppender(); + await page.keyboard.type( '1 2 3 4' ); + await page.keyboard.press( 'Backspace' ); + await page.keyboard.type( '4' ); + const blockText = await page.evaluate( () => document.activeElement.textContent ); + expect( blockText ).toBe( '1 2 3 4' ); + } ); + + it( 'should not delete trailing spaces when deleting a word with alt + backspace', async () => { + await clickBlockAppender(); + await page.keyboard.type( 'alpha beta gamma delta' ); + await pressWithModifier( META_KEY, 'Backspace' ); + await page.keyboard.type( 'delta' ); + const blockText = await page.evaluate( () => document.activeElement.textContent ); + expect( blockText ).toBe( 'alpha beta gamma delta' ); + } ); } );