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     9695x 444x     9695x 111x 213x   9584x 269x     9695x   9695x                 1x       895x         895x   895x 895x 914x   914x 909x 909x         895x                 1x                 534x   534x       534x 364x     534x           9695x           9584x    
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';
}