@studysync/draft-js-modifiers 0.4.11 → 0.4.13

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.
Files changed (66) hide show
  1. package/es/insertBlockAfter.js +3 -1
  2. package/es/insertBlockBefore.js +3 -1
  3. package/flow/stub/__dev__.js +3 -0
  4. package/insertBlockAfter.js +3 -1
  5. package/insertBlockBefore.js +3 -1
  6. package/package.json +6 -3
  7. package/script/add-module.js +48 -0
  8. package/src/addBlock.js +98 -0
  9. package/src/adjustBlockDepth.js +21 -0
  10. package/src/atEndOfBlock.js +10 -0
  11. package/src/atStartOfBlock.js +7 -0
  12. package/src/changeBlockType.js +19 -0
  13. package/src/getAllEntities.js +14 -0
  14. package/src/getEntitiesForBlock.js +29 -0
  15. package/src/getEntitiesForSelection.js +20 -0
  16. package/src/getSelectedText.js +11 -0
  17. package/src/getSimilarAdjacentBlocks.js +53 -0
  18. package/src/index.js +42 -0
  19. package/src/insertAtomicBlock.js +23 -0
  20. package/src/insertBlockAfter.js +42 -0
  21. package/src/insertBlockBefore.js +42 -0
  22. package/src/insertEmptyBlock.js +12 -0
  23. package/src/insertEntity.js +56 -0
  24. package/src/insertNewBlock.js +61 -0
  25. package/src/insertText.js +23 -0
  26. package/src/mergeBlockData.js +13 -0
  27. package/src/mergeBlockDataByKey.js +12 -0
  28. package/src/mergeEntityData.js +13 -0
  29. package/src/modifyBlock.js +20 -0
  30. package/src/modifyBlockByKey.js +19 -0
  31. package/src/moveCaretAfterBlock.js +26 -0
  32. package/src/moveCaretToEnd.js +20 -0
  33. package/src/removeBlock.js +43 -0
  34. package/src/removeBlockStyle.js +17 -0
  35. package/src/removeEntity.js +38 -0
  36. package/src/removeInlineStyles.js +29 -0
  37. package/src/resetBlock.js +29 -0
  38. package/src/selectAll.js +15 -0
  39. package/src/selectBlockByKey.js +20 -0
  40. package/src/setBlockData.js +14 -0
  41. package/src/toggleBlockStyle.js +33 -0
  42. package/src/toggleBlockType.js +12 -0
  43. package/src/toggleEntity.js +11 -0
  44. package/src/toggleInlineStyle.js +11 -0
  45. package/src/trimEditorState.js +41 -0
  46. package/src/utils/getCurrentBlock.js +10 -0
  47. package/src/utils/numbers.js +3 -0
  48. package/test/adjustBlockDepth.js +45 -0
  49. package/test/export.js +14 -0
  50. package/test/fixtures/createEditorState.js +12 -0
  51. package/test/fixtures/omitBlockKeysFromRawContent.js +9 -0
  52. package/test/insertAtomicBlock.js +89 -0
  53. package/test/insertEmptyBlock.js +65 -0
  54. package/test/insertNewBlock.js +68 -0
  55. package/test/insertText.js +58 -0
  56. package/test/mergeBlockData.js +40 -0
  57. package/test/mergeBlockDataByKey.js +103 -0
  58. package/test/mergeEntityData.js +49 -0
  59. package/test/modifyBlock.js +52 -0
  60. package/test/modifyBlockByKey.js +91 -0
  61. package/test/removeBlockStyle.js +52 -0
  62. package/test/removeInlineStyles.js +68 -0
  63. package/test/resetBlock.js +83 -0
  64. package/test/toggleBlockType.js +4 -0
  65. package/test/toggleEntity.js +4 -0
  66. 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
@@ -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,3 @@
1
+ export const fallsWithin = (value, start, end) => start <= value && value <= end
2
+
3
+ export const rangesOverlap = (s1, e1, s2, e2) => fallsWithin(s2, s1, e1) || fallsWithin(s1, s2, e2)
@@ -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
+ })