All files / roosterjs-content-model-dom/lib/domToModel/processors childProcessor.ts

100% Statements 28/28
94.44% Branches 17/18
100% Functions 3/3
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 79 80 81 82 83 841x 1x 1x                         1x         2120x 2120x   2120x 3180x   3180x   3180x     2120x                   1x         3267x 1906x 1361x 1255x                         1x               5300x 19x   19x     5300x 18x 4x   18x      
import { addSelectionMarker } from '../utils/addSelectionMarker';
import { getRegularSelectionOffsets } from '../utils/getRegularSelectionOffsets';
import { isNodeOfType } from '../../domUtils/isNodeOfType';
import type {
    ContentModelBlockGroup,
    DomToModelContext,
    ElementProcessor,
} from 'roosterjs-content-model-types';
 
/**
 * Content Model Element Processor for child elements
 * @param group The parent block group
 * @param parent Parent DOM node to process
 * @param context DOM to Content Model context
 */
export const childProcessor: ElementProcessor<ParentNode> = (
    group: ContentModelBlockGroup,
    parent: ParentNode,
    context: DomToModelContext
) => {
    const [nodeStartOffset, nodeEndOffset] = getRegularSelectionOffsets(context, parent);
    let index = 0;
 
    for (let child = parent.firstChild; child; child = child.nextSibling) {
        handleRegularSelection(index, context, group, nodeStartOffset, nodeEndOffset, parent);
 
        processChildNode(group, child, context);
 
        index++;
    }
 
    handleRegularSelection(index, context, group, nodeStartOffset, nodeEndOffset, parent);
};
 
/**
 * Helper function for processing child node
 * @param group The parent block group
 * @param parent Parent DOM node to process
 * @param context DOM to Content Model context
 *
 */
export function processChildNode(
    group: ContentModelBlockGroup,
    child: Node,
    context: DomToModelContext
) {
    if (isNodeOfType(child, 'ELEMENT_NODE') && child.style.display != 'none') {
        context.elementProcessors.element(group, child, context);
    } else if (isNodeOfType(child, 'TEXT_NODE')) {
        context.elementProcessors['#text'](group, child, context);
    }
}
 
/**
 * Helper function to handle regular (range based) selection when process child node
 * @param index Index of current child node in its parent
 * @param context DOM to Content Model context
 * @param group The parent block group
 * @param nodeStartOffset Start offset of current regular selection
 * @param nodeEndOffset  End offset of current regular selection
 * @param container The container node of this selection
 */
export function handleRegularSelection(
    index: number,
    context: DomToModelContext,
    group: ContentModelBlockGroup,
    nodeStartOffset: number,
    nodeEndOffset: number,
    container?: Node
) {
    if (index == nodeStartOffset) {
        context.isInSelection = true;
 
        addSelectionMarker(group, context, container, index);
    }
 
    if (index == nodeEndOffset && context.selection?.type == 'range') {
        if (!context.selection.range.collapsed) {
            addSelectionMarker(group, context, container, index);
        }
        context.isInSelection = false;
    }
}