All files / roosterjs-content-model-api/lib/publicApi/block setHeadingLevel.ts

100% Statements 16/16
94.44% Branches 17/18
100% Functions 4/4
100% Lines 16/16

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 591x         1x                           1x 9x   9x   5x       5x 3x                     3x 4x 4x   2x 1x               2x 2x   2x    
import { formatParagraphWithContentModel } from '../utils/formatParagraphWithContentModel';
import type { ContentModelParagraphDecorator, IEditor } from 'roosterjs-content-model-types';
 
type HeadingLevelTags = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
 
const HeaderFontSizes: Record<HeadingLevelTags, string> = {
    h1: '2em',
    h2: '1.5em',
    h3: '1.17em',
    h4: '1em',
    h5: '0.83em',
    h6: '0.67em',
};
 
/**
 * Set heading level of selected paragraphs
 * @param editor The editor to set heading level to
 * @param headingLevel Level of heading, from 1 to 6. Set to 0 means set it back to a regular paragraph
 */
export function setHeadingLevel(editor: IEditor, headingLevel: 0 | 1 | 2 | 3 | 4 | 5 | 6) {
    editor.focus();
 
    formatParagraphWithContentModel(editor, 'setHeadingLevel', para => {
        const tagName =
            headingLevel > 0
                ? (('h' + headingLevel) as HeadingLevelTags | null)
                : getExistingHeadingTag(para.decorator);
 
        if (headingLevel > 0) {
            para.decorator = {
                tagName: tagName!,
                format: tagName
                    ? {
                          fontWeight: 'bold',
                          fontSize: HeaderFontSizes[tagName],
                      }
                    : {},
            };
 
            // Remove existing formats since tags have default font size and weight
            para.segments.forEach(segment => {
                delete segment.format.fontSize;
                delete segment.format.fontWeight;
            });
        } else if (tagName) {
            delete para.decorator;
        }
    });
}
 
function getExistingHeadingTag(
    decorator?: ContentModelParagraphDecorator
): HeadingLevelTags | null {
    const tag = decorator?.tagName || '';
    const level = parseInt(tag.substring(1));
 
    return level >= 1 && level <= 6 ? (tag as HeadingLevelTags) : null;
}