Skip to content

fix(pdf): auto-install typst on Linux/Windows, render CJK text in PDFs - #30

Merged
mtmatt merged 1 commit into
mainfrom
fix/cjk-pdf-and-typst-install
Sep 28, 2026
Merged

mtmatt merged 1 commit into
mainfrom
fix/cjk-pdf-and-typst-install

Conversation

@mtmatt

@mtmatt mtmatt commented Sep 28, 2026

Copy link
Copy Markdown
Owner

Stacked on #29. This PR's base is chore/cleanup-and-linux-fixes, so the diff shows only this change. Merge #29 first, then retarget this PR to main.

Fixes two user reports: the typst engine is never installed automatically, and Chinese text breaks in some conversions such as md→pdf. Reproducing them turned up a few more causes, listed below.

Root causes and fixes

  1. typst never auto-installs on Linux/Windows. tools.toml has a [typst] entry, but downloader.rs's Manifest had no typst field (serde silently ignores the table) and ensure_tool had no "typst" arm. So ensure_typst always failed with unknown tool: typst.

    • Added the field, and a single Manifest::spec(name) lookup that tool_version and ensure_tool now share.
    • Pinned typst's sha256s from GitHub's release digests. The Linux archive was downloaded and verified against the checksum and the configured binary path.
    • Added a test that every tools.toml table resolves. It fails if the typst arm is removed.
  2. A typst in the tool dir was never used. detect_pdf_engine returned the bare name "typst", and pandoc then couldn't find a binary that wasn't on PATH. The new document/pdf.rs finds each engine's full path and appends engine dirs to pandoc's PATH. Pandoc still gets the engine name, because with a full path it extracts images to absolute temp paths that typst refuses to read, which breaks png→pdf.

  3. md→pdf via typst failed for every document on Linux. Distro pandoc 3.1.x (Debian, Ubuntu, Fedora) ships a typst template whose default font list is (), and current typst rejects an empty list ("font fallback list must not be empty"). The app now detects that template once per run and passes -V mainfont=Libertinus Serif. Newer pandoc gets no extra variables.

  4. CJK text. Pandoc's default fonts have no CJK glyphs:

    • pdflatex errors out.
    • xelatex/tectonic silently drop the characters.
    • typst grabs arbitrary system fallbacks. On macOS that meant SIL Hei Medium, Osaka and JCfg, plus misaligned list bullets.

    Documents with CJK letters (ideographs, kana or Hangul) now get:

    • typst with the installed CJK fonts from a preference list placed after the Latin font (mainfont, plus codefont for code blocks). If none of the listed fonts is installed, typst falls back to its own choice and a warning is logged.
    • .tex input prefers XeLaTeX-family engines with CJKmainfont, since the typst writer would drop raw LaTeX.
    • pdflatex only gives a clear error.
    • Font variables the document sets in its own YAML front matter are never overridden.
  5. image→pdf (found along the way; old pandoc ignores --resource-path with typst, and file names with spaces or parentheses broke ![](name)): the image is now copied into a temp dir and pandoc runs there.

Before / after (macOS, same Chinese/Japanese/Korean sample)

  • Before: mixed SIL Hei Medium, Osaka and JCfg glyphs, and bullets misaligned.
  • After: Songti SC, a serif that matches the Latin text, with Songti Bold headings, Apple SD Gothic Neo for Korean, and aligned bullets.

Testing

  • macOS (pandoc 3.9, typst 0.14.2): 126 unit tests plus 3 CLI end-to-end tests pass.
    • cjk_pdf_embeds_only_the_chosen_fonts runs real pandoc+typst and fails, naming SIL-Hei, without the fix.
    • image_to_pdf_handles_relative_path_and_awkward_name is a new CLI test.
  • Linux (Docker, Debian's pandoc 3.1.11, typst only in the tool dir):
    • plain md→pdf works (it failed before)
    • CJK without a known font falls back with a warning
    • CJK with fonts-noto-cjk embeds Noto Serif CJK plus Libertinus
    • image→pdf works (the new test fails against the old code)
    • a document's own mainfont is respected
    • the full suite passes under xvfb
  • clippy -D warnings is clean on macOS, Linux and Windows-gnu, and fmt is clean.
  • Not tested: the Windows runtime, the LaTeX engines, and wkhtmltopdf (none installed). CI has neither pandoc nor typst, so the tools-dependent tests skip there.

🤖 Generated with Claude Code

@mtmatt
mtmatt added this pull request to stack #31 September 28, 2026 11:55
Base automatically changed from chore/cleanup-and-linux-fixes to main September 28, 2026 11:56
- typst was listed in tools.toml but never wired into the downloader's
  Manifest, so ensure_typst failed with "unknown tool: typst" on
  Linux/Windows. Add it, pin its sha256s, and test that every tools.toml
  table resolves.
- New document/pdf.rs picks pandoc's PDF engine. It passes pandoc the
  engine name (a full path makes pandoc break typst image paths) and
  appends engine dirs to pandoc's PATH, so a typst in the app's tool dir
  is found.
- Distro pandoc 3.1.x's typst template defaults to an empty font list,
  which current typst rejects: md -> pdf via typst failed for every
  document on Linux. Detect that template and pass a mainfont.
- Documents with CJK text get a real CJK font: typst with an installed
  CJK font list behind its Latin font (instead of arbitrary fallback
  fonts), or CJKmainfont for XeLaTeX-family engines (preferred for .tex
  input). Font variables in the document's own front matter are left
  alone.
- image -> pdf stages the image in a temp dir and runs pandoc there:
  old pandoc ignores --resource-path with typst, and names with spaces
  or parentheses broke the generated markdown.
@mtmatt
mtmatt force-pushed the fix/cjk-pdf-and-typst-install branch from 9eec41b to f17115f Compare September 28, 2026 11:56
@mtmatt
mtmatt merged commit 23b7b67 into main Sep 28, 2026
9 checks passed
@mtmatt
mtmatt deleted the fix/cjk-pdf-and-typst-install branch September 28, 2026 12:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant