Skip to content
This repository has been archived by the owner on Feb 6, 2023. It is now read-only.

Commit

Permalink
Break out of code block on enter on blank line
Browse files Browse the repository at this point in the history
Summary: When a user hits an enter on blank line after a blank line, it the editor breaks out of the code block and get back to normal text

Differential Revision: D6173646

fbshipit-source-id: dd448770b39293a23c69c17fbaa55335e65c56d1
  • Loading branch information
Hanzhi Zhang authored and facebook-github-bot committed Nov 3, 2017
1 parent 13da543 commit 548fd5d
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 18 deletions.
7 changes: 4 additions & 3 deletions src/model/modifier/RichTextEditorUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -367,8 +367,8 @@ const RichTextEditorUtil = {
},

/**
* When a collapsed cursor is at the start of the first styled block, or
* an empty styled block, changes block to 'unstyled'. Returns null if
* When a collapsed cursor is at the start of the first styled block, or
* an empty styled block, changes block to 'unstyled'. Returns null if
* block or selection does not meet that criteria.
*/
tryToRemoveBlockStyle: function(editorState: EditorState): ?ContentState {
Expand All @@ -389,7 +389,8 @@ const RichTextEditorUtil = {
if (
type === 'code-block' &&
blockBefore &&
blockBefore.getType() === 'code-block'
blockBefore.getType() === 'code-block' &&
blockBefore.getLength() !== 0
) {
return null;
}
Expand Down
25 changes: 23 additions & 2 deletions src/model/modifier/__tests__/RichTextEditorUtil-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,14 @@ describe('RichTextEditorUtil', () => {
});

it('removes a preceding atomic block', () => {
const blockSizeBeforeRemove = editorState
.getCurrentContent()
.getBlockMap().size;
const withAtomicBlock = insertAtomicBlock(editorState);
const afterBackspace = onBackspace(withAtomicBlock);
const contentState = afterBackspace.getCurrentContent();
const blockMap = contentState.getBlockMap();
expect(blockMap.size).toBe(4);
expect(blockMap.size).toBe(blockSizeBeforeRemove + 1);
expect(blockMap.some(block => block.getType() === 'atomic')).toBe(false);
});
});
Expand All @@ -129,6 +132,9 @@ describe('RichTextEditorUtil', () => {
});

it('removes a following atomic block', () => {
const blockSizeBeforeRemove = editorState
.getCurrentContent()
.getBlockMap().size;
const withAtomicBlock = insertAtomicBlock(editorState);
const content = withAtomicBlock.getCurrentContent();
const atomicKey = content
Expand Down Expand Up @@ -157,7 +163,22 @@ describe('RichTextEditorUtil', () => {
blockMapAfterDelete.some(block => block.getType() === 'atomic'),
).toBe(false);

expect(blockMapAfterDelete.size).toBe(4);
expect(blockMapAfterDelete.size).toBe(blockSizeBeforeRemove + 1);
});
});

describe('tryToRemoveBlockStyle', () => {
const {tryToRemoveBlockStyle} = RichTextEditorUtil;

it('breaks out of code block on enter two blank lines', () => {
const blankLine = selectionState.merge({anchorKey: 'e', focusKey: 'e'});
const withBlankLine = EditorState.forceSelection(editorState, blankLine);

const afterEnter = tryToRemoveBlockStyle(withBlankLine);
const lastBlock = afterEnter.getLastBlock();

expect(lastBlock.getType()).toBe('blockquote');
expect(lastBlock.getText()).toBe('Charlie');
});
});
});
21 changes: 11 additions & 10 deletions src/model/transaction/__tests__/removeRangeFromContentState-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ var removeRangeFromContentState = require('removeRangeFromContentState');

