Summary
Converting ordinary LaTeX to Typst produces .typ files that fail typst compile with a hard error
for two very common constructs. Unlike the HTML/DOCX writers, Typst has a compile step, so these
degrade from "renders slightly differently" to "produces no document at all".
Both have small, well-scoped fixes. Tested with pandoc 3.10.1 and typst 0.15.1.
Case A: \ref to a section
\documentclass{article}\begin{document}
\section{Intro}\label{sec:i}
See \ref{sec:i}.
\end{document}
$ pandoc -s -f latex -t typst a.tex -o a.typ
$ typst compile a.typ
error: cannot reference heading without numbering
┌─ a.typ:150:4
│
150 │ See @sec:i.
│ ^^^^^^
│
= hint: you can enable heading numbering with `#set heading(numbering: "1.")`
The writer emits @sec:i, but nothing sets heading numbering. article numbers sections by
default in LaTeX, so this affects essentially every structured LaTeX document that uses \ref.
The default Typst template already supports this. It never receives the value:
$ pandoc --print-default-template=typst | grep -n section-numbering
104:$if(section-numbering)$
105: sectionnumbering: "$section-numbering$",
Confirmed workaround:
$ pandoc -s -f latex -t typst -M section-numbering="1.1" a.tex -o a.typ && typst compile a.typ
# succeeds
Suggested fix: have the LaTeX reader set section-numbering when the document class numbers
sections and \ref targets exist (mirroring the LaTeX default), or have the Typst writer fall back
to a plain #link(<label>)[…] when it cannot guarantee the target is numbered.
Case B: thebibliography, where the root cause is in the LaTeX reader
\documentclass{article}\begin{document}
Text \cite{k}.
\begin{thebibliography}{9}\bibitem{k} Knuth.\end{thebibliography}
\end{document}
$ pandoc -s -f latex -t typst b.tex -o b.typ
$ typst compile b.typ
error: label `<k>` does not exist in the document
┌─ b.typ:148:5
│
148 │ Text @k.
│ ^^
The reader drops the \bibitem key entirely. The resulting Span has an empty identifier:
$ pandoc -f latex -t native b.tex | tail -4
, Div
( "" , [ "thebibliography" ] , [] )
[ Para
[ Span ( "" , [] , [] ) [ Str "9" ] , Space , Str "Knuth." ]
The \cite{k} still becomes a Cite with citationId = "k", which the Typst writer renders as
@k. Since the key never reached the bibliography entry, the label does not exist.
This is also visible (less harmfully) in the HTML writer, which emits an empty citation:
$ pandoc -f latex -t html b.tex
<p>Text <span class="citation" data-cites="k"></span>.</p>
<div class="thebibliography">
<p><span>9</span> Knuth.</p>
</div>
--citeproc is not a workaround. It compiles, but silently drops the citation:
$ pandoc -s -f latex -t typst --citeproc b.tex -o b2.typ
[WARNING] Citeproc: citation k not found
The BibTeX path works correctly, which isolates the problem to thebibliography:
$ printf '\\documentclass{article}\\begin{document}\nText \\cite{k}.\n\\bibliography{r}\n\\end{document}\n' > c.tex
$ pandoc -s -f latex -t typst c.tex -o c.typ && typst compile c.typ # succeeds
$ grep bibliography c.typ
#bibliography(("r.bib"))
Minimal fix: preserve the \bibitem key as the identifier on the emitted Span
(or on a wrapping Div), so writers can attach a label. That alone makes the Typst output compile
and simultaneously fixes the empty data-cites span in the HTML writer.
Fuller fix: have the Typst writer emit #bibliography entries, or attach <key>
labels to each bibliography item.
Reproduction script
#!/usr/bin/env bash
set -uo pipefail
run() {
pandoc -s -f latex -t typst "$1.tex" -o "$1.typ" || return 1
if typst compile "$1.typ" "$1.pdf" >/dev/null 2>&1
then printf '%-2s compiles=YES\n' "$1"
else printf '%-2s compiles=NO\n' "$1"; typst compile "$1.typ" "$1.pdf" 2>&1 | head -3
fi
}
run a # NO — \ref to section
run b # NO — thebibliography
run c # YES — \bibliography{r.bib}
run d # YES — title/author/math
Observed on pandoc 3.10.1 / typst 0.15.1 / macOS 15 arm64.
Why this matters beyond the two cases
The Typst writer handles the rest well. Headings, labels, math, booktabs tables
(table.hline), figures, \title/\author, and \bibliography{x.bib} all convert cleanly.
These two gaps are what make "convert an existing LaTeX paper to Typst" fail in practice, since \ref and an inline
thebibliography appear in a large share of real documents, including many self-contained
conference and journal submissions where thebibliography is required rather than optional.
I am happy to prepare a PR for the reader-side \bibitem identifier fix if the approach looks right.
Summary
Converting ordinary LaTeX to Typst produces
.typfiles that failtypst compilewith a hard errorfor two very common constructs. Unlike the HTML/DOCX writers, Typst has a compile step, so these
degrade from "renders slightly differently" to "produces no document at all".
Both have small, well-scoped fixes. Tested with pandoc 3.10.1 and typst 0.15.1.
Case A:
\refto a sectionThe writer emits
@sec:i, but nothing sets heading numbering.articlenumbers sections bydefault in LaTeX, so this affects essentially every structured LaTeX document that uses
\ref.The default Typst template already supports this. It never receives the value:
Confirmed workaround:
Suggested fix: have the LaTeX reader set
section-numberingwhen the document class numberssections and
\reftargets exist (mirroring the LaTeX default), or have the Typst writer fall backto a plain
#link(<label>)[…]when it cannot guarantee the target is numbered.Case B:
thebibliography, where the root cause is in the LaTeX readerThe reader drops the
\bibitemkey entirely. The resultingSpanhas an empty identifier:The
\cite{k}still becomes aCitewithcitationId = "k", which the Typst writer renders as@k. Since the key never reached the bibliography entry, the label does not exist.This is also visible (less harmfully) in the HTML writer, which emits an empty citation:
--citeprocis not a workaround. It compiles, but silently drops the citation:The BibTeX path works correctly, which isolates the problem to
thebibliography:Minimal fix: preserve the
\bibitemkey as the identifier on the emittedSpan(or on a wrapping
Div), so writers can attach a label. That alone makes the Typst output compileand simultaneously fixes the empty
data-citesspan in the HTML writer.Fuller fix: have the Typst writer emit
#bibliographyentries, or attach<key>labels to each bibliography item.
Reproduction script
Observed on pandoc 3.10.1 / typst 0.15.1 / macOS 15 arm64.
Why this matters beyond the two cases
The Typst writer handles the rest well. Headings, labels, math,
booktabstables(
table.hline), figures,\title/\author, and\bibliography{x.bib}all convert cleanly.These two gaps are what make "convert an existing LaTeX paper to Typst" fail in practice, since
\refand an inlinethebibliographyappear in a large share of real documents, including many self-containedconference and journal submissions where
thebibliographyis required rather than optional.I am happy to prepare a PR for the reader-side
\bibitemidentifier fix if the approach looks right.