From f1e71be3bbd66cf81a7292ad68ad13e7d2694750 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Wed, 26 Nov 2025 15:24:26 +0100 Subject: [PATCH] Fix font package detection for fonts with spaces in names Fonts with spaces (e.g., "Noto Emoji", "DejaVu Sans") were failing auto-installation because fontSearchTerm() generated search patterns that didn't match font files. Font files use concatenated names without spaces (NotoEmoji-Regular.ttf, DejaVuSans-Bold.ttf). Replace spaces with \s* regex pattern to match files with or without spaces. Closes #13726 Fix font package detection for fonts with spaces in names Resolves an issue where fonts packages containing spaces in their names (e.g., "Noto Sans") were not properly detected in Quarto projects. Updated font path handling to correctly quote and process font names with whitespace characters. --- news/changelog-1.8.md | 1 + src/command/render/latexmk/parse-error.ts | 3 ++- tests/unit/latexmk/parse-error.test.ts | 5 ++++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/news/changelog-1.8.md b/news/changelog-1.8.md index 8520e1526f..62fba2d199 100644 --- a/news/changelog-1.8.md +++ b/news/changelog-1.8.md @@ -3,6 +3,7 @@ ## In this release - ([#13694](https://github.com/quarto-dev/quarto-cli/issues/13694)): Fix `notebook-view.url` being ignored - external notebook links now properly use specified URLs instead of local preview files. +- ([#13732](https://github.com/quarto-dev/quarto-cli/issues/13732)): Fix automatic font package installation for fonts with spaces in their names (e.g., "Noto Emoji", "DejaVu Sans"). Font file search patterns now match both with and without spaces. ## In previous releases diff --git a/src/command/render/latexmk/parse-error.ts b/src/command/render/latexmk/parse-error.ts index 77b9772f55..fee3d9135c 100644 --- a/src/command/render/latexmk/parse-error.ts +++ b/src/command/render/latexmk/parse-error.ts @@ -285,7 +285,8 @@ const packageMatchers = [ ]; function fontSearchTerm(font: string): string { - return `${font}(-(Bold|Italic|Regular).*)?[.](tfm|afm|mf|otf|ttf)`; + const fontPattern = font.replace(/\s+/g, '\\s*'); + return `${fontPattern}(-(Bold|Italic|Regular).*)?[.](tfm|afm|mf|otf|ttf)`; } function findMissingPackages(logFileText: string): string[] { diff --git a/tests/unit/latexmk/parse-error.test.ts b/tests/unit/latexmk/parse-error.test.ts index aa57753165..ebf7666dc9 100644 --- a/tests/unit/latexmk/parse-error.test.ts +++ b/tests/unit/latexmk/parse-error.test.ts @@ -10,7 +10,8 @@ import { unitTest } from "../../test.ts"; import { assert } from "testing/asserts"; function fontSearchTerm(font: string): string { - return `${font}(-(Bold|Italic|Regular).*)?[.](tfm|afm|mf|otf|ttf)`; + const fontPattern = font.replace(/\s+/g, '\\s*'); + return `${fontPattern}(-(Bold|Italic|Regular).*)?[.](tfm|afm|mf|otf|ttf)`; } function assertFound(logText: string, expected: string, file?: string) { @@ -32,6 +33,8 @@ unitTest("Detect missing files with `findMissingFontsAndPackages`", async () => assertFound('!pdfTeX error: /usr/local/bin/pdflatex (file tcrm0700): Font tcrm0700 at 600 not found', fontSearchTerm("tcrm0700")) assertFound('(fontspec) The font "LibertinusSerif-Regular" cannot be', fontSearchTerm("LibertinusSerif-Regular")); assertFound('! Font \\JY3/mc/m/n/10=file:HaranoAjiMincho-Regular.otf:-kern;jfm=ujis at 9.24713pt not loadable: metric data not found or bad.', "HaranoAjiMincho-Regular.otf"); + assertFound('! The font "Noto Emoji" cannot be found.', fontSearchTerm("Noto Emoji")); + assertFound('! Package fontspec Error: The font "DejaVu Sans" cannot be found.', fontSearchTerm("DejaVu Sans")); assertFound("! LaTeX Error: File `framed.sty' not found.", "framed.sty"); assertFound("/usr/local/bin/mktexpk: line 123: mf: command not found", "mf"); assertFound("or the language definition file ngerman.ldf was not found", "ngerman.ldf");