quarto-dev / quarto-dev/quarto-cli

Typst: `_brand.yml` Google fonts download a Latin-only subset for CJK families

Open
#14,761 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

brand bug
Dominant language
JavaScript
Stars
6k
Forks
458
Avg merge
1d 9h
Merged PRs (30d)
41

Description

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

When a font is declared in _brand.yml with source: google and the document is rendered to typst, Quarto downloads the font from the v1 Google Fonts CSS API (https://fonts.googleapis.com/css). For CJK families that endpoint serves a Latin-only subset: for Noto Serif JP it returns a 48 KB TTF whose cmap has 218 codepoints and zero kanji and zero kana.

The result is that every Japanese character in the Typst output falls back to a system font, or renders as tofu () on a machine that has no Japanese font installed.

The v2 endpoint (https://fonts.googleapis.com/css2), which Quarto already uses for the HTML/SCSS path, returns the complete 7.5 MB font for the same family. So HTML output is unaffected and only Typst is broken.

This is easy to miss on a developer machine: if the same family also happens to be installed as a system font (common on macOS), Typst silently uses the system copy and the output looks correct. The failure only shows up on a clean machine.

file size cmap entries kanji kana internal name
v1 /css (what Quarto downloads) 48,176 B 218 0 0 Noto Serif JP ExtraLight Regular
v2 /css2 7,477,960 B 16,726 12,744 189 Noto Serif JP Regular
Steps to reproduce

_brand.yml:

typography:
  fonts:
    - family: Noto Serif JP
      source: google
  base:
    family: Noto Serif JP

report.qmd:

---
title: "Noto Serif JP from _brand.yml"
format:
  typst:
    keep-typ: true
---

吾輩は猫である。名前はまだ無い。

Latin text renders fine.
quarto render report.qmd

# What Quarto downloaded (48 KB -- the whole font is 7.5 MB):
find .quarto/typst/fonts -name '*.ttf' -exec ls -l {} \;

# Compile the kept .typ the way a machine without Japanese system fonts sees it:
quarto typst compile --font-path .quarto/typst/fonts --ignore-system-fonts report.typ actual.png

--ignore-system-fonts is only used to make the bug visible on a machine that happens to have a Japanese font installed; on a clean Linux runner a plain quarto render produces the same tofu.

The two URLs can be compared directly:

# v1 -- what Quarto requests for Typst: 48 KB, no CJK
curl -s -G https://fonts.googleapis.com/css --data-urlencode 'family=Noto Serif JP' | grep -o 'url([^)]*)'
# https://fonts.gstatic.com/s/notoserifjp/v33/xn71YHs72GKoTvER4Gn3b5eMRtWGkp6o7MjQ2bwxOtbHKrc.ttf

# v2 -- 7.5 MB, complete
curl -s 'https://fonts.googleapis.com/css2?family=Noto+Serif+JP' | grep -o 'url([^)]*)'
# https://fonts.gstatic.com/s/notoserifjp/v33/xn71YHs72GKoTvER4Gn3b5eMRtWGkp6o7MjQ2bwxOubA.ttf
Actual behavior

Every Japanese glyph is missing from the downloaded font, so the output is tofu:

Actual behavior: Every Japanese glyph is missing from the downloaded font.
Expected behavior
Expected behavior: Japanese glyph is rendered with the downloaded font.
Your environment
  • IDE: VS Code 1.132.0
  • OS: macOS 26.5.2 (Apple silicon)
Quarto check output
Quarto 1.10.18
[✓] Checking environment information...
      Quarto cache location: /Users/kazuharu/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.10.18
      Path: /Applications/quarto/bin

[✓] Checking tools....................OK
      TinyTeX: v2026.03.02
      Chromium (deprecated): 869685
            (Run "quarto install chrome-headless-shell" to replace)
      Chrome Headless Shell: (not installed)
      VeraPDF: (not installed)

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

[✓] Checking Chrome Headless....................OK
      Using: Chrome found on system
      Path: /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
      Source: MacOS known location

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

[✓] Checking R installation...........OK
      Version: 4.6.0
      Path: /Library/Frameworks/R.framework/Versions/4.6/Resources
      LibPaths:
        - /Users/kazuharu/github/workshop-graduate-2026/rv/library/4.6/arm64
        - /Library/Frameworks/R.framework/Versions/4.6/Resources/library
      knitr: 1.51
      rmarkdown: 2.31

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

[✓] Checking Python 3 installation....OK
      Version: 3.14.6
      Path: /opt/homebrew/Cellar/jupyterlab/4.6.2/libexec/bin/python
      Jupyter: 5.9.1
      Kernels: julia-1.11, julia-1.10, julia-1.12, nbstata

      NOTE: No Jupyter kernel for Python found

[✓] Checking Julia installation...

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Typst rendering path that handles Google fonts declared in _brand.yml, and compare its v1 CSS request with the v2 endpoint already used by the HTML/SCSS path. Reproduce with report.qmd and quarto render, then inspect the downloaded files under .quarto/typst/fonts; done means a clean machine renders the Japanese text without tofu and the complete CJK font is downloaded.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
cli
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.