All files / roosterjs-content-model-api/lib/publicApi/table insertTable.ts

85.71% Statements 36/42
64.71% Branches 22/34
100% Functions 5/5
85% Lines 34/40

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 109 110 111 112 113 1141x 1x 1x 1x                                                       1x               11x   11x   11x   11x 11x   11x 11x   11x   11x 2x     11x 11x   11x   11x     11x 11x   11x         11x   11x 11x 11x 11x     11x                       25x   11x 23x 23x               23x 23x              
import { adjustTableIndentation } from '../../modelApi/common/adjustIndentation';
import { createTableStructure } from '../../modelApi/table/createTableStructure';
import { getSelectedContentForTable, insertTableContent } from '../../modelApi/table/tableContent';
import {
    createContentModelDocument,
    createSelectionMarker,
    applyTableFormat,
    deleteSelection,
    mergeModel,
    normalizeTable,
    setSelection,
    MIN_ALLOWED_TABLE_CELL_WIDTH,
} from 'roosterjs-content-model-dom';
import type {
    ContentModelTable,
    ContentModelTableFormat,
    IEditor,
    TableMetadataFormat,
    ContentModelTableCellFormat,
} from 'roosterjs-content-model-types';
 
/**
 * Insert table into editor at current selection
 * @param editor The editor instance
 * @param columns Number of columns in table, it also controls the default table cell width:
 * if columns <= 4, width = 120px; if columns <= 6, width = 100px; else width = 70px
 * @param rows Number of rows in table
 * @param tableMetadataFormat (Optional) The table format that are stored as metadata. If not passed, the default format will be applied: background color: #FFF; border color: #ABABAB
 * @param format (Optional) The table format used for style attributes
 * @param cellFormat (Optional) custom format for table cells, except for borders styles, for borders use tableMetadataFormat
 */
export function insertTable(
    editor: IEditor,
    columns: number,
    rows: number,
    tableMetadataFormat?: Partial<TableMetadataFormat>,
    format?: ContentModelTableFormat,
    customCellFormat?: ContentModelTableCellFormat
) {
    editor.focus();
 
    const blocks = getSelectedContentForTable(editor);
 
    editor.formatContentModel(
        (model, context) => {
            const deleteSelectionResult = deleteSelection(model, [], context);
            const insertPosition = deleteSelectionResult.insertPoint;
 
            Eif (insertPosition) {
                const doc = createContentModelDocument();
 
                const table = createTableStructure(doc, columns, rows, customCellFormat);
 
                if (format) {
                    table.format = { ...format };
                }
 
                normalizeTable(table, editor.getPendingFormat() || insertPosition.marker.format);
                initCellWidth(table);
 
                insertTableContent(table, blocks, columns, customCellFormat);
 
                adjustTableIndentation(insertPosition, table);
 
                // Assign default vertical align
                tableMetadataFormat = tableMetadataFormat || { verticalAlign: 'top' };
                applyTableFormat(table, tableMetadataFormat);
 
                mergeModel(model, doc, context, {
                    insertPosition,
                    mergeFormat: 'mergeAll',
                });
 
                const firstBlock = table.rows[0]?.cells[0]?.blocks[0];
 
                Eif (firstBlock?.blockType == 'Paragraph') {
                    const marker = createSelectionMarker(firstBlock.segments[0]?.format);
                    firstBlock.segments.unshift(marker);
                    setSelection(model, marker);
                }
 
                return true;
            } else {
                return false;
            }
        },
        {
            apiName: 'insertTable',
        }
    );
}
 
function initCellWidth(table: ContentModelTable) {
    const columns = Math.max(...table.rows.map(row => row.cells.length));
 
    for (let i = 0; i < columns; i++) {
        Eif (table.widths[i] === undefined) {
            table.widths[i] = getTableCellWidth(columns);
        } else if (table.widths[i] < MIN_ALLOWED_TABLE_CELL_WIDTH) {
            table.widths[i] = MIN_ALLOWED_TABLE_CELL_WIDTH;
        }
    }
}
 
function getTableCellWidth(columns: number): number {
    Eif (columns <= 4) {
        return 120;
    } else if (columns <= 6) {
        return 100;
    } else {
        return 70;
    }
}