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;
}
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.