diff --git a/news/changelog-1.10.md b/news/changelog-1.10.md index fb34c2e35bc..e9f6a320ad3 100644 --- a/news/changelog-1.10.md +++ b/news/changelog-1.10.md @@ -22,6 +22,7 @@ All changes included in 1.10: - ([#14261](https://github.com/quarto-dev/quarto-cli/issues/14261)): Fix theorem/example block titles containing inline code producing invalid Typst markup when syntax highlighting is applied. - ([#14460](https://github.com/quarto-dev/quarto-cli/issues/14460)): Fix CSS `border` and `border-color` declarations losing tokens that precede an `rgb()`/`rgba()` color (e.g. `border: 0px solid rgb(255, 0, 0)` rendering as a 2.25pt border instead of being suppressed). Also fixes: `var(--brand-NAME)` references crashing the Typst CSS translator when `NAME` contained digits (e.g. `--brand-red-50`); a crash when an `rgba()` alpha is unparseable; the `dvmin` length unit being silently rejected (a stray space in the unit table); CSS keywords like `BOLD` not matching as `bold` (CSS keywords are case-insensitive); invalid hex colors like `#fffff` being silently accepted as 2-component colors. +- ([#14511](https://github.com/quarto-dev/quarto-cli/issues/14511)): Fix brand fonts downloaded for a Typst book project not being passed to `typst compile`, causing `unknown font family` warnings and fallback to Libertinus Serif. ### `revealjs` diff --git a/src/command/render/output-typst.ts b/src/command/render/output-typst.ts index 798c7aa7fd8..762bde81eef 100644 --- a/src/command/render/output-typst.ts +++ b/src/command/render/output-typst.ts @@ -42,7 +42,7 @@ import { Format } from "../../config/types.ts"; import { writeFileToStdout } from "../../core/console.ts"; import { dirAndStem, expandPath } from "../../core/path.ts"; import { kStdOut, replacePandocOutputArg } from "./flags.ts"; -import { OutputRecipe, RenderOptions } from "./types.ts"; +import { OutputRecipe, PandocOptions, RenderOptions } from "./types.ts"; import { normalizeOutputPath } from "./output-shared.ts"; import { typstCompile, @@ -228,7 +228,14 @@ export function typstPdfOutputRecipe( // when pandoc is done, we need to run the pdf generator and then copy the // output to the user's requested destination - const complete = async () => { + // + // Read format state from `pandocOptions.format` rather than the captured + // `format` parameter: for book projects, `withBookTitleMetadata` deep-clones + // the recipe's format between recipe construction and `renderPandoc`, so the + // captured reference becomes stale and never observes mutations applied by + // `resolveExtras` (e.g. brand font paths). See #14511. + const complete = async (pandocOptions: PandocOptions) => { + const liveFormat = pandocOptions.format; // input file is pandoc's output const typstInput = join(inputDir, output); @@ -237,12 +244,13 @@ export function typstPdfOutputRecipe( const pdfOutput = join(inputDir, inputStem + ".pdf"); const typstOptions: TypstCompileOptions = { quiet: options.flags?.quiet, - fontPaths: (asArray(format.metadata?.[kFontPaths]) as string[]).map( + fontPaths: (asArray(liveFormat.metadata?.[kFontPaths]) as string[]).map( (p) => isAbsolute(p) ? p : resolve(inputDir, p), ), pdfStandard: normalizePdfStandardForTypst( asArray( - format.render?.[kPdfStandard] ?? format.metadata?.[kPdfStandard] ?? + liveFormat.render?.[kPdfStandard] ?? + liveFormat.metadata?.[kPdfStandard] ?? pdfStandardEnv(), ), ), @@ -274,7 +282,8 @@ export function typstPdfOutputRecipe( // Validate PDF against specified standards using verapdf (if available) const pdfStandards = asArray( - format.render?.[kPdfStandard] ?? format.metadata?.[kPdfStandard] ?? + liveFormat.render?.[kPdfStandard] ?? + liveFormat.metadata?.[kPdfStandard] ?? pdfStandardEnv(), ) as string[]; if (pdfStandards.length > 0) { @@ -284,7 +293,7 @@ export function typstPdfOutputRecipe( } // keep typ if requested - if (!format.render[kKeepTyp]) { + if (!liveFormat.render[kKeepTyp]) { safeRemoveSync(typstInput); } @@ -329,6 +338,14 @@ export function typstPdfOutputRecipe( // if we have some variant declared, resolve it // (use for opt-out citations extension) + // + // Note: this block reads from the captured `format` parameter (the + // construction-time snapshot). That is safe today because it runs + // synchronously before `renderPandoc`, i.e. before any post-construction + // reassignment of `recipe.format` (such as `withBookTitleMetadata`'s deep + // clone — see #14511). Any future code reading format state from this + // recipe AFTER `renderPandoc` has started must use `pandocOptions.format` + // / `recipe.format` (live), not the captured parameter. if (format.render?.[kVariant]) { const to = format.pandoc.to; const variant = format.render[kVariant]; diff --git a/tests/docs/smoke-all/typst/font-paths/brand-font-paths-book/.gitignore b/tests/docs/smoke-all/typst/font-paths/brand-font-paths-book/.gitignore new file mode 100644 index 00000000000..ad293093b07 --- /dev/null +++ b/tests/docs/smoke-all/typst/font-paths/brand-font-paths-book/.gitignore @@ -0,0 +1,2 @@ +/.quarto/ +**/*.quarto_ipynb diff --git a/tests/docs/smoke-all/typst/font-paths/brand-font-paths-book/_quarto.yml b/tests/docs/smoke-all/typst/font-paths/brand-font-paths-book/_quarto.yml new file mode 100644 index 00000000000..263d2ec86be --- /dev/null +++ b/tests/docs/smoke-all/typst/font-paths/brand-font-paths-book/_quarto.yml @@ -0,0 +1,12 @@ +project: + type: book + +brand: branding/brand.yml + +book: + title: "Brand font-paths in a Typst book" + author: "Quarto Test" + chapters: + - index.qmd + +format: typst diff --git a/tests/docs/smoke-all/typst/font-paths/brand-font-paths-book/branding/brand.yml b/tests/docs/smoke-all/typst/font-paths/brand-font-paths-book/branding/brand.yml new file mode 100644 index 00000000000..4cee6c25605 --- /dev/null +++ b/tests/docs/smoke-all/typst/font-paths/brand-font-paths-book/branding/brand.yml @@ -0,0 +1,8 @@ +typography: + fonts: + - family: "Amaranth" + source: file + files: + - fonts/Amaranth-Regular.ttf + base: + family: Amaranth diff --git a/tests/docs/smoke-all/typst/font-paths/brand-font-paths-book/branding/fonts/Amaranth-Regular.ttf b/tests/docs/smoke-all/typst/font-paths/brand-font-paths-book/branding/fonts/Amaranth-Regular.ttf new file mode 100644 index 00000000000..944ccf7d0a5 Binary files /dev/null and b/tests/docs/smoke-all/typst/font-paths/brand-font-paths-book/branding/fonts/Amaranth-Regular.ttf differ diff --git a/tests/docs/smoke-all/typst/font-paths/brand-font-paths-book/index.qmd b/tests/docs/smoke-all/typst/font-paths/brand-font-paths-book/index.qmd new file mode 100644 index 00000000000..46afe7484aa --- /dev/null +++ b/tests/docs/smoke-all/typst/font-paths/brand-font-paths-book/index.qmd @@ -0,0 +1,18 @@ +--- +title: "Brand font-paths in a Typst book (#14511)" +include-in-header: + text: | + #set text(fallback: false) +_quarto: + tests: + typst: + printsMessage: + level: INFO + regex: 'warning: unknown font family' + negate: true +--- + +```{=typst} +#set text(font: "Amaranth") +Testing brand font-paths in a book project. +```