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   3x   5x 145x 139x 19x 146x                 1x   180x     91x 91x   91x   91x               146x 146x 193x   139x 139x   139x 160x   3x 3x 3x     4x 4x     1x 1x     146x 146x     6x 6x       139x 131x       139x     3x 3x   1x 1x     19x 19x 18x 24x       19x     31x 31x          
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;
            }
        });
    }
}