All files / roosterjs-content-model-core/lib/command/cutCopy getContentForCopy.ts

97.92% Statements 47/48
89.19% Branches 33/37
100% Functions 4/4
97.87% Lines 46/47

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 1101x 1x 1x 1x 1x             1x                           1x 28x 4x   28x 21x   28x                   1x         22x 22x 22x 19x 19x   19x 6x 2x 2x   2x       13x 8x   19x   19x 19x 19x   19x 19x 19x 17x             17x           5x       17x   17x 6x   6x   6x 6x 11x 4x 4x   7x     17x    
import { adjustImageSelectionOnSafari } from './adjustImageSelectionOnSafari';
import { adjustSelectionForCopyCut } from './adjustSelectionForCopyCut';
import { onCreateCopyEntityNode } from '../../override/pasteCopyBlockEntityParser';
import { preprocessTable } from './preprocessTable';
import { pruneUnselectedModel } from './pruneUnselectedModel';
import type {
    DOMSelection,
    IEditor,
    OnNodeCreated,
    TextAndHtmlContentForCopy,
} from 'roosterjs-content-model-types';
import {
    contentModelToDom,
    contentModelToText,
    createModelToDomContext,
    isElementOfType,
    isNodeOfType,
    iterateSelections,
    wrap,
} from 'roosterjs-content-model-dom';
 
/**
 * @internal
 * Exported only for unit testing
 */
export const onNodeCreated: OnNodeCreated = (modelElement, node): void => {
    if (isNodeOfType(node, 'ELEMENT_NODE') && isElementOfType(node, 'table')) {
        wrap(node.ownerDocument, node, 'div');
    }
    if (isNodeOfType(node, 'ELEMENT_NODE') && !node.isContentEditable) {
        node.removeAttribute('contenteditable');
    }
    onCreateCopyEntityNode(modelElement, node);
};
 
/**
 * Get the content for the copy event
 * @param editor The editor object
 * @param isCut if the event cut the content.
 * @param event the clipboard event that triggered the copy/cut
 * @returns
 */
export function getContentForCopy(
    editor: IEditor,
    isCut: boolean,
    event: ClipboardEvent
): TextAndHtmlContentForCopy | null {
    const selection = editor.getDOMSelection();
    adjustImageSelectionOnSafari(editor, selection);
    if (selection && (selection.type != 'range' || !selection.range.collapsed)) {
        const pasteModel = editor.getContentModelCopy('disconnected');
        pruneUnselectedModel(pasteModel);
 
        if (selection.type === 'table') {
            iterateSelections(pasteModel, (_, tableContext) => {
                Eif (tableContext?.table) {
                    preprocessTable(tableContext.table);
 
                    return true;
                }
                return false;
            });
        } else if (selection.type === 'range') {
            adjustSelectionForCopyCut(pasteModel);
        }
        const context = createModelToDomContext();
 
        context.onNodeCreated = onNodeCreated;
        const doc = editor.getDocument();
        const tempDiv = doc.createElement('div');
 
        const selectionForCopy = contentModelToDom(doc, tempDiv, pasteModel, context);
        const newRange = selectionForCopy ? domSelectionToRange(doc, selectionForCopy) : null;
        if (newRange) {
            const { clonedRoot } = editor.triggerEvent('beforeCutCopy', {
                clonedRoot: tempDiv,
                range: newRange,
                rawEvent: event,
                isCut,
            });
 
            return {
                htmlContent: clonedRoot,
                textContent: contentModelToText(pasteModel),
            };
        }
    }
    return null;
}
 
function domSelectionToRange(doc: Document, selection: DOMSelection): Range | null {
    let newRange: Range | null = null;
 
    if (selection.type === 'table') {
        const table = selection.table;
        const elementToSelect =
            table.parentElement?.childElementCount == 1 ? table.parentElement : table;
 
        newRange = doc.createRange();
        newRange.selectNode(elementToSelect);
    } else if (selection.type === 'image') {
        newRange = doc.createRange();
        newRange.selectNode(selection.image);
    } else {
        newRange = selection.range;
    }
 
    return newRange;
}