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

100% Statements 40/40
93.1% Branches 27/29
100% Functions 3/3
100% Lines 39/39

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 1001x 1x 1x 1x                                       1x 28x 4x   28x 21x   28x                   1x         22x 22x   22x 19x 19x 19x   19x 8x     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 {
    contentModelToDom,
    contentModelToText,
    createModelToDomContext,
    trimModelForSelection,
    isElementOfType,
    isNodeOfType,
    wrap,
} from 'roosterjs-content-model-dom';
import type {
    DOMSelection,
    IEditor,
    OnNodeCreated,
    TextAndHtmlContentForCopy,
} from 'roosterjs-content-model-types';
 
/**
 * @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');
        const context = createModelToDomContext();
        trimModelForSelection(pasteModel, selection);
 
        if (selection.type === 'range') {
            adjustSelectionForCopyCut(pasteModel);
        }
 
        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;
}