All files / roosterjs-content-model-dom/lib/modelApi/common mutate.ts

100% Statements 32/32
95% Branches 19/20
100% Functions 8/8
100% Lines 28/28

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                                  1x     12030x 578x     12030x 157x 306x   11873x 316x     12030x   12030x                 1x       985x         985x   985x 985x 1004x   1004x 999x 999x         985x                 1x                 589x   589x       589x 397x     589x           12030x           11873x    
import type {
    MutableType,
    ReadonlyContentModelBlock,
    ReadonlyContentModelBlockGroup,
    ReadonlyContentModelListItem,
    ReadonlyContentModelParagraph,
    ReadonlyContentModelSegment,
    ReadonlyContentModelTable,
    ShallowMutableContentModelParagraph,
    ShallowMutableContentModelSegment,
} from 'roosterjs-content-model-types';
 
/**
 * Convert a readonly block to mutable block, clear cached element if exist
 * @param block The block to convert from
 * @returns The same block object of its related mutable type
 */
export function mutateBlock<T extends ReadonlyContentModelBlockGroup | ReadonlyContentModelBlock>(
    block: T
): MutableType<T> {
    if (block.cachedElement) {
        delete block.cachedElement;
    }
 
    if (isTable(block)) {
        block.rows.forEach(row => {
            delete row.cachedElement;
        });
    } else if (isListItem(block)) {
        block.levels.forEach(level => delete level.cachedElement);
    }
 
    const result = (block as unknown) as MutableType<T>;
 
    return result;
}
 
/**
 * Convert segments of a readonly paragraph to be mutable.
 * Segments that are not belong to the given paragraph will be skipped
 * @param paragraph The readonly paragraph to convert from
 * @param segments The segments to convert from
 */
export function mutateSegments(
    paragraph: ReadonlyContentModelParagraph,
    segments: ReadonlyContentModelSegment[]
): [ShallowMutableContentModelParagraph, ShallowMutableContentModelSegment[], number[]] {
    const mutablePara = mutateBlock(paragraph);
    const result: [
        ShallowMutableContentModelParagraph,
        ShallowMutableContentModelSegment[],
        number[]
    ] = [mutablePara, [], []];
 
    Eif (segments) {
        segments.forEach(segment => {
            const index = paragraph.segments.indexOf(segment);
 
            if (index >= 0) {
                result[1].push(mutablePara.segments[index]);
                result[2].push(index);
            }
        });
    }
 
    return result;
}
 
/**
 * Convert a readonly segment to be mutable, together with its owner paragraph
 * If the segment does not belong to the given paragraph, return null for the segment
 * @param paragraph The readonly paragraph to convert from
 * @param segment The segment to convert from
 */
export function mutateSegment<T extends ReadonlyContentModelSegment>(
    paragraph: ReadonlyContentModelParagraph,
    segment: T,
    callback?: (
        segment: MutableType<T>,
        paragraph: ShallowMutableContentModelParagraph,
        index: number
    ) => void
): [ShallowMutableContentModelParagraph, MutableType<T> | null, number] {
    const [mutablePara, mutableSegments, indexes] = mutateSegments(paragraph, [segment]);
    const mutableSegment =
        (mutableSegments[0] as ReadonlyContentModelSegment) == segment
            ? (mutableSegments[0] as MutableType<T>)
            : null;
 
    if (callback && mutableSegment) {
        callback(mutableSegments[0] as MutableType<T>, mutablePara, indexes[0]);
    }
 
    return [mutablePara, mutableSegment, indexes[0] ?? -1];
}
 
function isTable(
    obj: ReadonlyContentModelBlockGroup | ReadonlyContentModelBlock
): obj is ReadonlyContentModelTable {
    return (obj as ReadonlyContentModelTable).blockType == 'Table';
}
 
function isListItem(
    obj: ReadonlyContentModelBlockGroup | ReadonlyContentModelBlock
): obj is ReadonlyContentModelListItem {
    return (obj as ReadonlyContentModelListItem).blockGroupType == 'ListItem';
}