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     9679x 444x     9679x 109x 211x   9570x 269x     9679x   9679x                 1x       893x         893x   893x 893x 912x   912x 907x 907x         893x                 1x                 533x   533x       533x 363x     533x           9679x           9570x    
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';
}