describe('removeRangeFromContentState', () => {
var {contentState, selectionState} = getSampleStateForTesting();
const blockSizeBeforeRemoval = contentState.getBlockMap().size;

function checkForCharacterList(block) {
expect(Immutable.List.isList(block.getCharacterList())).toBe(true);
Expand Down Expand Up @@ -119,7 +120,7 @@ describe('removeRangeFromContentState', () => {
var selection = selectionState.set('focusKey', 'b');
var afterRemoval = removeRangeFromContentState(contentState, selection);
var afterBlockMap = afterRemoval.getBlockMap();
expect(afterBlockMap.size).toBe(2);
expect(afterBlockMap.size).toBe(blockSizeBeforeRemoval - 1);
var alteredBlock = afterBlockMap.first();

// Block B is removed. Its contents replace the contents of block A,
Expand Down Expand Up @@ -147,7 +148,7 @@ describe('removeRangeFromContentState', () => {

var afterRemoval = removeRangeFromContentState(contentState, selection);
var afterBlockMap = afterRemoval.getBlockMap();
expect(afterBlockMap.size).toBe(2);
expect(afterBlockMap.size).toBe(blockSizeBeforeRemoval - 1);
var alteredBlock = afterBlockMap.first();

// A slice of block B contents replace the contents of block A,
Expand Down Expand Up @@ -179,7 +180,7 @@ describe('removeRangeFromContentState', () => {

var afterRemoval = removeRangeFromContentState(contentState, selection);
var afterBlockMap = afterRemoval.getBlockMap();
expect(afterBlockMap.size).toBe(2);
expect(afterBlockMap.size).toBe(blockSizeBeforeRemoval - 1);
var alteredBlock = afterBlockMap.first();

// Block A is effectively just emptied out, while block B is removed.
Expand Down Expand Up @@ -209,7 +210,7 @@ describe('removeRangeFromContentState', () => {
.first();
var afterRemoval = removeRangeFromContentState(contentState, selection);
var afterBlockMap = afterRemoval.getBlockMap();
expect(afterBlockMap.size).toBe(2);
expect(afterBlockMap.size).toBe(blockSizeBeforeRemoval - 1);
var alteredBlock = afterBlockMap.first();

expect(alteredBlock).not.toBe(originalBlockA);
Expand Down Expand Up @@ -244,7 +245,7 @@ describe('removeRangeFromContentState', () => {
.first();
var afterRemoval = removeRangeFromContentState(contentState, selection);
var afterBlockMap = afterRemoval.getBlockMap();
expect(afterBlockMap.size).toBe(2);
expect(afterBlockMap.size).toBe(blockSizeBeforeRemoval - 1);
var alteredBlock = afterBlockMap.first();

expect(alteredBlock).not.toBe(originalBlockA);
Expand Down Expand Up @@ -286,7 +287,7 @@ describe('removeRangeFromContentState', () => {
.first();
var afterRemoval = removeRangeFromContentState(contentState, selection);
var afterBlockMap = afterRemoval.getBlockMap();
expect(afterBlockMap.size).toBe(2);
expect(afterBlockMap.size).toBe(blockSizeBeforeRemoval - 1);
var alteredBlock = afterBlockMap.first();

expect(alteredBlock).not.toBe(originalBlockA);
Expand Down Expand Up @@ -325,7 +326,7 @@ describe('removeRangeFromContentState', () => {
.first();
var afterRemoval = removeRangeFromContentState(contentState, selection);
var afterBlockMap = afterRemoval.getBlockMap();
expect(afterBlockMap.size).toBe(2);
expect(afterBlockMap.size).toBe(blockSizeBeforeRemoval - 1);
var alteredBlock = afterBlockMap.first();

expect(alteredBlock).not.toBe(originalBlockA);
Expand Down Expand Up @@ -360,7 +361,7 @@ describe('removeRangeFromContentState', () => {
.first();
var afterRemoval = removeRangeFromContentState(contentState, selection);
var afterBlockMap = afterRemoval.getBlockMap();
expect(afterBlockMap.size).toBe(2);
expect(afterBlockMap.size).toBe(blockSizeBeforeRemoval - 1);
var alteredBlock = afterBlockMap.first();

expect(alteredBlock).not.toBe(originalBlockA);
Expand Down Expand Up @@ -395,7 +396,7 @@ describe('removeRangeFromContentState', () => {

var afterRemoval = removeRangeFromContentState(contentState, selection);
var afterBlockMap = afterRemoval.getBlockMap();
expect(afterBlockMap.size).toBe(2);
expect(afterBlockMap.size).toBe(blockSizeBeforeRemoval - 1);
var alteredBlock = afterBlockMap.first();

// no-op for the first block, since no new content is appended.
Expand Down Expand Up @@ -429,7 +430,7 @@ describe('removeRangeFromContentState', () => {

var afterRemoval = removeRangeFromContentState(contentState, selection);
var afterBlockMap = afterRemoval.getBlockMap();
expect(afterBlockMap.size).toBe(1);
expect(afterBlockMap.size).toBe(blockSizeBeforeRemoval - 2);
var alteredBlock = afterBlockMap.first();

expect(alteredBlock).not.toBe(originalBlockA);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const {List} = Immutable;

describe('splitBlockInContentState', () => {
var {contentState, selectionState} = getSampleStateForTesting();
const blockSizeBeforeSplit = contentState.getBlockMap().size;

function checkForCharacterList(block) {
expect(List.isList(block.getCharacterList())).toBe(true);
Expand Down Expand Up @@ -54,10 +55,11 @@ describe('splitBlockInContentState', () => {
});

it('must split at the beginning of a block', () => {
const blockSizeBeforeInsert = contentState.getBlockMap().size;
var initialBlock = contentState.getBlockMap().first();
var afterSplit = splitBlockInContentState(contentState, selectionState);
var afterBlockMap = afterSplit.getBlockMap();
expect(afterBlockMap.size).toBe(4);
expect(afterBlockMap.size).toBe(blockSizeBeforeInsert + 1);

var preSplitBlock = afterBlockMap.first();

Expand Down Expand Up @@ -92,7 +94,7 @@ describe('splitBlockInContentState', () => {

var afterSplit = splitBlockInContentState(contentState, selection);
var afterBlockMap = afterSplit.getBlockMap();
expect(afterBlockMap.size).toBe(4);
expect(afterBlockMap.size).toBe(blockSizeBeforeSplit + 1);

var preSplitBlock = afterBlockMap.first();
var postSplitBlock = afterBlockMap.skip(1).first();
Expand Down Expand Up @@ -137,7 +139,7 @@ describe('splitBlockInContentState', () => {

var afterSplit = splitBlockInContentState(contentState, selection);
var afterBlockMap = afterSplit.getBlockMap();
expect(afterBlockMap.size).toBe(4);
expect(afterBlockMap.size).toBe(blockSizeBeforeSplit + 1);

var preSplitBlock = afterBlockMap.first();
var postSplitBlock = afterBlockMap.skip(1).first();
Expand Down
18 changes: 18 additions & 0 deletions src/model/transaction/getSampleStateForTesting.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,24 @@ var BLOCKS = [
}),
new ContentBlock({
key: 'c',
type: 'code-block',
text: 'Test',
characterList: Immutable.List(Immutable.Repeat(CharacterMetadata.EMPTY, 4)),
}),
new ContentBlock({
key: 'd',
type: 'code-block',
text: '',
characterList: Immutable.List(),
}),
new ContentBlock({
key: 'e',
type: 'code-block',
text: '',
characterList: Immutable.List(),
}),
new ContentBlock({
key: 'f',
type: 'blockquote',
text: 'Charlie',
characterList: Immutable.List(
Expand Down

0 comments on commit 548fd5d

Please sign in to comment.