All files / roosterjs-editor-adapter/lib/editor/utils buildRangeEx.ts

10% Statements 2/20
0% Branches 0/43
0% Functions 0/5
10% Lines 2/20

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 1101x                         1x                                                                                                                                                                                                
import { createRange, safeInstanceOf } from 'roosterjs-editor-dom';
import { SelectionRangeTypes } from 'roosterjs-editor-types';
import type {
    NodePosition,
    PositionType,
    SelectionPath,
    SelectionRangeEx,
    TableSelection,
} from 'roosterjs-editor-types';
 
/**
 * @internal
 */
export function buildRangeEx(
    root: HTMLElement,
    arg1: Range | SelectionRangeEx | NodePosition | Node | SelectionPath | null,
    arg2?: NodePosition | number | PositionType | TableSelection | null,
    arg3?: Node,
    arg4?: number | PositionType
): SelectionRangeEx {
    let rangeEx: SelectionRangeEx | null = null;
 
    if (isSelectionRangeEx(arg1)) {
        rangeEx = arg1;
    } else if (safeInstanceOf(arg1, 'HTMLTableElement') && isTableSelectionOrNull(arg2)) {
        rangeEx = {
            type: SelectionRangeTypes.TableSelection,
            ranges: [],
            areAllCollapsed: false,
            table: arg1,
            coordinates: arg2 ?? undefined,
        };
    } else if (safeInstanceOf(arg1, 'HTMLImageElement') && typeof arg2 == 'undefined') {
        rangeEx = {
            type: SelectionRangeTypes.ImageSelection,
            ranges: [],
            areAllCollapsed: false,
            image: arg1,
        };
    } else {
        const range = !arg1
            ? null
            : safeInstanceOf(arg1, 'Range')
            ? arg1
            : isSelectionPath(arg1)
            ? createRange(root, arg1.start, arg1.end)
            : isNodePosition(arg1) || safeInstanceOf(arg1, 'Node')
            ? createRange(
                  <Node>arg1,
                  <number | PositionType>arg2,
                  <Node>arg3,
                  <number | PositionType>arg4
              )
            : null;
 
        rangeEx = range
            ? {
                  type: SelectionRangeTypes.Normal,
                  ranges: [range],
                  areAllCollapsed: range.collapsed,
              }
            : {
                  type: SelectionRangeTypes.Normal,
                  ranges: [],
                  areAllCollapsed: true,
              };
    }
 
    return rangeEx;
}
 
function isSelectionRangeEx(obj: any): obj is SelectionRangeEx {
    const rangeEx = obj as SelectionRangeEx;
    return (
        rangeEx &&
        typeof rangeEx == 'object' &&
        typeof rangeEx.type == 'number' &&
        Array.isArray(rangeEx.ranges)
    );
}
 
function isTableSelectionOrNull(obj: any): obj is TableSelection | null {
    const selection = obj as TableSelection | null;
 
    return (
        selection === null ||
        (selection &&
            typeof selection == 'object' &&
            typeof selection.firstCell == 'object' &&
            typeof selection.lastCell == 'object')
    );
}
 
function isSelectionPath(obj: any): obj is SelectionPath {
    const path = obj as SelectionPath;
 
    return path && typeof path == 'object' && Array.isArray(path.start) && Array.isArray(path.end);
}
 
function isNodePosition(obj: any): obj is NodePosition {
    const pos = obj as NodePosition;
 
    return (
        pos &&
        typeof pos == 'object' &&
        typeof pos.node == 'object' &&
        typeof pos.offset == 'number'
    );
}