All files / roosterjs-content-model-api/lib/modelApi/table canMergeCells.ts

100% Statements 26/26
90% Branches 45/50
100% Functions 9/9
100% Lines 24/24

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          1x               43x   87x     43x     87x     43x   120x       119x 43x   120x       119x   43x               70x   70x 46x 5x   41x       70x               70x   70x 46x 5x   41x       70x    
import type { ReadonlyContentModelTableRow } from 'roosterjs-content-model-types';
 
/**
 * @internal
 */
export function canMergeCells(
    rows: ReadonlyContentModelTableRow[],
    firstRow: number,
    firstCol: number,
    lastRow: number,
    lastCol: number
): boolean {
    const noSpanAbove =
        firstCol == lastCol ||
        rows[firstRow].cells.every(
            (cell, colIndex) => colIndex < firstCol || colIndex > lastCol || !cell.spanAbove
        );
    const noSpanLeft =
        firstRow == lastRow ||
        rows.every(
            (row, rowIndex) =>
                rowIndex < firstRow || rowIndex > lastRow || !row.cells[firstCol].spanLeft
        );
 
    const noDifferentBelowSpan = rows[lastRow].cells
        .map((_, colIndex) =>
            colIndex >= firstCol && colIndex <= lastCol
                ? getBelowSpanCount(rows, lastRow, colIndex)
                : -1
        )
        .every((x, _, a) => x < 0 || x == a[firstCol]);
    const noDifferentRightSpan = rows
        .map((_, rowIndex) =>
            rowIndex >= firstRow && rowIndex <= lastRow
                ? getRightSpanCount(rows, rowIndex, lastCol)
                : -1
        )
        .every((x, _, a) => x < 0 || x == a[firstRow]);
 
    return noSpanAbove && noSpanLeft && noDifferentBelowSpan && noDifferentRightSpan;
}
 
function getBelowSpanCount(
    rows: ReadonlyContentModelTableRow[],
    rowIndex: number,
    colIndex: number
) {
    let spanCount = 0;
 
    for (let row = rowIndex + 1; row < rows.length; row++) {
        if (rows[row]?.cells[colIndex]?.spanAbove) {
            spanCount++;
        } else {
            break;
        }
    }
 
    return spanCount;
}
 
function getRightSpanCount(
    rows: ReadonlyContentModelTableRow[],
    rowIndex: number,
    colIndex: number
) {
    let spanCount = 0;
 
    for (let col = colIndex + 1; col < rows[rowIndex]?.cells.length; col++) {
        if (rows[rowIndex]?.cells[col]?.spanLeft) {
            spanCount++;
        } else {
            break;
        }
    }
 
    return spanCount;
}