diff --git a/src/model/transaction/__tests__/__snapshots__/splitBlockInContentState-test.js.snap b/src/model/transaction/__tests__/__snapshots__/splitBlockInContentState-test.js.snap index 60085665dd..ce9eac7d0e 100644 --- a/src/model/transaction/__tests__/__snapshots__/splitBlockInContentState-test.js.snap +++ b/src/model/transaction/__tests__/__snapshots__/splitBlockInContentState-test.js.snap @@ -1,5 +1,229 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`must convert empty list item ContentBlock to unstyled rather than split 1`] = ` +Array [ + Object { + "characterList": Array [ + Object { + "entity": null, + "style": Array [], + }, + Object { + "entity": null, + "style": Array [], + }, + Object { + "entity": null, + "style": Array [], + }, + Object { + "entity": null, + "style": Array [], + }, + Object { + "entity": null, + "style": Array [], + }, + ], + "children": Array [], + "data": Object {}, + "depth": 0, + "key": "A", + "nextSibling": "B", + "parent": null, + "prevSibling": null, + "text": "Alpha", + "type": "unstyled", + }, + Object { + "characterList": Array [], + "children": Array [ + "C", + "F", + ], + "data": Object {}, + "depth": 0, + "key": "B", + "nextSibling": "G", + "parent": null, + "prevSibling": "A", + "text": "", + "type": "unstyled", + }, + Object { + "characterList": Array [], + "children": Array [ + "D", + "E", + ], + "data": Object {}, + "depth": 0, + "key": "C", + "nextSibling": "F", + "parent": "B", + "prevSibling": null, + "text": "", + "type": "unstyled", + }, + Object { + "characterList": Array [ + Object { + "entity": null, + "style": Array [], + }, + Object { + "entity": null, + "style": Array [], + }, + Object { + "entity": null, + "style": Array [], + }, + Object { + "entity": null, + "style": Array [], + }, + Object { + "entity": null, + "style": Array [], + }, + ], + "children": Array [], + "data": Object {}, + "depth": 0, + "key": "D", + "nextSibling": "E", + "parent": "C", + "prevSibling": null, + "text": "Delta", + "type": "unstyled", + }, + Object { + "characterList": Array [ + Object { + "entity": null, + "style": Array [], + }, + Object { + "entity": null, + "style": Array [], + }, + Object { + "entity": null, + "style": Array [], + }, + Object { + "entity": null, + "style": Array [], + }, + Object { + "entity": null, + "style": Array [], + }, + Object { + "entity": null, + "style": Array [], + }, + Object { + "entity": null, + "style": Array [], + }, + Object { + "entity": null, + "style": Array [], + }, + ], + "children": Array [], + "data": Object {}, + "depth": 0, + "key": "E", + "nextSibling": null, + "parent": "C", + "prevSibling": "D", + "text": "Elephant", + "type": "unstyled", + }, + Object { + "characterList": Array [ + Object { + "entity": null, + "style": Array [], + }, + Object { + "entity": null, + "style": Array [], + }, + Object { + "entity": null, + "style": Array [], + }, + Object { + "entity": null, + "style": Array [], + }, + ], + "children": Array [], + "data": Object {}, + "depth": 0, + "key": "F", + "nextSibling": null, + "parent": "B", + "prevSibling": "C", + "text": "Fire", + "type": "unstyled", + }, + Object { + "characterList": Array [ + Object { + "entity": null, + "style": Array [], + }, + Object { + "entity": null, + "style": Array [], + }, + Object { + "entity": null, + "style": Array [], + }, + Object { + "entity": null, + "style": Array [], + }, + Object { + "entity": null, + "style": Array [], + }, + Object { + "entity": null, + "style": Array [], + }, + ], + "children": Array [], + "data": Object {}, + "depth": 0, + "key": "G", + "nextSibling": null, + "parent": null, + "prevSibling": "B", + "text": "Gorila", + "type": "unstyled", + }, + Object { + "characterList": Array [], + "children": Array [], + "data": Object {}, + "depth": 0, + "key": "H", + "nextSibling": null, + "parent": null, + "prevSibling": "G", + "text": "", + "type": "unstyled", + }, +] +`; + exports[`must split at the beginning of a block 1`] = ` Array [ Object { @@ -395,6 +619,18 @@ Array [ "text": "Gorila", "type": "unstyled", }, + Object { + "characterList": Array [], + "children": Array [], + "data": Object {}, + "depth": 0, + "key": "H", + "nextSibling": null, + "parent": null, + "prevSibling": "G", + "text": "", + "type": "unordered-list-item", + }, ] `; @@ -619,6 +855,18 @@ Array [ "text": "Gorila", "type": "unstyled", }, + Object { + "characterList": Array [], + "children": Array [], + "data": Object {}, + "depth": 0, + "key": "H", + "nextSibling": null, + "parent": null, + "prevSibling": "G", + "text": "", + "type": "unordered-list-item", + }, ] `; @@ -1017,6 +1265,18 @@ Array [ "text": "Gorila", "type": "unstyled", }, + Object { + "characterList": Array [], + "children": Array [], + "data": Object {}, + "depth": 0, + "key": "H", + "nextSibling": null, + "parent": null, + "prevSibling": "G", + "text": "", + "type": "unordered-list-item", + }, ] `; @@ -1241,6 +1501,18 @@ Array [ "text": "Gorila", "type": "unstyled", }, + Object { + "characterList": Array [], + "children": Array [], + "data": Object {}, + "depth": 0, + "key": "H", + "nextSibling": null, + "parent": null, + "prevSibling": "G", + "text": "", + "type": "unordered-list-item", + }, ] `; @@ -1641,6 +1913,18 @@ Array [ "text": "Gorila", "type": "unstyled", }, + Object { + "characterList": Array [], + "children": Array [], + "data": Object {}, + "depth": 0, + "key": "H", + "nextSibling": null, + "parent": null, + "prevSibling": "G", + "text": "", + "type": "unordered-list-item", + }, ] `; @@ -1866,5 +2150,17 @@ Array [ "text": "Gorila", "type": "unstyled", }, + Object { + "characterList": Array [], + "children": Array [], + "data": Object {}, + "depth": 0, + "key": "H", + "nextSibling": null, + "parent": null, + "prevSibling": "G", + "text": "", + "type": "unordered-list-item", + }, ] `; diff --git a/src/model/transaction/__tests__/splitBlockInContentState-test.js b/src/model/transaction/__tests__/splitBlockInContentState-test.js index db47538bdf..11656875ca 100644 --- a/src/model/transaction/__tests__/splitBlockInContentState-test.js +++ b/src/model/transaction/__tests__/splitBlockInContentState-test.js @@ -70,6 +70,12 @@ const contentBlockNodes = [ prevSibling: 'B', text: 'Gorila', }), + new ContentBlockNode({ + key: 'H', + prevSibling: 'G', + text: '', + type: 'unordered-list-item', + }), ]; const treeSelectionState = SelectionState.createEmpty('A'); const treeContentState = contentState.set( @@ -208,3 +214,15 @@ test('must split at the end of a nested ContentBlock', () => { treeContentState, ); }); + +test('must convert empty list item ContentBlock to unstyled rather than split', () => { + assertSplitBlockInContentState( + treeSelectionState.merge({ + anchorOffset: 0, + focusOffset: 0, + anchorKey: 'H', + focusKey: 'H', + }), + treeContentState, + ); +}); diff --git a/src/model/transaction/splitBlockInContentState.js b/src/model/transaction/splitBlockInContentState.js index f7ec6f7fc6..0d3c20d989 100644 --- a/src/model/transaction/splitBlockInContentState.js +++ b/src/model/transaction/splitBlockInContentState.js @@ -18,10 +18,11 @@ import type ContentState from 'ContentState'; import type SelectionState from 'SelectionState'; const ContentBlockNode = require('ContentBlockNode'); -const Immutable = require('immutable'); const generateRandomKey = require('generateRandomKey'); +const Immutable = require('immutable'); const invariant = require('invariant'); +const modifyBlockForContentState = require('modifyBlockForContentState'); const {List, Map} = Immutable; @@ -95,10 +96,23 @@ const splitBlockInContentState = ( invariant(selectionState.isCollapsed(), 'Selection range must be collapsed.'); const key = selectionState.getAnchorKey(); - const offset = selectionState.getAnchorOffset(); const blockMap = contentState.getBlockMap(); const blockToSplit = blockMap.get(key); const text = blockToSplit.getText(); + + if (!text) { + const blockType = blockToSplit.getType(); + if ( + blockType === 'unordered-list-item' || + blockType === 'ordered-list-item' + ) { + return modifyBlockForContentState(contentState, selectionState, block => + block.merge({type: 'unstyled', depth: 0}), + ); + } + } + + const offset = selectionState.getAnchorOffset(); const chars = blockToSplit.getCharacterList(); const keyBelow = generateRandomKey(); const isExperimentalTreeBlock = blockToSplit instanceof ContentBlockNode;