All files / roosterjs-content-model-api/lib/publicApi/utils formatTextSegmentBeforeSelectionMarker.ts

100% Statements 15/15
100% Branches 9/9
100% Functions 3/3
100% Lines 15/15

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 731x                                 1x                     54x   54x 54x       54x   54x         51x       51x   51x 49x       49x   49x                       54x     54x    
import { getSelectedSegmentsAndParagraphs, mutateSegment } from 'roosterjs-content-model-dom';
import type {
    ContentModelSegmentFormat,
    ContentModelText,
    FormatContentModelContext,
    FormatContentModelOptions,
    IEditor,
    ShallowMutableContentModelDocument,
    ShallowMutableContentModelParagraph,
} from 'roosterjs-content-model-types';
 
/**
 * Invoke a callback to format the text segment before the selection marker using Content Model
 * @param editor The editor object
 * @param callback The callback to format the text segment.
 * @returns True if the segment before cursor is found and callback is called, otherwise false
 */
export function formatTextSegmentBeforeSelectionMarker(
    editor: IEditor,
    callback: (
        model: ShallowMutableContentModelDocument,
        previousSegment: ContentModelText,
        paragraph: ShallowMutableContentModelParagraph,
        markerFormat: ContentModelSegmentFormat,
        context: FormatContentModelContext
    ) => boolean,
    options?: FormatContentModelOptions
): boolean {
    let result = false;
 
    editor.formatContentModel((model, context) => {
        const selectedSegmentsAndParagraphs = getSelectedSegmentsAndParagraphs(
            model,
            false /*includeFormatHolder*/
        );
        let rewrite = false;
 
        if (
            selectedSegmentsAndParagraphs.length > 0 &&
            selectedSegmentsAndParagraphs[0][0].segmentType == 'SelectionMarker' &&
            selectedSegmentsAndParagraphs[0][1]
        ) {
            mutateSegment(
                selectedSegmentsAndParagraphs[0][1],
                selectedSegmentsAndParagraphs[0][0],
                (marker, paragraph, markerIndex) => {
                    const previousSegment = paragraph.segments[markerIndex - 1];
 
                    if (previousSegment && previousSegment.segmentType === 'Text') {
                        result = true;
 
                        // Preserve pending format if any when format text segment, so if there is pending format (e.g. from paste)
                        // and some auto action happens after paste, the pending format will still take effect
                        context.newPendingFormat = 'preserve';
 
                        rewrite = callback(
                            model,
                            previousSegment,
                            paragraph,
                            marker.format,
                            context
                        );
                    }
                }
            );
        }
 
        return rewrite;
    }, options);
 
    return result;
}