@studysync/draft-js-modifiers 0.4.12 → 0.4.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/insertBlockAfter.js +3 -1
- package/es/insertBlockBefore.js +3 -1
- package/flow/stub/__dev__.js +3 -0
- package/insertBlockAfter.js +3 -1
- package/insertBlockBefore.js +3 -1
- package/package.json +4 -1
- package/script/add-module.js +48 -0
- package/src/addBlock.js +98 -0
- package/src/adjustBlockDepth.js +21 -0
- package/src/atEndOfBlock.js +10 -0
- package/src/atStartOfBlock.js +7 -0
- package/src/changeBlockType.js +19 -0
- package/src/getAllEntities.js +14 -0
- package/src/getEntitiesForBlock.js +29 -0
- package/src/getEntitiesForSelection.js +20 -0
- package/src/getSelectedText.js +11 -0
- package/src/getSimilarAdjacentBlocks.js +53 -0
- package/src/index.js +42 -0
- package/src/insertAtomicBlock.js +23 -0
- package/src/insertBlockAfter.js +42 -0
- package/src/insertBlockBefore.js +42 -0
- package/src/insertEmptyBlock.js +12 -0
- package/src/insertEntity.js +56 -0
- package/src/insertNewBlock.js +61 -0
- package/src/insertText.js +23 -0
- package/src/mergeBlockData.js +13 -0
- package/src/mergeBlockDataByKey.js +12 -0
- package/src/mergeEntityData.js +13 -0
- package/src/modifyBlock.js +20 -0
- package/src/modifyBlockByKey.js +19 -0
- package/src/moveCaretAfterBlock.js +26 -0
- package/src/moveCaretToEnd.js +20 -0
- package/src/removeBlock.js +43 -0
- package/src/removeBlockStyle.js +17 -0
- package/src/removeEntity.js +38 -0
- package/src/removeInlineStyles.js +29 -0
- package/src/resetBlock.js +29 -0
- package/src/selectAll.js +15 -0
- package/src/selectBlockByKey.js +20 -0
- package/src/setBlockData.js +14 -0
- package/src/toggleBlockStyle.js +33 -0
- package/src/toggleBlockType.js +12 -0
- package/src/toggleEntity.js +11 -0
- package/src/toggleInlineStyle.js +11 -0
- package/src/trimEditorState.js +41 -0
- package/src/utils/getCurrentBlock.js +10 -0
- package/src/utils/numbers.js +3 -0
- package/test/adjustBlockDepth.js +45 -0
- package/test/export.js +14 -0
- package/test/fixtures/createEditorState.js +12 -0
- package/test/fixtures/omitBlockKeysFromRawContent.js +9 -0
- package/test/insertAtomicBlock.js +89 -0
- package/test/insertEmptyBlock.js +65 -0
- package/test/insertNewBlock.js +68 -0
- package/test/insertText.js +58 -0
- package/test/mergeBlockData.js +40 -0
- package/test/mergeBlockDataByKey.js +103 -0
- package/test/mergeEntityData.js +49 -0
- package/test/modifyBlock.js +52 -0
- package/test/modifyBlockByKey.js +91 -0
- package/test/removeBlockStyle.js +52 -0
- package/test/removeInlineStyles.js +68 -0
- package/test/resetBlock.js +83 -0
- package/test/toggleBlockType.js +4 -0
- package/test/toggleEntity.js +4 -0
- package/test/toggleInlineStyle.js +4 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { SelectionState } from "draft-js"
|
|
2
|
+
import { Modifier } from "draft-js"
|
|
3
|
+
import { EditorState } from "draft-js"
|
|
4
|
+
import { getSelectedText } from "."
|
|
5
|
+
|
|
6
|
+
const insertEntity = (editorState, text, type, data, mutability = 'MUTABLE') => {
|
|
7
|
+
const selectedText = getSelectedText(editorState)
|
|
8
|
+
const contentState = editorState.getCurrentContent()
|
|
9
|
+
const selection = editorState.getSelection()
|
|
10
|
+
const textWithSpace = text.concat(' ')
|
|
11
|
+
const newContent = selectedText ? Modifier.replaceText(
|
|
12
|
+
contentState,
|
|
13
|
+
selection,
|
|
14
|
+
text
|
|
15
|
+
) : Modifier.insertText(
|
|
16
|
+
contentState,
|
|
17
|
+
selection,
|
|
18
|
+
textWithSpace
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
const newContentWithEntity = newContent.createEntity(
|
|
22
|
+
type,
|
|
23
|
+
mutability,
|
|
24
|
+
data,
|
|
25
|
+
false
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
const entityKey = newContentWithEntity.getLastCreatedEntityKey()
|
|
29
|
+
|
|
30
|
+
const anchorOffset = selection.getAnchorOffset()
|
|
31
|
+
const newSelection = new SelectionState({
|
|
32
|
+
anchorKey: selection.getAnchorKey(),
|
|
33
|
+
anchorOffset,
|
|
34
|
+
focusKey: selection.getAnchorKey(),
|
|
35
|
+
focusOffset: anchorOffset + text.length,
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
const newContentWithLink = Modifier.applyEntity(
|
|
39
|
+
newContentWithEntity,
|
|
40
|
+
newSelection,
|
|
41
|
+
entityKey
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
const withLinkText = EditorState.push(
|
|
45
|
+
editorState,
|
|
46
|
+
newContentWithLink,
|
|
47
|
+
'insert-characters'
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
return EditorState.forceSelection(
|
|
51
|
+
withLinkText,
|
|
52
|
+
newContent.getSelectionAfter()
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export default insertEntity
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import { EditorState, ContentBlock, CharacterMetadata, genKey } from 'draft-js'
|
|
4
|
+
import { Map, List, Repeat } from 'immutable'
|
|
5
|
+
import getCurrentBlock from './utils/getCurrentBlock'
|
|
6
|
+
|
|
7
|
+
import type { DraftBlockType } from 'draft-js/lib/DraftBlockType'
|
|
8
|
+
|
|
9
|
+
const insertNewBlock = (
|
|
10
|
+
editorState: EditorState,
|
|
11
|
+
blockType: DraftBlockType = 'unstyled',
|
|
12
|
+
text: string = '',
|
|
13
|
+
data: Object = {}
|
|
14
|
+
): EditorState => {
|
|
15
|
+
const content = editorState.getCurrentContent()
|
|
16
|
+
const selection = editorState.getSelection()
|
|
17
|
+
const currentBlock = getCurrentBlock(editorState)
|
|
18
|
+
const emptyBlockKey = genKey()
|
|
19
|
+
const emptyBlock = new ContentBlock({
|
|
20
|
+
key: emptyBlockKey,
|
|
21
|
+
type: blockType,
|
|
22
|
+
text,
|
|
23
|
+
characterList: List(Repeat(CharacterMetadata.create(), text.length)),
|
|
24
|
+
data: Map().merge(data),
|
|
25
|
+
})
|
|
26
|
+
const blockMap = content.getBlockMap()
|
|
27
|
+
const blocksBefore = blockMap.toSeq().takeUntil(value => value === currentBlock)
|
|
28
|
+
const blocksAfter = blockMap.toSeq().skipUntil(value => value === currentBlock).rest()
|
|
29
|
+
const augmentedBlocks = [
|
|
30
|
+
[
|
|
31
|
+
currentBlock.getKey(),
|
|
32
|
+
currentBlock,
|
|
33
|
+
],
|
|
34
|
+
[
|
|
35
|
+
emptyBlockKey,
|
|
36
|
+
emptyBlock,
|
|
37
|
+
],
|
|
38
|
+
]
|
|
39
|
+
const newBlocks = blocksBefore.concat(augmentedBlocks, blocksAfter).toOrderedMap()
|
|
40
|
+
const focusKey = emptyBlockKey
|
|
41
|
+
const newContent = content.merge({
|
|
42
|
+
blockMap: newBlocks,
|
|
43
|
+
selectionBefore: selection,
|
|
44
|
+
selectionAfter: selection.merge({
|
|
45
|
+
anchorKey: focusKey,
|
|
46
|
+
anchorOffset: 0,
|
|
47
|
+
focusKey,
|
|
48
|
+
focusOffset: 0,
|
|
49
|
+
isBackward: false,
|
|
50
|
+
}),
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
const newState = EditorState.push(
|
|
54
|
+
editorState,
|
|
55
|
+
newContent,
|
|
56
|
+
'split-block'
|
|
57
|
+
)
|
|
58
|
+
return EditorState.forceSelection(newState, newContent.getSelectionAfter())
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export default insertNewBlock
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import { EditorState, Modifier } from 'draft-js'
|
|
4
|
+
|
|
5
|
+
const insertText = (editorState: EditorState, text: string, entity?: ?string = null): EditorState => {
|
|
6
|
+
const selection = editorState.getSelection()
|
|
7
|
+
const content = editorState.getCurrentContent()
|
|
8
|
+
const newContent = Modifier[selection.isCollapsed() ? 'insertText' : 'replaceText'](
|
|
9
|
+
content,
|
|
10
|
+
selection,
|
|
11
|
+
text,
|
|
12
|
+
editorState.getCurrentInlineStyle(),
|
|
13
|
+
entity
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
return EditorState.push(
|
|
17
|
+
editorState,
|
|
18
|
+
newContent,
|
|
19
|
+
'insert-fragment'
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default insertText
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import { EditorState, Modifier } from 'draft-js'
|
|
4
|
+
import { Map } from 'immutable'
|
|
5
|
+
|
|
6
|
+
const mergeBlockData = (editorState: EditorState, data: { [id: string]: any }): EditorState => {
|
|
7
|
+
const content = editorState.getCurrentContent()
|
|
8
|
+
const selection = editorState.getSelection()
|
|
9
|
+
const newContent = Modifier.mergeBlockData(content, selection, Map(data))
|
|
10
|
+
return EditorState.push(editorState, newContent, 'change-block-data')
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default mergeBlockData
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import { EditorState } from 'draft-js'
|
|
4
|
+
|
|
5
|
+
const mergeBlockDataByKey = (editorState: EditorState, blockKey: string, data: { [id: string]: any }): EditorState => {
|
|
6
|
+
const content = editorState.getCurrentContent()
|
|
7
|
+
const updatedBlock = content.getBlockForKey(blockKey).mergeIn(['data'], data)
|
|
8
|
+
const blockMap = content.getBlockMap().merge({ [blockKey]: updatedBlock })
|
|
9
|
+
return EditorState.push(editorState, content.merge({ blockMap }), 'change-block-data')
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default mergeBlockDataByKey
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import { EditorState } from 'draft-js'
|
|
4
|
+
|
|
5
|
+
const mergeEntityData = (editorState: EditorState, entityKey: string, data: Object): EditorState => {
|
|
6
|
+
const newContentState = editorState.getCurrentContent().mergeEntityData(entityKey, data)
|
|
7
|
+
return EditorState.forceSelection(
|
|
8
|
+
EditorState.push(editorState, newContentState, 'apply-entity'),
|
|
9
|
+
editorState.getSelection()
|
|
10
|
+
)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default mergeEntityData
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import { EditorState } from 'draft-js'
|
|
4
|
+
import modifyBlockForContentState from 'draft-js/lib/modifyBlockForContentState'
|
|
5
|
+
|
|
6
|
+
import type { ContentBlock } from 'draft-js'
|
|
7
|
+
|
|
8
|
+
const modifyBlock = (editorState: EditorState, blockData: ContentBlock): EditorState => {
|
|
9
|
+
const content = editorState.getCurrentContent()
|
|
10
|
+
const selection = editorState.getSelection()
|
|
11
|
+
const newContent = modifyBlockForContentState(content, selection, block => block.merge(blockData))
|
|
12
|
+
|
|
13
|
+
return EditorState.push(
|
|
14
|
+
editorState,
|
|
15
|
+
newContent,
|
|
16
|
+
'split-block' // TODO: will this do ?
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default modifyBlock
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import { EditorState } from 'draft-js'
|
|
4
|
+
|
|
5
|
+
import type { ContentBlock } from 'draft-js'
|
|
6
|
+
|
|
7
|
+
const modifyBlockByKey = (editorState: EditorState, blockKey: string, blockData: ContentBlock): EditorState => {
|
|
8
|
+
const content = editorState.getCurrentContent()
|
|
9
|
+
const blockMap = content.getBlockMap().map(b => b.key === blockKey ? b.merge(blockData) : b)
|
|
10
|
+
const newContent = content.merge({ blockMap })
|
|
11
|
+
|
|
12
|
+
return EditorState.push(
|
|
13
|
+
editorState,
|
|
14
|
+
newContent,
|
|
15
|
+
'split-block' // TODO: will this do ?
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default modifyBlockByKey
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { EditorState } from "draft-js"
|
|
2
|
+
import { SelectionState } from "draft-js"
|
|
3
|
+
|
|
4
|
+
const moveCaretAfterBlock = (editorState, block) => {
|
|
5
|
+
const content = editorState.getCurrentContent()
|
|
6
|
+
const nextBlock = content.getBlockAfter(block.getKey())
|
|
7
|
+
const key = nextBlock ? nextBlock.getKey() : undefined
|
|
8
|
+
|
|
9
|
+
if (key) {
|
|
10
|
+
const selectionState = SelectionState.createEmpty()
|
|
11
|
+
const newSelectionState = selectionState.merge({
|
|
12
|
+
anchorKey: key,
|
|
13
|
+
anchorOffset: 0,
|
|
14
|
+
focusKey: key,
|
|
15
|
+
focusOffset: 0,
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
return EditorState.forceSelection(
|
|
19
|
+
editorState,
|
|
20
|
+
newSelectionState
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
return editorState
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default moveCaretAfterBlock
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { SelectionState } from "draft-js"
|
|
2
|
+
import { EditorState } from "draft-js"
|
|
3
|
+
|
|
4
|
+
const moveCaretToEnd = (editorState) => {
|
|
5
|
+
const content = editorState.getCurrentContent()
|
|
6
|
+
const lastBlock = content.getLastBlock()
|
|
7
|
+
|
|
8
|
+
const key = lastBlock.getKey()
|
|
9
|
+
const length = lastBlock.getLength()
|
|
10
|
+
|
|
11
|
+
const selection = new SelectionState({
|
|
12
|
+
anchorKey: key,
|
|
13
|
+
anchorOffset: length,
|
|
14
|
+
focusKey: key,
|
|
15
|
+
focusOffset: length,
|
|
16
|
+
})
|
|
17
|
+
return EditorState.forceSelection(editorState, selection)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default moveCaretToEnd
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { SelectionState } from "draft-js"
|
|
2
|
+
import { Modifier } from "draft-js"
|
|
3
|
+
|
|
4
|
+
// from draft-js-plugins/draft-js-plugins/packages/drag-n-drop/src/modifiers/addBlock.ts
|
|
5
|
+
const removeBlock = (contentState, blockKey) => {
|
|
6
|
+
const afterKey = contentState.getKeyAfter(blockKey)
|
|
7
|
+
const afterBlock = contentState.getBlockForKey(afterKey)
|
|
8
|
+
let targetRange
|
|
9
|
+
|
|
10
|
+
// Only if the following block the last with no text then the whole block
|
|
11
|
+
// should be removed. Otherwise the block should be reduced to an unstyled block
|
|
12
|
+
// without any characters.
|
|
13
|
+
if (
|
|
14
|
+
afterBlock
|
|
15
|
+
&& afterBlock.getType() === 'unstyled'
|
|
16
|
+
&& afterBlock.getLength() === 0
|
|
17
|
+
&& afterBlock === contentState.getBlockMap().last()
|
|
18
|
+
) {
|
|
19
|
+
targetRange = new SelectionState({
|
|
20
|
+
anchorKey: blockKey,
|
|
21
|
+
anchorOffset: 0,
|
|
22
|
+
focusKey: afterKey,
|
|
23
|
+
focusOffset: 0,
|
|
24
|
+
})
|
|
25
|
+
} else {
|
|
26
|
+
targetRange = new SelectionState({
|
|
27
|
+
anchorKey: blockKey,
|
|
28
|
+
anchorOffset: 0,
|
|
29
|
+
focusKey: blockKey,
|
|
30
|
+
focusOffset: 1,
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// change the blocktype and remove the characterList entry with the block
|
|
35
|
+
const newContentState = Modifier.setBlockType(
|
|
36
|
+
contentState,
|
|
37
|
+
targetRange,
|
|
38
|
+
'unstyled'
|
|
39
|
+
)
|
|
40
|
+
return Modifier.removeRange(newContentState, targetRange, 'backward')
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export default removeBlock
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import { EditorState, RichUtils } from 'draft-js'
|
|
4
|
+
|
|
5
|
+
const removeBlockStyle = (editorState: EditorState): EditorState => {
|
|
6
|
+
const withoutBlockStyle = RichUtils.tryToRemoveBlockStyle(editorState)
|
|
7
|
+
if (withoutBlockStyle) {
|
|
8
|
+
return EditorState.push(
|
|
9
|
+
editorState,
|
|
10
|
+
withoutBlockStyle,
|
|
11
|
+
'change-block-type'
|
|
12
|
+
)
|
|
13
|
+
}
|
|
14
|
+
return editorState
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default removeBlockStyle
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Modifier } from "draft-js"
|
|
2
|
+
import { EditorState } from "draft-js"
|
|
3
|
+
|
|
4
|
+
const removeEntity = (editorState, entity) => {
|
|
5
|
+
const contentState = editorState.getCurrentContent()
|
|
6
|
+
const selectionState = editorState.getSelection()
|
|
7
|
+
const startKey = selectionState.getStartKey()
|
|
8
|
+
const contentBlock = contentState.getBlockForKey(startKey)
|
|
9
|
+
|
|
10
|
+
/* istanbul ignore if */
|
|
11
|
+
if (!entity) return editorState
|
|
12
|
+
|
|
13
|
+
let entitySelection = null
|
|
14
|
+
|
|
15
|
+
contentBlock.findEntityRanges(
|
|
16
|
+
character => character.getEntity() === entity.entityKey,
|
|
17
|
+
(start, end) => {
|
|
18
|
+
entitySelection = selectionState.merge({
|
|
19
|
+
anchorOffset: start,
|
|
20
|
+
focusOffset: end,
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
const newContentState = Modifier.applyEntity(
|
|
26
|
+
contentState,
|
|
27
|
+
entitySelection,
|
|
28
|
+
null
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
return EditorState.push(
|
|
32
|
+
editorState,
|
|
33
|
+
newContentState,
|
|
34
|
+
'apply-entity'
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export default removeEntity
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import { EditorState, ContentState, CharacterMetadata, Modifier } from 'draft-js'
|
|
4
|
+
import getCurrentBlock from './utils/getCurrentBlock'
|
|
5
|
+
|
|
6
|
+
const removeInlineStyles = (editorState: EditorState, inlineStyles: Array<string> = []): EditorState => {
|
|
7
|
+
const selection = editorState.getSelection()
|
|
8
|
+
const content = editorState.getCurrentContent()
|
|
9
|
+
let newContent
|
|
10
|
+
|
|
11
|
+
if (selection.isCollapsed()) {
|
|
12
|
+
const block = getCurrentBlock(editorState)
|
|
13
|
+
const updatedCharacterList = block.getCharacterList().map(c => {
|
|
14
|
+
return inlineStyles.reduce((characterMetadata: CharacterMetadata, style: string): CharacterMetadata => {
|
|
15
|
+
return CharacterMetadata.removeStyle(characterMetadata, style)
|
|
16
|
+
}, c)
|
|
17
|
+
})
|
|
18
|
+
const updatedBlock = block.set('characterList', updatedCharacterList)
|
|
19
|
+
newContent = content.merge({ blockMap: content.getBlockMap().merge({ [block.getKey()]: updatedBlock }) })
|
|
20
|
+
} else {
|
|
21
|
+
newContent = inlineStyles.reduce((contentState: ContentState, style: string): ContentState => {
|
|
22
|
+
return Modifier.removeInlineStyle(contentState, selection, style)
|
|
23
|
+
}, content)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return EditorState.push(editorState, newContent, 'change-inline-style')
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export default removeInlineStyles
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import { EditorState, SelectionState, Modifier } from 'draft-js'
|
|
4
|
+
|
|
5
|
+
import type { ContentBlock } from 'draft-js'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Remove range also change block type to 'unstyled'
|
|
9
|
+
*/
|
|
10
|
+
const resetBlock = (editorState: EditorState, block: ContentBlock): EditorState => {
|
|
11
|
+
const content = editorState.getCurrentContent()
|
|
12
|
+
const key = block.getKey()
|
|
13
|
+
const targetRange = new SelectionState({
|
|
14
|
+
anchorKey: key,
|
|
15
|
+
anchorOffset: 0,
|
|
16
|
+
focusKey: key,
|
|
17
|
+
focusOffset: block.getLength(),
|
|
18
|
+
})
|
|
19
|
+
const withoutTargetContent = Modifier.removeRange(content, targetRange, 'backward')
|
|
20
|
+
const resetBlock = Modifier.setBlockType(
|
|
21
|
+
withoutTargetContent,
|
|
22
|
+
withoutTargetContent.getSelectionAfter(),
|
|
23
|
+
'unstyled'
|
|
24
|
+
)
|
|
25
|
+
const newState = EditorState.push(editorState, resetBlock, 'remove-range')
|
|
26
|
+
return EditorState.forceSelection(newState, resetBlock.getSelectionAfter())
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export default resetBlock
|
package/src/selectAll.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { EditorState } from "draft-js"
|
|
2
|
+
|
|
3
|
+
const selectAll = (editorState) => {
|
|
4
|
+
const currentContent = editorState.getCurrentContent()
|
|
5
|
+
const selectionState = editorState.getSelection().merge({
|
|
6
|
+
anchorKey: currentContent.getFirstBlock().getKey(),
|
|
7
|
+
anchorOffset: 0,
|
|
8
|
+
focusOffset: currentContent.getLastBlock().getText().length,
|
|
9
|
+
focusKey: currentContent.getLastBlock().getKey(),
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
return EditorState.forceSelection(editorState, selectionState)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default selectAll
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { SelectionState } from "draft-js"
|
|
2
|
+
import { EditorState } from "draft-js"
|
|
3
|
+
|
|
4
|
+
const selectBlockByKey = (editorState, key) => {
|
|
5
|
+
const currentBlock = editorState.getCurrentContent().getBlockForKey(key)
|
|
6
|
+
const selectionState = SelectionState.createEmpty()
|
|
7
|
+
const entireBlockSelectionState = selectionState.merge({
|
|
8
|
+
anchorKey: key,
|
|
9
|
+
anchorOffset: 0,
|
|
10
|
+
focusKey: key,
|
|
11
|
+
focusOffset: currentBlock.getText().length,
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
return EditorState.forceSelection(
|
|
15
|
+
editorState,
|
|
16
|
+
entireBlockSelectionState
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default selectBlockByKey
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { EditorState } from "draft-js"
|
|
2
|
+
import { Modifier } from "draft-js"
|
|
3
|
+
|
|
4
|
+
const setBlockData = (editorState, data) => {
|
|
5
|
+
const newContentState = Modifier.setBlockData(
|
|
6
|
+
editorState.getCurrentContent(),
|
|
7
|
+
editorState.getSelection(),
|
|
8
|
+
data
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
return EditorState.push(editorState, newContentState, 'change-block-data')
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default setBlockData
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { RichUtils } from "draft-js"
|
|
2
|
+
import { EditorState } from "draft-js"
|
|
3
|
+
import { Modifier } from "draft-js"
|
|
4
|
+
import { Map } from 'immutable'
|
|
5
|
+
|
|
6
|
+
const toggleBlockStyle = (editorState, { type: blockStyle, data }) => {
|
|
7
|
+
/* istanbul ignore else */
|
|
8
|
+
if (data) {
|
|
9
|
+
const selection = editorState.getSelection()
|
|
10
|
+
|
|
11
|
+
const newContentState = Modifier.mergeBlockData(
|
|
12
|
+
editorState.getCurrentContent(),
|
|
13
|
+
selection,
|
|
14
|
+
Map(data)
|
|
15
|
+
)
|
|
16
|
+
const newEditorState = EditorState.push(
|
|
17
|
+
editorState,
|
|
18
|
+
newContentState,
|
|
19
|
+
'change-block-data'
|
|
20
|
+
)
|
|
21
|
+
return RichUtils.toggleBlockType(newEditorState, blockStyle)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// We currently always have data, but just in case we add new types in the
|
|
25
|
+
// future, the default action is to just blindly toggle it.
|
|
26
|
+
/* istanbul ignore next */
|
|
27
|
+
return RichUtils.toggleBlockType(
|
|
28
|
+
editorState,
|
|
29
|
+
blockStyle
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export default toggleBlockStyle
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import { RichUtils } from 'draft-js'
|
|
4
|
+
|
|
5
|
+
import type { EditorState } from 'draft-js'
|
|
6
|
+
import type { DraftBlockType } from 'draft-js/lib/DraftBlockType'
|
|
7
|
+
|
|
8
|
+
const toggleBlockType = (editorState: EditorState, blockType: DraftBlockType): EditorState => {
|
|
9
|
+
return RichUtils.toggleBlockType(editorState, blockType)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default toggleBlockType
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import { RichUtils } from 'draft-js'
|
|
4
|
+
|
|
5
|
+
import type { EditorState } from 'draft-js'
|
|
6
|
+
|
|
7
|
+
const toggleEntity = (editorState: EditorState, entityKey: ?string): EditorState => {
|
|
8
|
+
return RichUtils.toggleLink(editorState, editorState.getSelection(), entityKey)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default toggleEntity
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import { RichUtils } from 'draft-js'
|
|
4
|
+
|
|
5
|
+
import type { EditorState } from 'draft-js'
|
|
6
|
+
|
|
7
|
+
const toggleInlineStyle = (editorState: EditorState, inlineStyle: string): EditorState => {
|
|
8
|
+
return RichUtils.toggleInlineStyle(editorState, inlineStyle)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default toggleInlineStyle
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { EditorState, Modifier, SelectionState } from 'draft-js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Taken from:
|
|
5
|
+
* https://stackoverflow.com/questions/46802855/draft-js-how-to-trim-contents
|
|
6
|
+
*
|
|
7
|
+
* This *might* mess up entities, but so far I haven't seen any issues
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const trimEditorState = (currentEditorState) => {
|
|
11
|
+
const currentContent = currentEditorState.getCurrentContent()
|
|
12
|
+
const newContent = currentContent.getBlockMap().reduce((accumulator, block) => {
|
|
13
|
+
const key = block.getKey()
|
|
14
|
+
const text = block.getText()
|
|
15
|
+
const trimmedLeft = text.trimLeft()
|
|
16
|
+
const trimmedRight = text.trimRight()
|
|
17
|
+
const offset = text.length - trimmedLeft.length
|
|
18
|
+
|
|
19
|
+
const textToReplaceLeft = new SelectionState({
|
|
20
|
+
anchorKey: key,
|
|
21
|
+
focusKey: key,
|
|
22
|
+
anchorOffset: 0,
|
|
23
|
+
focusOffset: offset,
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
const leftTrimmedContent = Modifier.replaceText(accumulator, textToReplaceLeft, '')
|
|
27
|
+
|
|
28
|
+
const textToReplaceRight = new SelectionState({
|
|
29
|
+
anchorKey: key,
|
|
30
|
+
focusKey: key,
|
|
31
|
+
anchorOffset: trimmedRight.length - offset,
|
|
32
|
+
focusOffset: text.length - offset,
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
return Modifier.replaceText(leftTrimmedContent, textToReplaceRight, '')
|
|
36
|
+
}, currentContent)
|
|
37
|
+
|
|
38
|
+
return EditorState.push(currentEditorState, newContent, 'remove-range')
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default trimEditorState
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import type { EditorState, ContentBlock } from 'draft-js'
|
|
4
|
+
|
|
5
|
+
const getCurrentBlock = (editorState: EditorState): ContentBlock => {
|
|
6
|
+
const selection = editorState.getSelection()
|
|
7
|
+
return editorState.getCurrentContent().getBlockForKey(selection.getEndKey())
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default getCurrentBlock
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import test from 'ava'
|
|
2
|
+
import { convertToRaw } from 'draft-js'
|
|
3
|
+
import createEditorState from './fixtures/createEditorState'
|
|
4
|
+
|
|
5
|
+
import adjustBlockDepth from '../src/adjustBlockDepth'
|
|
6
|
+
|
|
7
|
+
const rawContentState = (type, ...depths) => ({
|
|
8
|
+
entityMap: {},
|
|
9
|
+
blocks: depths.map((depth, i) => ({
|
|
10
|
+
key: `item${i}`,
|
|
11
|
+
text: `test ${i}`,
|
|
12
|
+
type,
|
|
13
|
+
depth,
|
|
14
|
+
inlineStyleRanges: [],
|
|
15
|
+
entityRanges: [],
|
|
16
|
+
data: {},
|
|
17
|
+
})),
|
|
18
|
+
})
|
|
19
|
+
const selectionState = () => ({
|
|
20
|
+
anchorKey: 'item1',
|
|
21
|
+
anchorOffset: 0,
|
|
22
|
+
focusKey: 'item1',
|
|
23
|
+
focusOffset: 0,
|
|
24
|
+
isBackward: false,
|
|
25
|
+
hasFocus: true,
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
;[
|
|
29
|
+
'unordered-list-item',
|
|
30
|
+
'ordered-list-item',
|
|
31
|
+
'checkable-list-item',
|
|
32
|
+
].forEach(type => {
|
|
33
|
+
test(`adjustBlockDepth ${type}`, t => {
|
|
34
|
+
const editorState = createEditorState(
|
|
35
|
+
rawContentState(type, 0, 0),
|
|
36
|
+
selectionState()
|
|
37
|
+
)
|
|
38
|
+
const newEditorState = adjustBlockDepth(editorState, 1, 4)
|
|
39
|
+
t.not(newEditorState, editorState)
|
|
40
|
+
t.deepEqual(
|
|
41
|
+
convertToRaw(newEditorState.getCurrentContent()),
|
|
42
|
+
rawContentState(type, 0, 1)
|
|
43
|
+
)
|
|
44
|
+
})
|
|
45
|
+
})
|