All files / roosterjs-content-model-dom/lib/modelToText contentModelToText.ts

95.92% Statements 47/49
73.33% Branches 22/30
86.67% Functions 13/15
95.92% Lines 47/49

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            1x 1x 2x   1x   1x 144x 128x 14x 139x                 1x   168x     85x 85x   85x   85x               139x 139x 176x   128x 128x   128x 154x   3x 3x 3x     2x 2x     1x 1x     145x 145x     2x 2x       128x 126x       128x     3x 3x   1x 1x     14x 14x 16x 24x       14x     30x 30x          
import type {
    ModelToTextCallbacks,
    ReadonlyContentModelBlockGroup,
    ReadonlyContentModelDocument,
} from 'roosterjs-content-model-types';
 
const TextForHR = '________________________________________';
const defaultCallbacks: Required<ModelToTextCallbacks> = {
    onDivider: divider => (divider.tagName == 'hr' ? TextForHR : ''),
    onEntityBlock: () => '',
    onEntitySegment: entity => entity.wrapper.textContent ?? '',
    onGeneralSegment: segment => segment.element.textContent ?? '',
    onImage: () => ' ',
    onText: text => text.text,
    onParagraph: () => true,
    onTable: () => true,
    onBlockGroup: () => true,
};
 
/**
 * Convert Content Model to plain text
 * @param model The source Content Model
 * @param [separator='\r\n'] The separator string used for connect lines
 * @param callbacks  Callbacks to customize the behavior of contentModelToText function
 */
export function contentModelToText(
    model: ReadonlyContentModelDocument,
    separator: string = '\r\n',
    callbacks?: ModelToTextCallbacks
): string {
    const textArray: string[] = [];
    const fullCallbacks = Object.assign({}, defaultCallbacks, callbacks);
 
    contentModelToTextArray(model, textArray, fullCallbacks);
 
    return textArray.join(separator);
}
 
function contentModelToTextArray(
    group: ReadonlyContentModelBlockGroup,
    textArray: string[],
    callbacks: Required<ModelToTextCallbacks>
) {
    Eif (callbacks.onBlockGroup(group)) {
        group.blocks.forEach(block => {
            switch (block.blockType) {
                case 'Paragraph':
                    Eif (callbacks.onParagraph(block)) {
                        let text = '';
 
                        block.segments.forEach(segment => {
                            switch (segment.segmentType) {
                                case 'Br':
                                    textArray.push(text);
                                    text = '';
                                    break;
 
                                case 'Entity':
                                    text += callbacks.onEntitySegment(segment);
                                    break;
 
                                case 'General':
                                    text += callbacks.onGeneralSegment(segment);
                                    break;
 
                                case 'Text':
                                    text += callbacks.onText(segment);
                                    break;
 
                                case 'Image':
                                    text += callbacks.onImage(segment);
                                    break;
                            }
                        });
 
                        if (text) {
                            textArray.push(text);
                        }
                    }
 
                    break;
 
                case 'Divider':
                    textArray.push(callbacks.onDivider(block));
                    break;
                case 'Entity':
                    textArray.push(callbacks.onEntityBlock(block));
                    break;
 
                case 'Table':
                    Eif (callbacks.onTable(block)) {
                        block.rows.forEach(row =>
                            row.cells.forEach(cell => {
                                contentModelToTextArray(cell, textArray, callbacks);
                            })
                        );
                    }
                    break;
 
                case 'BlockGroup':
                    contentModelToTextArray(block, textArray, callbacks);
                    break;
            }
        });
    }
}