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     9161x 384x     9161x 99x 195x   9062x 249x     9161x   9161x                 1x       834x         834x   834x 834x 853x   853x 848x 848x         834x                 1x                 488x   488x       488x 318x     488x           9161x           9062x    
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';
}