fix(core): test the minimum font size when fitting text (#5283)

This commit is contained in:
Abdullah M. Nazif
2026-10-08 19:30:17 +00:00
committed by GitHub
parent f478fa6ff5
commit bb05bbe146
2 changed files with 43 additions and 1 deletions
@@ -70,4 +70,41 @@ describe("fitTextFontSize", () => {
expect(mockPrepare).toHaveBeenNthCalledWith(1, "test", "900 80px Outfit");
expect(mockPrepare).toHaveBeenNthCalledWith(2, "test", "900 70px Outfit");
});
it.each([
{ baseFontSize: 78, minFontSize: 43, step: 2 },
{ baseFontSize: 60, minFontSize: 31, step: 4 },
{ baseFontSize: 55, minFontSize: 42.5, step: 3.5 },
{ baseFontSize: 48, minFontSize: 42, step: 10 },
{ baseFontSize: 44, minFontSize: 43, step: 2 },
])("accepts text that only fits at the minimum with %j", (options) => {
mockLayout.mockImplementation(() => {
const font = mockPrepare.mock.lastCall?.[1] ?? "";
const size = Number(/ ([\d.]+)px /.exec(font)?.[1]);
return { height: 90, lineCount: size <= options.minFontSize ? 1 : 2 };
});
expect(fitTextFontSize("fits at the floor", options)).toEqual({
fontSize: options.minFontSize,
fits: true,
});
expect(mockPrepare).toHaveBeenLastCalledWith(
"fits at the floor",
`900 ${options.minFontSize}px Outfit`,
);
});
it("measures the minimum exactly once when it is already on a size step", () => {
mockLayout.mockReturnValue({ height: 180, lineCount: 2 });
expect(fitTextFontSize("too long", { baseFontSize: 48, minFontSize: 42, step: 2 })).toEqual({
fontSize: 42,
fits: false,
});
expect(mockPrepare.mock.calls.map((call) => call[1])).toEqual([
"900 48px Outfit",
"900 46px Outfit",
"900 44px Outfit",
"900 42px Outfit",
]);
});
});
+6 -1
View File
@@ -35,13 +35,18 @@ export function fitTextFontSize(text: string, options?: Partial<FitTextOptions>)
const opts = { ...DEFAULTS, ...options };
const lineHeightRatio = 1.2;
for (let size = opts.baseFontSize; size >= opts.minFontSize; size -= opts.step) {
for (
let size = opts.baseFontSize;
size >= opts.minFontSize;
size = Math.max(opts.minFontSize, size - opts.step)
) {
const font = `${opts.fontWeight} ${size}px ${opts.fontFamily}`;
const prepared = prepare(text, font);
const { lineCount } = layout(prepared, opts.maxWidth, size * lineHeightRatio);
if (lineCount <= 1) {
return { fontSize: size, fits: true };
}
if (size === opts.minFontSize) break;
}
return { fontSize: opts.minFontSize, fits: false };