Typst brand fonts never download a bold-italic face from Google Fonts

Abierto
#14,883 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
3/5
Tiempo estimado
1-2 días
Aptitud para principiantes
76/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
typescript
Área
cli

Línea de trabajo

Start in src/command/render/pandoc.ts at lines 1548-1560 and compare its Google Fonts URL construction with the working v2 URL described for src/core/sass/brand.ts. Reproduce the issue with the provided QMD document, then run quarto typst fonts --variants --font-path .quarto/typst/fonts. Done means the requested normal, italic, bold, and bold-italic faces are available for Typst without changing the HTML path.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

brand bug typst

I have:

  • searched the issue tracker for similar issues
  • installed the latest version of Quarto CLI
  • formatted my issue following the Bug Reports guide

Bug description

For format: typst, Quarto downloads the Google fonts named in the brand
into .quarto/typst/fonts/. When a font entry gives both a style and a
weight, the two never combine. Quarto downloads the weights at normal style
and weight 400 at each style. It never downloads a bold-italic face.

The result is silent. Typst has no face to use, so #strong[... #emph[x] ...]
shows italic at regular weight. A brand that asks for a bold-italic heading
gets the same. Nothing in the render log says a face is missing.

The cause is the URL that Quarto builds for the Google Fonts API. In
src/command/render/pandoc.ts#L1548-L1560,
the family, the style list, and the weight list are joined with :

const parts = [family!];
if (style) {
  style = Array.isArray(style) ? style : [style];
  parts.push(style.join(","));
}
if (weight) {
  weight = Array.isArray(weight) ? weight : [weight];
  parts.push(weight.join(","));
}
const response = await fetch(
  `${base_urls[source]}?family=${parts.join(":")}`,
);

For style: [normal, italic] and weight: [400, 700] this gives:

https://fonts.googleapis.com/css?family=Atkinson Hyperlegible:normal,italic:400,700

That is not valid syntax for the v1 CSS API. The v1 API expects one
comma-separated variant list, in which a weight and a style are one token
(700italic). The API splits the string on commas and reads each part as a
separate variant. The parts here are normal, italic:400 and 700, so it
returns normal 400, italic 400 and normal 700.

Two faults follow from this:

  1. A weight and a style never combine, so bold italic is unreachable.
  2. The first weight in the list is joined to the last style and is lost. For
    style: italic and weight: [700, 900] the token italic:700 returns
    italic 400, and only 900 arrives as a weight.

HTML is not affected. HTML uses a separate code path in
src/core/sass/brand.ts#L119-L153,
which builds a v2 (css2) URL with correct ital,wght@ pairs. For the same
brand it emits
css2?family=Atkinson+Hyperlegible:ital,wght@0,700;1,700, and that URL does
serve italic 700.

Steps to reproduce

Render this document. The brand is in the document YAML, so no _brand.yml
file is necessary. It asks for two weights at two styles.

---
title: "Bold italic"
format: typst
brand:
  typography:
    fonts:
      - family: Atkinson Hyperlegible
        source: google
        weight: [400, 700]
        style: [normal, italic]
    base: Atkinson Hyperlegible
---

Normal. *Italic.* **Bold.** ***Bold italic.***

Then ask Typst which variants it found in the font cache:

quarto typst fonts --variants --font-path .quarto/typst/fonts

Actual behavior

Rendered document showing the 'bold italic' heading and text italic but not bold.

No bold-italic face is in the cache:

Atkinson Hyperlegible
  ├ .../9Bt43C1KxNDXMspQ1lPyU89-1h6ONRlW45G056IqUwU.ttf
  │   Style: Italic, Weight: 400, Stretch: 100%
  ├ .../9Bt73C1KxNDXMspQ1lPyU89-1h6ONRlW45G8Wbc9dCWK.ttf
  │   Style: Normal, Weight: 700, Stretch: 100%
  └ .../9Bt23C1KxNDXMspQ1lPyU89-1h6ONRlW45G04pIt.ttf
      Style: Normal, Weight: 400, Stretch: 100%

Three faces arrive out of the four requested combinations, and italic 700 is
the one that never arrives. All four exist for this family. The render gives
no warning, so ***Bold italic.*** shows italic at regular weight.

The result is the same when the brand asks for the bold-italic face alone.
With weight: 700 and style: italic, one face arrives, and it is
Style: Italic, Weight: 400.

Two separate fonts: entries for the same family give the same result. A
_brand.yml file gives the same result as the document YAML above: both
produce an identical .typ file.

Google does serve the face. This command returns italic 700:

curl -s "https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible:ital,wght@0,400;0,700;1,400;1,700"

Expected behavior

Quarto downloads a face for each combination of the requested weights and
styles that exist for the family. For the document above,
quarto typst fonts --variants also reports Style: Italic, Weight: 700.
If a combination does not exist for the family, Quarto says so in the render
log, as it already does for an unusable font format.

Your environment

  • IDE: Positron 1.130.0
  • OS: macOS 26.6.2 (build 25G83)

The fault is also present in the development version. The font fetch is
TypeScript that a development build runs from source, and the lines above are
unchanged between the v1.11.4 tag and main at 8c87d79. A development build
of main downloads the same single 9Bt4 file.

Quarto check output

Quarto 1.11.4
[✓] Checking environment information...
      Quarto cache location: /Users/charlottewickham/Library/Caches/quarto
[✓] Checking versions of quarto binary dependencies...
      Pandoc version 3.10.0: OK
      Dart Sass version 1.101.0: OK
      Deno version 2.7.14: OK
      Typst version 0.15.1: OK
[✓] Checking versions of quarto dependencies......OK
[✓] Checking Quarto installation......OK
      Version: 1.11.4
      Path: /Applications/quarto/bin

[✓] Checking tools....................OK
      TinyTeX: v2026.04
      Chrome Headless Shell: 150.0.7871.115
      VeraPDF: 1.28.2

[✓] Checking LaTeX....................OK
      Using: TinyTex
      Path: /Users/charlottewickham/Library/TinyTeX/bin/universal-darwin
      Version: 2026

[✓] Checking Chrome Headless....................OK
      Using: Chrome Headless Shell installed by Quarto
      Path: /Users/charlottewickham/Library/Application Support/quarto/chrome-headless-shell/chrome-headless-shell-mac-arm64/chrome-headless-shell
      Version: 150.0.7871.115

[✓] Checking basic markdown render....OK

[✓] Checking R installation...........OK
      Version: 4.5.2
      Path: /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources
      LibPaths:
        - /Users/charlottewickham/Library/R/arm64/4.5/library
        - /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/library
      knitr: 1.51
      rmarkdown: 2.30

[✓] Checking Knitr engine render......OK

[✓] Checking Python 3 installation....OK
      Version: 3.12.2
      Path: /Users/charlottewickham/.pyenv/versions/3.12.2/bin/python3
      Jupyter: 5.9.1
      Kernels: python3

[✓] Checking Jupyter engine render....OK

[✓] Checking Julia installation...

An AI assistant helped investigate this, grounded in a local clone of
quarto-cli, as described in Using AI tools to investigate.

Lenguaje dominante
JavaScript
Estrellas
6k
Forks
458
Merge medio
1 d 8 h
PR fusionados (30 d)
42

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de quarto-dev/quarto-cli

Todos los issues de quarto-dev/quarto-cli

Issues similares

Más issues de JavaScript

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.