All files / roosterjs-content-model-api/lib/publicApi/segment changeFontSize.ts

100% Statements 36/36
92% Branches 23/25
100% Functions 4/4
100% Lines 34/34

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 831x 1x 1x                     1x 1x 1x               1x     48x   24x   24x     23x                       23x 22x   22x 22x   22x           22x 22x 22x 5x 17x 7x 7x 7x 10x 7x 52x 7x 7x       3x 10x 3x 3x       22x    
import { formatSegmentWithContentModel } from '../utils/formatSegmentWithContentModel';
import { parseValueWithUnit } from 'roosterjs-content-model-dom';
import { setFontSizeInternal } from './setFontSize';
import type {
    ContentModelSegmentFormat,
    IEditor,
    ShallowMutableContentModelParagraph,
} from 'roosterjs-content-model-types';
 
/**
 * Default font size sequence, in pt. Suggest editor UI use this sequence as your font size list,
 * So that when increase/decrease font size, the font size can match the sequence of your font size picker
 */
const FONT_SIZES = [8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72];
const MIN_FONT_SIZE = 1;
const MAX_FONT_SIZE = 1000;
 
/**
 * Increase or decrease font size in selection
 * @param editor The editor instance
 * @param change Whether increase or decrease font size
 * @param fontSizes A sorted font size array, in pt. Default value is FONT_SIZES
 */
export function changeFontSize(
    editor: IEditor,
    change: 'increase' | 'decrease',
    EfontSizes: number[] = FONT_SIZES
) {
    editor.focus();
 
    formatSegmentWithContentModel(
        editor,
        'changeFontSize',
        (format, _, __, paragraph) => changeFontSizeInternal(change, format, paragraph, fontSizes),
        undefined /* segmentHasStyleCallback*/,
        true /*includingFormatHandler*/
    );
}
 
function changeFontSizeInternal(
    change: 'increase' | 'decrease',
    format: ContentModelSegmentFormat,
    paragraph: ShallowMutableContentModelParagraph | null,
    fontSizes: number[]
) {
    if (format.fontSize) {
        const sizeInPt = parseValueWithUnit(format.fontSize, undefined /*element*/, 'pt');
 
        Eif (sizeInPt > 0) {
            const newSize = getNewFontSize(sizeInPt, change == 'increase' ? 1 : -1, fontSizes);
 
            setFontSizeInternal(newSize + 'pt', format, paragraph);
        }
    }
}
 
function getNewFontSize(pt: number, changeBase: 1 | -1, fontSizes: number[]): number {
    pt = changeBase == 1 ? Math.floor(pt) : Math.ceil(pt);
    const last = fontSizes[fontSizes.length - 1];
    if (pt <= fontSizes[0]) {
        pt = Math.max(pt + changeBase, MIN_FONT_SIZE);
    } else if (pt > last || (pt == last && changeBase == 1)) {
        pt = pt / 10;
        pt = changeBase == 1 ? Math.floor(pt) : Math.ceil(pt);
        pt = Math.min(Math.max((pt + changeBase) * 10, last), MAX_FONT_SIZE);
    } else if (changeBase == 1) {
        for (let i = 0; i < fontSizes.length; i++) {
            if (pt < fontSizes[i]) {
                pt = fontSizes[i];
                break;
            }
        }
    } else {
        for (let i = fontSizes.length - 1; i >= 0; i--) {
            if (pt > fontSizes[i]) {
                pt = fontSizes[i];
                break;
            }
        }
    }
    return pt;
}