Skip to content

Commit

Permalink
fix(filters): handle removal of all blocks, inserting one unstyled
Browse files Browse the repository at this point in the history
  • Loading branch information
thibaudcolas committed Jan 22, 2019
1 parent 05edf66 commit 652750f
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 41 deletions.
14 changes: 12 additions & 2 deletions src/lib/filters/selection.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,23 @@ import { ContentState } from "draft-js"

/**
* Applies the new content to the editor state, optionally moving the selection
* to be on a valid block (https://github.com/thibaudcolas/draftjs-filters/issues/27).
* to be on a valid block, inserting one if needed.
* See https://github.com/thibaudcolas/draftjs-filters/issues/27.
*/
export const applyContentWithSelection = (
editorState: EditorStateType,
content: ContentState,
nextContent: ContentState,
) => {
// If the block map is empty, insert a new unstyled block and put the selection on it.
if (nextContent.getBlockMap().size === 0) {
return EditorState.moveFocusToEnd(
EditorState.set(editorState, {
currentContent: ContentState.createFromText(""),
}),
)
}

const nextState = EditorState.set(editorState, {
currentContent: nextContent,
})
Expand All @@ -29,7 +39,7 @@ export const applyContentWithSelection = (
const nextKeys = nextContent.getBlockMap().keySeq()

// Find the first key whose successor is different in the old content (because a block was removed).
// Starting from the end so the selection is preserved towards the last not-removed block in the filtered region.
// Starting from the end so the selection is preserved towards the last preserved block in the filtered region.
const nextAnchorKey = nextKeys
.reverse()
.find((k) => content.getKeyAfter(k) !== nextContent.getKeyAfter(k))
Expand Down
76 changes: 37 additions & 39 deletions src/lib/filters/selection.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,43 @@ describe("selection", () => {
]),
]

it("inserts a block if there is none left, with selection on it", () => {
let editorState = EditorState.createWithContent(
convertFromRaw({
entityMap: {},
blocks: [
{
key: "f8beh",
text: "test",
depth: 3,
},
],
}),
)

const content = editorState.getCurrentContent()
const nextContent = filters.reduce((c, filter) => filter(c), content)
const nextState = applyContentWithSelection(
editorState,
content,
nextContent,
)
const block = nextState.getCurrentContent().getFirstBlock()

expect(block.toJS()).toMatchObject({
text: "",
type: "unstyled",
depth: 0,
})

expect(nextState.getSelection().toJS()).toMatchObject({
anchorKey: block.getKey(),
anchorOffset: 0,
focusKey: block.getKey(),
focusOffset: 0,
})
})

it("does not change selection if valid", () => {
let editorState = EditorState.createWithContent(
convertFromRaw({
Expand Down Expand Up @@ -134,45 +171,6 @@ describe("selection", () => {
})
})

it("does not change selection if it cannot be moved elsewhere", () => {
let editorState = EditorState.createWithContent(
convertFromRaw({
entityMap: {},
blocks: [
{
key: "f8beh",
text: "test",
depth: 3,
},
],
}),
)
editorState = EditorState.acceptSelection(
editorState,
editorState.getSelection().merge({
anchorKey: "f8beh",
focusKey: "f8beh",
anchorOffset: 4,
focusOffset: 4,
}),
)

const content = editorState.getCurrentContent()
const nextContent = filters.reduce((c, filter) => filter(c), content)
const nextState = applyContentWithSelection(
editorState,
content,
nextContent,
)

expect(nextState.getSelection().toJS()).toMatchObject({
anchorKey: "f8beh",
anchorOffset: 4,
focusKey: "f8beh",
focusOffset: 4,
})
})

it("works for the last block", () => {
let editorState = EditorState.createWithContent(
convertFromRaw({
Expand Down

0 comments on commit 652750f

Please sign in to comment.