diff --git a/news/changelog-1.9.md b/news/changelog-1.9.md index f5953cd5088..36e401833de 100644 --- a/news/changelog-1.9.md +++ b/news/changelog-1.9.md @@ -6,6 +6,7 @@ All changes included in 1.9: - ([#13441](https://github.com/quarto-dev/quarto-cli/pull/13441)): Catch `undefined` exceptions in Pandoc failure to avoid spurious error message. - ([#13046](https://github.com/quarto-dev/quarto-cli/issues/13046)): Use new url for multiplex socket.io server as default for `format: revealjs` and `revealjs.multiplex: true`. - ([#13506](https://github.com/quarto-dev/quarto-cli/issues/13506)): Fix navbar active state detection when sidebar has no logo configured. Prevents empty logo links from interfering with navigation highlighting. +- ([#13633](https://github.com/quarto-dev/quarto-cli/issues/13633)): Fix detection and auto-installation of babel language packages from newer error format that doesn't explicitly mention `.ldf` filename. ## Dependencies @@ -37,6 +38,7 @@ All changes included in 1.9: ### `pdf` +- ([#10291](https://github.com/quarto-dev/quarto-cli/issues/10291)): Fix detection of babel hyphenation warnings with straight-quote format instead of backtick-quote format. - ([rstudio/tinytex-releases#49](https://github.com/rstudio/tinytex-releases/issues/49)): Fix detection of LuaTeX-ja missing file errors by matching both "File" and "file" in error messages. ## Projects diff --git a/src/command/render/latexmk/parse-error.ts b/src/command/render/latexmk/parse-error.ts index ee99c76330a..02a5b1b87dd 100644 --- a/src/command/render/latexmk/parse-error.ts +++ b/src/command/render/latexmk/parse-error.ts @@ -133,7 +133,7 @@ export function findMissingHyphenationFiles(logText: string) { const babelWarningRegex = /^Package babel Warning:/m; const hasWarning = logText.match(babelWarningRegex); if (hasWarning) { - const languageRegex = /^\(babel\).* language `(\S+)'.*$/m; + const languageRegex = /^\(babel\).* language [`'](\S+)[`'].*$/m; const languageMatch = logText.match(languageRegex); if (languageMatch) { return filterLang(languageMatch[1]); @@ -283,6 +283,12 @@ const packageMatchers = [ { regex: /.*! LaTeX Error: File [`']([^']+)' not found.*/g }, { regex: /.* [fF]ile ['`]?([^' ]+)'? not found.*/g }, { regex: /.*the language definition file ([^\s]*).*/g }, + { + regex: /.*! Package babel Error: Unknown option [`']([^'`]+)'[.].*/g, + filter: (match: string, _text: string) => { + return `${match}.ldf`; + }, + }, { regex: /.* \\(file ([^)]+)\\): cannot open .*/g }, { regex: /.*file [`']([^']+)' .*is missing.*/g }, { regex: /.*! CTeX fontset [`']([^']+)' is unavailable.*/g }, diff --git a/tests/docs/smoke-all/2024/08/30/10291/latex-hyphen-lang-es-no-install.qmd b/tests/docs/smoke-all/2024/08/30/10291/latex-hyphen-lang-es-no-install.qmd index 294d822314e..ef95719fb86 100644 --- a/tests/docs/smoke-all/2024/08/30/10291/latex-hyphen-lang-es-no-install.qmd +++ b/tests/docs/smoke-all/2024/08/30/10291/latex-hyphen-lang-es-no-install.qmd @@ -1,16 +1,22 @@ --- format: pdf -# new babel support in Pandoc 3.6.3 solves missing package when specific lang is used. lang: es latex-auto-install: false _quarto: + tests-on-ci: false tests: - pdf: default + pdf: + noErrors: true + printsMessage: + level: WARN + regex: "Possibly missing hyphenation" --- +** This test is to be run manually as we don't want to uninstall and reinstall package in CI** + ```{r} #| include: false - +#| messages: 'NA' # Remove the hyphen package for spanish so that the test is meaningful if (tinytex::check_installed("hyphen-spanish")) { message("Removing 'hyphen-spanish' package for the render") diff --git a/tests/docs/smoke-all/2024/08/30/10291/latex-hyphen-lang-es.qmd b/tests/docs/smoke-all/2024/08/30/10291/latex-hyphen-lang-es.qmd index 89bafffd58b..ce1b6b66703 100644 --- a/tests/docs/smoke-all/2024/08/30/10291/latex-hyphen-lang-es.qmd +++ b/tests/docs/smoke-all/2024/08/30/10291/latex-hyphen-lang-es.qmd @@ -6,14 +6,21 @@ _quarto: pdf: null --- +**Only remove package on CI** ```{r} +#| eval: !expr isFALSE(as.logical(Sys.getenv("CI", "false"))) #| include: false +#| messages: "NA" # Remove the hyphen package for spanish if (tinytex::check_installed("hyphen-spanish")) { message("Removing 'hyphen-spanish' package for the render") tinytex::tlmgr_remove("hyphen-spanish") } +if (tinytex::check_installed("babel-spanish")) { + message("Removing 'babel-spanish' package for the render") + tinytex::tlmgr_remove("babel-spanish") +} ``` # Hola ! diff --git a/tests/docs/smoke-all/2025/11/04/13633.qmd b/tests/docs/smoke-all/2025/11/04/13633.qmd new file mode 100644 index 00000000000..24685a399b8 --- /dev/null +++ b/tests/docs/smoke-all/2025/11/04/13633.qmd @@ -0,0 +1,22 @@ +--- +title: "Babel English Auto-Install (#13633)" +format: pdf +lang: en +_quarto: + tests: + pdf: null +--- + +```{r} +#| eval: !expr isFALSE(as.logical(Sys.getenv("CI", "false"))) +#| include: false +#| messages: "NA" + +# Remove babel-english package to test auto-installation +if (tinytex::check_installed("babel-english")) { + message("Removing 'babel-english' package for the render") + tinytex::tlmgr_remove("babel-english") +} +``` + +This document tests that Quarto correctly detects and auto-installs babel-english when rendering with `lang: en`. diff --git a/tests/unit/latexmk/parse-error.test.ts b/tests/unit/latexmk/parse-error.test.ts index 3a34e4f8f36..7ad40b854be 100644 --- a/tests/unit/latexmk/parse-error.test.ts +++ b/tests/unit/latexmk/parse-error.test.ts @@ -5,7 +5,7 @@ * */ -import { findMissingFontsAndPackages } from "../../../src/command/render/latexmk/parse-error.ts" +import { findMissingFontsAndPackages, findMissingHyphenationFiles } from "../../../src/command/render/latexmk/parse-error.ts" import { unitTest } from "../../test.ts"; import { assert } from "testing/asserts"; @@ -42,6 +42,10 @@ unitTest("Detect missing files with `findMissingFontsAndPackages`", async () => (babel) There is a locale ini file for this language. (babel) If it’s the main language, try adding \`provide=*' (babel) to the babel package options.`, "ngerman.ldf") + assertFound("! Package babel Error: Unknown option 'english'.", "english.ldf"); + assertFound(`! Package babel Error: Unknown option 'ngerman'. +(babel) Suggested actions: +(babel) * Make sure you haven't misspelled it`, "ngerman.ldf"); assertFound("!pdfTeX error: pdflatex (file 8r.enc): cannot open encoding file for reading", "8r.enc"); assertFound("! CTeX fontset `fandol' is unavailable in current mode", "fandol"); assertFound("! CTeX fontset 'fandol' is unavailable in current mode", "fandol"); @@ -70,4 +74,61 @@ unitTest("Detect missing files with `findMissingFontsAndPackages`", async () => assertFound("No file LGRcmr.fd. ! LaTeX Error: This NFSS system isn't set up properly.", "lgrcmr.fd"); },{ cwd: () => "unit/latexmk/" +}) + +unitTest("Detect missing hyphenation with babel warnings", async () => { + // Test backtick-quote format (old format) + const logWithBacktick = `Package babel Warning: No hyphenation patterns were preloaded for +(babel) the language \`Spanish' into the format. +(babel) Please, configure your TeX system to add them and +(babel) rebuild the format. Now I will use the patterns +(babel) preloaded for \\language=0 instead on input line 51.`; + assert( + findMissingHyphenationFiles(logWithBacktick) === "hyphen-spanish", + "Should detect hyphen-spanish from backtick-quote format" + ); + + // Test straight-quote format (new format - the bug we're fixing) + const logWithStraightQuotes = `Package babel Warning: No hyphenation patterns were preloaded for +(babel) the language 'Spanish' into the format. +(babel) Please, configure your TeX system to add them and +(babel) rebuild the format. Now I will use the patterns +(babel) preloaded for \\language=0 instead on input line 51.`; + assert( + findMissingHyphenationFiles(logWithStraightQuotes) === "hyphen-spanish", + "Should detect hyphen-spanish from straight-quote format" + ); + + // Test ngerman special case (should return hyphen-german, not hyphen-ngerman) + const logGerman = `Package babel Warning: No hyphenation patterns were preloaded for +(babel) the language 'ngerman' into the format.`; + assert( + findMissingHyphenationFiles(logGerman) === "hyphen-german", + "Should map ngerman to hyphen-german" + ); + + // Test Chinese - no hyphen package exists + const logChinese = `Package babel Warning: No hyphenation patterns were preloaded for +(babel) the language 'chinese' into the format.`; + assert( + findMissingHyphenationFiles(logChinese) === undefined, + "Should return undefined for Chinese (no hyphen package)" + ); + + // Test alternative Info pattern (issue #10291) + const logInfoChinese = `Package babel Info: Hyphen rules for 'chinese-hans' set to \\l@nil +(babel) (\\language10). Reported on input line 143.`; + assert( + findMissingHyphenationFiles(logInfoChinese) === undefined, + "Should return undefined for chinese-hans via Info pattern" + ); + + // Test no warning present + const logNoWarning = "Some other log text without babel warnings"; + assert( + findMissingHyphenationFiles(logNoWarning) === undefined, + "Should return undefined when no babel warning present" + ); +}, { + cwd: () => "unit/latexmk/" }) \ No newline at end of file