UNPKG

3.82 kBJavaScriptView Raw
1/**
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 * @format
8 *
9 * @emails oncall+draft_js
10 */
11'use strict';
12
13var CharacterMetadata = require("./CharacterMetadata");
14
15var findRangesImmutable = require("./findRangesImmutable");
16
17var invariant = require("fbjs/lib/invariant");
18
19function removeEntitiesAtEdges(contentState, selectionState) {
20 var blockMap = contentState.getBlockMap();
21 var entityMap = contentState.getEntityMap();
22 var updatedBlocks = {};
23 var startKey = selectionState.getStartKey();
24 var startOffset = selectionState.getStartOffset();
25 var startBlock = blockMap.get(startKey);
26 var updatedStart = removeForBlock(entityMap, startBlock, startOffset);
27
28 if (updatedStart !== startBlock) {
29 updatedBlocks[startKey] = updatedStart;
30 }
31
32 var endKey = selectionState.getEndKey();
33 var endOffset = selectionState.getEndOffset();
34 var endBlock = blockMap.get(endKey);
35
36 if (startKey === endKey) {
37 endBlock = updatedStart;
38 }
39
40 var updatedEnd = removeForBlock(entityMap, endBlock, endOffset);
41
42 if (updatedEnd !== endBlock) {
43 updatedBlocks[endKey] = updatedEnd;
44 }
45
46 if (!Object.keys(updatedBlocks).length) {
47 return contentState.set('selectionAfter', selectionState);
48 }
49
50 return contentState.merge({
51 blockMap: blockMap.merge(updatedBlocks),
52 selectionAfter: selectionState
53 });
54}
55/**
56 * Given a list of characters and an offset that is in the middle of an entity,
57 * returns the start and end of the entity that is overlapping the offset.
58 * Note: This method requires that the offset be in an entity range.
59 */
60
61
62function getRemovalRange(characters, entityKey, offset) {
63 var removalRange; // Iterates through a list looking for ranges of matching items
64 // based on the 'isEqual' callback.
65 // Then instead of returning the result, call the 'found' callback
66 // with each range.
67 // Then filters those ranges based on the 'filter' callback
68 //
69 // Here we use it to find ranges of characters with the same entity key.
70
71 findRangesImmutable(characters, // the list to iterate through
72 function (a, b) {
73 return a.getEntity() === b.getEntity();
74 }, // 'isEqual' callback
75 function (element) {
76 return element.getEntity() === entityKey;
77 }, // 'filter' callback
78 function (start, end) {
79 // 'found' callback
80 if (start <= offset && end >= offset) {
81 // this entity overlaps the offset index
82 removalRange = {
83 start: start,
84 end: end
85 };
86 }
87 });
88 !(typeof removalRange === 'object') ? process.env.NODE_ENV !== "production" ? invariant(false, 'Removal range must exist within character list.') : invariant(false) : void 0;
89 return removalRange;
90}
91
92function removeForBlock(entityMap, block, offset) {
93 var chars = block.getCharacterList();
94 var charBefore = offset > 0 ? chars.get(offset - 1) : undefined;
95 var charAfter = offset < chars.count() ? chars.get(offset) : undefined;
96 var entityBeforeCursor = charBefore ? charBefore.getEntity() : undefined;
97 var entityAfterCursor = charAfter ? charAfter.getEntity() : undefined;
98
99 if (entityAfterCursor && entityAfterCursor === entityBeforeCursor) {
100 var entity = entityMap.__get(entityAfterCursor);
101
102 if (entity.getMutability() !== 'MUTABLE') {
103 var _getRemovalRange = getRemovalRange(chars, entityAfterCursor, offset),
104 start = _getRemovalRange.start,
105 end = _getRemovalRange.end;
106
107 var current;
108
109 while (start < end) {
110 current = chars.get(start);
111 chars = chars.set(start, CharacterMetadata.applyEntity(current, null));
112 start++;
113 }
114
115 return block.set('characterList', chars);
116 }
117 }
118
119 return block;
120}
121
122module.exports = removeEntitiesAtEdges;
\No newline at end of file