|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- /**
- * 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
- * @flow
- * @emails oncall+draft_js
- */
- 'use strict';
-
- import type { BlockNodeRecord } from "./BlockNodeRecord";
- import type { DraftRemovalDirection } from "./DraftRemovalDirection";
- import type { EntityMap } from "./EntityMap";
- import type SelectionState from "./SelectionState";
-
- const DraftEntitySegments = require("./DraftEntitySegments");
-
- const getRangesForDraftEntity = require("./getRangesForDraftEntity");
-
- const 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: EntityMap, startBlock: BlockNodeRecord, endBlock: BlockNodeRecord, selectionState: SelectionState, direction: DraftRemovalDirection): SelectionState {
- const start = selectionState.getStartOffset();
- const end = selectionState.getEndOffset();
- const startEntityKey = startBlock.getEntityAt(start);
- const endEntityKey = endBlock.getEntityAt(end - 1);
-
- if (!startEntityKey && !endEntityKey) {
- return selectionState;
- }
-
- let newSelectionState = selectionState;
-
- if (startEntityKey && startEntityKey === endEntityKey) {
- newSelectionState = getEntityRemovalRange(entityMap, startBlock, newSelectionState, direction, startEntityKey, true, true);
- } else if (startEntityKey && endEntityKey) {
- const startSelectionState = getEntityRemovalRange(entityMap, startBlock, newSelectionState, direction, startEntityKey, false, true);
- const endSelectionState = getEntityRemovalRange(entityMap, endBlock, newSelectionState, direction, endEntityKey, false, false);
- newSelectionState = newSelectionState.merge({
- anchorOffset: startSelectionState.getAnchorOffset(),
- focusOffset: endSelectionState.getFocusOffset(),
- isBackward: false
- });
- } else if (startEntityKey) {
- const startSelectionState = getEntityRemovalRange(entityMap, startBlock, newSelectionState, direction, startEntityKey, false, true);
- newSelectionState = newSelectionState.merge({
- anchorOffset: startSelectionState.getStartOffset(),
- isBackward: false
- });
- } else if (endEntityKey) {
- const endSelectionState = getEntityRemovalRange(entityMap, endBlock, newSelectionState, direction, endEntityKey, false, false);
- newSelectionState = newSelectionState.merge({
- focusOffset: endSelectionState.getEndOffset(),
- isBackward: false
- });
- }
-
- return newSelectionState;
- }
-
- function getEntityRemovalRange(entityMap: EntityMap, block: BlockNodeRecord, selectionState: SelectionState, direction: DraftRemovalDirection, entityKey: string, isEntireSelectionWithinEntity: boolean, isEntityAtStart: boolean): SelectionState {
- let start = selectionState.getStartOffset();
- let end = selectionState.getEndOffset();
-
- const entity = entityMap.__get(entityKey);
-
- const mutability = entity.getMutability();
- const 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.
-
-
- const entityRanges = getRangesForDraftEntity(block, entityKey).filter(range => sideToConsider <= range.end && sideToConsider >= range.start);
- invariant(entityRanges.length == 1, 'There should only be one entity range within this removal range.');
- const 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;
- }
- }
-
- const 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;
|