From b7eec8d20564072788e4c66195257264cf8a197e Mon Sep 17 00:00:00 2001 From: iseulde Date: Mon, 28 Jan 2019 17:57:27 +0100 Subject: [PATCH 1/3] WIP: make shift+enter work in lists --- .../editor/src/components/rich-text/index.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/packages/editor/src/components/rich-text/index.js b/packages/editor/src/components/rich-text/index.js index ea58c212ee3a2..9aaab4757a2a6 100644 --- a/packages/editor/src/components/rich-text/index.js +++ b/packages/editor/src/components/rich-text/index.js @@ -599,7 +599,24 @@ export class RichText extends Component { } if ( this.multilineTag ) { - if ( this.onSplit && isEmptyLine( record ) ) { + if ( event.shiftKey ) { + const text = getTextContent( record ); + const end = getSelectionEnd( record ); + const length = text.length; + let toInsert = '\n'; + + // If the caret is at the end of the text, and there is no + // trailing line break or no text at all, we have to insert two + // line breaks in order to create a new line visually and place + // the caret there. + if ( ( end === length || charAt( record, end ) === LINE_SEPARATOR ) && ( + text.charAt( end - 1 ) !== '\n' || length === 0 + ) ) { + toInsert = '\n\n'; + } + + this.onChange( insert( record, toInsert ) ); + } else if ( this.onSplit && isEmptyLine( record ) ) { this.onSplit( ...split( record ).map( this.valueToFormat ) ); } else { this.onChange( insertLineSeparator( record ) ); From e97ebe9b806df01d1ff89f729cd9946e7b474c98 Mon Sep 17 00:00:00 2001 From: iseulde Date: Tue, 12 Feb 2019 10:25:43 +0100 Subject: [PATCH 2/3] Merge similar logic --- .../editor/src/components/rich-text/index.js | 34 ++----------------- packages/rich-text/src/index.js | 1 + packages/rich-text/src/insert-line-break.js | 34 +++++++++++++++++++ 3 files changed, 38 insertions(+), 31 deletions(-) create mode 100644 packages/rich-text/src/insert-line-break.js diff --git a/packages/editor/src/components/rich-text/index.js b/packages/editor/src/components/rich-text/index.js index 9aaab4757a2a6..12da83aa2d4d3 100644 --- a/packages/editor/src/components/rich-text/index.js +++ b/packages/editor/src/components/rich-text/index.js @@ -33,6 +33,7 @@ import { toHTMLString, getTextContent, insert, + insertLineBreak, insertLineSeparator, isEmptyLine, unstableToDom, @@ -600,43 +601,14 @@ export class RichText extends Component { if ( this.multilineTag ) { if ( event.shiftKey ) { - const text = getTextContent( record ); - const end = getSelectionEnd( record ); - const length = text.length; - let toInsert = '\n'; - - // If the caret is at the end of the text, and there is no - // trailing line break or no text at all, we have to insert two - // line breaks in order to create a new line visually and place - // the caret there. - if ( ( end === length || charAt( record, end ) === LINE_SEPARATOR ) && ( - text.charAt( end - 1 ) !== '\n' || length === 0 - ) ) { - toInsert = '\n\n'; - } - - this.onChange( insert( record, toInsert ) ); + this.onChange( insertLineBreak( record ) ); } else if ( this.onSplit && isEmptyLine( record ) ) { this.onSplit( ...split( record ).map( this.valueToFormat ) ); } else { this.onChange( insertLineSeparator( record ) ); } } else if ( event.shiftKey || ! this.onSplit ) { - const text = getTextContent( record ); - const length = text.length; - let toInsert = '\n'; - - // If the caret is at the end of the text, and there is no - // trailing line break or no text at all, we have to insert two - // line breaks in order to create a new line visually and place - // the caret there. - if ( record.end === length && ( - text.charAt( length - 1 ) !== '\n' || length === 0 - ) ) { - toInsert = '\n\n'; - } - - this.onChange( insert( record, toInsert ) ); + this.onChange( insertLineBreak( record ) ); } else { this.splitContent(); } diff --git a/packages/rich-text/src/index.js b/packages/rich-text/src/index.js index 7ce8ed970e6eb..423046079132b 100644 --- a/packages/rich-text/src/index.js +++ b/packages/rich-text/src/index.js @@ -19,6 +19,7 @@ export { removeFormat } from './remove-format'; export { remove } from './remove'; export { replace } from './replace'; export { insert } from './insert'; +export { insertLineBreak } from './insert-line-break'; export { insertLineSeparator } from './insert-line-separator'; export { insertObject } from './insert-object'; export { slice } from './slice'; diff --git a/packages/rich-text/src/insert-line-break.js b/packages/rich-text/src/insert-line-break.js new file mode 100644 index 0000000000000..540214d614f3c --- /dev/null +++ b/packages/rich-text/src/insert-line-break.js @@ -0,0 +1,34 @@ +/** + * Internal dependencies + */ + +import { insert } from './insert'; +import { LINE_SEPARATOR } from './special-characters'; + +/** + * Inserts a line break at the given or selected position. Inserts two line + * breaks if at the end of a line. + * + * @param {Object} value Value to modify. + * + * @return {Object} The value with the line break(s) inserted. + */ +export function insertLineBreak( value ) { + const { text, end } = value; + const length = text.length; + + let toInsert = '\n'; + + // If the caret is at the end of the text, and there is no + // trailing line break or no text at all, we have to insert two + // line breaks in order to create a new line visually and place + // the caret there. + if ( + ( end === length || text[ end ] === LINE_SEPARATOR ) && + ( text[ end - 1 ] !== '\n' || length === 0 ) + ) { + toInsert = '\n\n'; + } + + return insert( value, toInsert ); +} From 97b8c088c65a942325f1d78013628bfbfd246453 Mon Sep 17 00:00:00 2001 From: iseulde Date: Tue, 12 Feb 2019 10:43:50 +0100 Subject: [PATCH 3/3] Add e2e tests --- .../blocks/__snapshots__/list.test.js.snap | 12 +++++++++++ packages/e2e-tests/specs/blocks/list.test.js | 21 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/packages/e2e-tests/specs/blocks/__snapshots__/list.test.js.snap b/packages/e2e-tests/specs/blocks/__snapshots__/list.test.js.snap index 71118e8d65118..ef176d16bb9d7 100644 --- a/packages/e2e-tests/specs/blocks/__snapshots__/list.test.js.snap +++ b/packages/e2e-tests/specs/blocks/__snapshots__/list.test.js.snap @@ -144,6 +144,18 @@ exports[`List should indent and outdent level 2 3`] = ` " `; +exports[`List should insert a line break on shift+enter 1`] = ` +" +
  • a

+" +`; + +exports[`List should insert a line break on shift+enter in a non trailing list item 1`] = ` +" +
  • a
  • b

  • c
+" +`; + exports[`List should outdent with children 1`] = ` "
  • a
    • b
      • c
diff --git a/packages/e2e-tests/specs/blocks/list.test.js b/packages/e2e-tests/specs/blocks/list.test.js index 98b7f74bd2536..915c9da4f537a 100644 --- a/packages/e2e-tests/specs/blocks/list.test.js +++ b/packages/e2e-tests/specs/blocks/list.test.js @@ -280,4 +280,25 @@ describe( 'List', () => { expect( await getEditedPostContent() ).toMatchSnapshot(); } ); + + it( 'should insert a line break on shift+enter', async () => { + await insertBlock( 'List' ); + await page.keyboard.type( 'a' ); + await pressKeyWithModifier( 'shift', 'Enter' ); + + expect( await getEditedPostContent() ).toMatchSnapshot(); + } ); + + it( 'should insert a line break on shift+enter in a non trailing list item', async () => { + await insertBlock( 'List' ); + await page.keyboard.type( 'a' ); + await page.keyboard.press( 'Enter' ); + await page.keyboard.type( 'b' ); + await page.keyboard.press( 'Enter' ); + await page.keyboard.type( 'c' ); + await page.keyboard.press( 'ArrowUp' ); + await pressKeyWithModifier( 'shift', 'Enter' ); + + expect( await getEditedPostContent() ).toMatchSnapshot(); + } ); } );