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

100% Statements 33/33
100% Branches 14/14
100% Functions 4/4
100% Lines 32/32

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 941x 1x 1x 1x 1x 1x 1x                         1x                   1x         59x 59x 59x   59x       59x     59x 59x         59x 236x     59x   59x 2x     59x     7x   7x 1x         7x 7x 7x   52x       59x       59x   59x              
import { addBlock } from '../../modelApi/common/addBlock';
import { createFormatContainer } from '../../modelApi/creators/createFormatContainer';
import { createParagraph } from '../../modelApi/creators/createParagraph';
import { getDefaultStyle } from '../utils/getDefaultStyle';
import { parseFormat } from '../utils/parseFormat';
import { setParagraphNotImplicit } from '../../modelApi/block/setParagraphNotImplicit';
import { stackFormat } from '../utils/stackFormat';
import type {
    ContentModelFormatContainer,
    ContentModelFormatContainerFormat,
    ContentModelParagraph,
    ElementProcessor,
    MarginFormat,
    PaddingFormat,
} from 'roosterjs-content-model-types';
 
/**
 * @internal
 */
export const ContextStyles: (keyof (MarginFormat & PaddingFormat))[] = [
    'marginLeft',
    'marginRight',
    'paddingLeft',
    'paddingRight',
];
 
/**
 * @internal
 */
export const formatContainerProcessor: ElementProcessor<HTMLElement> = (
    group,
    element,
    context
) => {
    stackFormat(context, { segment: 'shallowCloneForBlock', paragraph: 'shallowClone' }, () => {
        parseFormat(element, context.formatParsers.block, context.blockFormat, context);
        parseFormat(element, context.formatParsers.segmentOnBlock, context.segmentFormat, context);
 
        const format: ContentModelFormatContainerFormat = {
            ...context.blockFormat,
        };
 
        parseFormat(element, context.formatParsers.container, format, context);
 
        const tagName =
            getDefaultStyle(element).display == 'block' ? element.tagName.toLowerCase() : 'div';
        const formatContainer = createFormatContainer(tagName, format);
 
        // It is possible to inherit margin left/right styles from parent DIV or other containers,
        // since we are going into a deeper level of format container now,
        // the container will render these styles so no need to keep them in context format
        ContextStyles.forEach(style => {
            delete context.blockFormat[style];
        });
 
        context.elementProcessors.child(formatContainer, element, context);
 
        if (element.style.fontSize && parseInt(element.style.fontSize) == 0) {
            formatContainer.zeroFontSize = true;
        }
 
        if (shouldFallbackToParagraph(formatContainer)) {
            // For DIV container that only has one paragraph child, container style can be merged into paragraph
            // and no need to have this container
            const paragraph = formatContainer.blocks[0] as ContentModelParagraph;
 
            if (formatContainer.zeroFontSize) {
                paragraph.segmentFormat = Object.assign({}, paragraph.segmentFormat, {
                    fontSize: '0',
                });
            }
 
            Object.assign(paragraph.format, formatContainer.format);
            setParagraphNotImplicit(paragraph);
            addBlock(group, paragraph);
        } else {
            addBlock(group, formatContainer);
        }
    });
 
    addBlock(group, createParagraph(true /*isImplicit*/, context.blockFormat));
};
 
function shouldFallbackToParagraph(formatContainer: ContentModelFormatContainer) {
    const firstChild = formatContainer.blocks[0];
 
    return (
        formatContainer.tagName == 'div' &&
        formatContainer.blocks.length == 1 &&
        firstChild.blockType == 'Paragraph' &&
        firstChild.isImplicit
    );
}