draft-js
Version:
A React framework for building text editors.
117 lines (95 loc) • 4.43 kB
JavaScript
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*
* @emails oncall+draft_js
*/
'use strict';
var DraftEntitySegments = require("./DraftEntitySegments");
var getRangesForDraftEntity = require("./getRangesForDraftEntity");
var invariant = require("fbjs/lib/invariant");
/**
* Given a SelectionState and a removal direction, determine the entire range
* that should be removed from a ContentState. This is based on any entities
* within the target, with their `mutability` values taken into account.
*
* For instance, if we are attempting to remove part of an "immutable" entity
* range, the entire entity must be removed. The returned `SelectionState`
* will be adjusted accordingly.
*/
function getCharacterRemovalRange(entityMap, startBlock, endBlock, selectionState, direction) {
var start = selectionState.getStartOffset();
var end = selectionState.getEndOffset();
var startEntityKey = startBlock.getEntityAt(start);
var endEntityKey = endBlock.getEntityAt(end - 1);
if (!startEntityKey && !endEntityKey) {
return selectionState;
}
var newSelectionState = selectionState;
if (startEntityKey && startEntityKey === endEntityKey) {
newSelectionState = getEntityRemovalRange(entityMap, startBlock, newSelectionState, direction, startEntityKey, true, true);
} else if (startEntityKey && endEntityKey) {
var startSelectionState = getEntityRemovalRange(entityMap, startBlock, newSelectionState, direction, startEntityKey, false, true);
var endSelectionState = getEntityRemovalRange(entityMap, endBlock, newSelectionState, direction, endEntityKey, false, false);
newSelectionState = newSelectionState.merge({
anchorOffset: startSelectionState.getAnchorOffset(),
focusOffset: endSelectionState.getFocusOffset(),
isBackward: false
});
} else if (startEntityKey) {
var _startSelectionState = getEntityRemovalRange(entityMap, startBlock, newSelectionState, direction, startEntityKey, false, true);
newSelectionState = newSelectionState.merge({
anchorOffset: _startSelectionState.getStartOffset(),
isBackward: false
});
} else if (endEntityKey) {
var _endSelectionState = getEntityRemovalRange(entityMap, endBlock, newSelectionState, direction, endEntityKey, false, false);
newSelectionState = newSelectionState.merge({
focusOffset: _endSelectionState.getEndOffset(),
isBackward: false
});
}
return newSelectionState;
}
function getEntityRemovalRange(entityMap, block, selectionState, direction, entityKey, isEntireSelectionWithinEntity, isEntityAtStart) {
var start = selectionState.getStartOffset();
var end = selectionState.getEndOffset();
var entity = entityMap.__get(entityKey);
var mutability = entity.getMutability();
var sideToConsider = isEntityAtStart ? start : end; // `MUTABLE` entities can just have the specified range of text removed
// directly. No adjustments are needed.
if (mutability === 'MUTABLE') {
return selectionState;
} // Find the entity range that overlaps with our removal range.
var entityRanges = getRangesForDraftEntity(block, entityKey).filter(function (range) {
return sideToConsider <= range.end && sideToConsider >= range.start;
});
!(entityRanges.length == 1) ? process.env.NODE_ENV !== "production" ? invariant(false, 'There should only be one entity range within this removal range.') : invariant(false) : void 0;
var entityRange = entityRanges[0]; // For `IMMUTABLE` entity types, we will remove the entire entity range.
if (mutability === 'IMMUTABLE') {
return selectionState.merge({
anchorOffset: entityRange.start,
focusOffset: entityRange.end,
isBackward: false
});
} // For `SEGMENTED` entity types, determine the appropriate segment to
// remove.
if (!isEntireSelectionWithinEntity) {
if (isEntityAtStart) {
end = entityRange.end;
} else {
start = entityRange.start;
}
}
var removalRange = DraftEntitySegments.getRemovalRange(start, end, block.getText().slice(entityRange.start, entityRange.end), entityRange.start, direction);
return selectionState.merge({
anchorOffset: removalRange.start,
focusOffset: removalRange.end,
isBackward: false
});
}
module.exports = getCharacterRemovalRange;