Typst ist ein relativ neues open-source Textsatzsystem, das als Alternative zu LaTeX entwickelt wurde. Es zeichnet sich durch eine einfachere Syntax und eine intuitivere Bedienung aus, während es dennoch die leistungsstarken Formatierungs- und Gestaltungsmöglichkeiten bietet, die für wissenschaftliche und technische Dokumente erforderlich sind.
Seit der Version 1.4 (Januar 2024) ist Typst in Quarto enthalten und kann daher direkt verwendet werden um PDF-Dokumente zu erzeugen, siehe https://quarto.org/docs/output-formats/typst.html.
Vorteile von Typst gegenüber LaTeX
- Es ist unglaublich schnell! Typst ist in Rust geschrieben und verwendet inkrementelle Kompilierung, was schnellere Kompilierungszeiten ermöglicht. Selbst bei einfachen einseitigen Dokumenten ist es spürbar schneller als LaTeX.
- Es ist direkt in Quarto enthalten und muss nicht zusätzlich installiert werden.
- Die Syntax ist (ein wenig :-) ) einfacher als bei LaTeX.
- Die Fehlermeldungen sind aussagekräftiger als bei LaTeX.
Nachteile
- LaTeX kann viel mehr als Typst.
- Typst ist noch relativ neu, es kann noch nicht alles. Es hat nichtmals einen Wikipediaeintrag (Stand 11/2024).
- Falls ihr euch von “KI” inspirieren lassen wollt: ChatGTP und Co. können Typst quasi gar nicht und erzeugen großen Müll-Code.
PDF-Dokumente
Seit Jahrzehnten (ja, ich bin alt) verwende ich LaTeX. Mittlerweile erzeuge ich alle meine Dokument mit Quarto, aber immerhin habe ich meine schönsten LaTeX Vorlagen in Quarto-Extensions ausgelagert, so dass ich sie “unter der Haube” immer noch verwende (siehe z.B. diesen Blogpost). Das funktioniert sehr gut, und eigentlich bin ich auch zufrieden damit.
Dennoch habe ich einfach mal aus Spaß Typst ausprobiert, und vor allem die Geschwindigkeit des rendering hat mich sehr begeistert. Meine LaTeX Dokumente benötigen mindestens 2 (manchmal sogar 3) LaTeX-Läufe, die für sich schon relativ lange brauchen, um durchzulaufen. Typst hingegen ist nach einem Lauf fertig, und dieser Lauf ist einfach unglaublich schnell.
Also habe ich auf den Bahnfahrten angefangen, meine LaTeX-Extensions um Typst zu erweitern.
Eine Quarto Extension erstellen
Um eine neue Extension zu erstellen folge ich grob der Anleitung auf der Quarto Webseite.
Für meine Extensions habe ich ein eigenes Verzeichnis. Per Terminal wechsel ich in dieses Verzeichnis und starte dort ein neues Extensionprojekt mit dem Befehl
Terminal
$ quarto create extension format
Nun wähle ich typst
aus der Auswahlliste und gebe erneut den Namen der Extension (foobar
) ein. Anschließend kann der Ordner z.B. mit vscodium
geöffnet werden.
Ich bearbeite die Dateien nicht in RStudio, da dort kein Syntax Highlighting für Typst angeboten wird. Ich nutze Positron, aber grundsätzlich geht es natürlich mit jedem Texteditor.
In meinem Ordner liegt nun ein neues Verzeichnis foobar
, und in diesem sind die folgenden Dateien und Verzeichnisse zu finden:
Dateistruktur im Ordner foobar
template.qmd
README.md
_extensions/
_extensions/foobar/
_extensions/foobar/_extension.yml
_extensions/foobar/typst-show.typ
_extensions/foobar/typst-template.typ
Die Dateien sind bereits mit Standardinhalt befüllt, so dass die die Datei template.qmd
direkt gerendert werden kann. Probiert es mal direkt aus!
Schaut euch die generierten Dateien an:
template.qmd
- Das Dokument, welches gerendert werden soll.README.md
- Eine README-Datei mit allen Infos zur Extension._extensions/
- Hier liegen alle Extensions, auf dietemplate.qmd
zugreifen kann._extensions/foobar/
- Hier liegt unsere Extension._extensions/foobar/_extension.yml
- Hier geben wir die Metadaten unserer Extension (Name, Autor, Beschreibung, etc.) an, sowie die bereitsgestellten Formate nebst Standardparameter_extensions/foobar/typst-show.typ
- Diese Datei ruft unser eigentliches Template auf. Hier können zudem Pandoc-Metadaten an Funktionsparameter gemappt werden._extensions/foobar/typst-template.typ
- Unsere eigentliche Templatedatei.
Für mich als Autodidakt war es herausfordernd, die Typst-Syntax zu lernen. Eine sehr wichtige Nachschlageseite hierfür ist https://typst.app/docs/. Die Standardinhalte von typst-show.typ
und typst-template.typ
haben mich zunächst stark verwirrt, so dass ich in diesem Blogbeispiel mit leeren .typ
-Dateien anfangen möchte.
typst-show.typ
Die Datei typst-show.typ
ruft unser eigentliches Template auf. Ich lösche den Standardinhalt und ersetze ihn mit dieser einzigen Funktion.
typst-show.typ
#show: foobar.with(
)
Innerhalb dieser Funktion können wir (später) YAML-Parameter abgreifen. Dies funktioniert allerdings auch in der Datei typst-template.typ
, so dass ich es hier zunächst auslasse.
typst-template.typ
In der Datei typst-template.typ
lebt unser eigentliches Template. Auch hier lösche ich den Standardinhalt und ersetze ihn durch
typst-template.typ
#let foobar(// Welche Werte erwartet mein Template?
body= {
) // Hier beginnt die Ausgabe
body}
Die Datei besteht aus 2 Teilen, #let foobar()
definiert unsere Templatefunktion (die, die von typst-show.typ
aufgerufen wird) und legt fest, welche Parameter diese Funktion erwartet. Standardmäßig steht hier nur body
, womit der Inhalt unserer template.qmd
gemeint ist.
Im zweiten Teil, welcher mit ={ ... }
eingeleitet wird, erfolgt das eigentliche Styling der Ausgabe. Auch hier steht derzeit nur body
, was bedeutet, dass der Inhalt auf einer “blanken” Seite ausgegeben wird. Klickt mal jetzt auf “rendern”.
Typst-Befehle mit und ohne #
Was mich am Anfang am meisten verwirrt hat ist, dass Typst-Befehle und -Variablen manchmal ein #
vorangestellt benötigen, und manchmal nicht. So wie ich es verstanden habe
- wird bei jedem Befehl und jeder Variable ein
#
benötigt. - innerhalb von Funktionsdefinitionen (z.B. der zweite Teil unserer
foobar
Funktion) dürfen keine#
verwendet werden. Alles, was in runden Klammern steht, benötigt kein#
. - innerhalb von Funktionsaufrufen müssen wieder
#
gesetzt werden. Alles, was in eckigen Klammern steht, benötigt ein#
.
YAML-Parameter direkt auslesen
Parameter aus dem YAML-Header können wie gewohnt über Pandoc gemappt werden. In unserer Extension wollen wir zunächst den title
-Parameter auslesen und ausgeben.
Wir können dies einerseits direkt in der typst-template.typ
vornehmen
typst-template.typ
#let foobar(// Welche Werte erwartet mein Template?
body= {
) // Hier beginnt die Ausgabe
// title anzeigen
$title$]
text(36pt)[
body}
Wenn ihr jetzt rendert, seht ihr den großen Titel am Dokumentanfang.
YAML-Parameter über typst-show.typ
anmelden
Ein anderer Weg, um den Parameter title
aus dem YAML-Header zu lesen, erfolgt in 2 Schritten.
- In der Datei
typst-show.typ
lesen wir den Parameter aus und weisen ihn der Variablemeintitel
zu:
typst-show.typ
#show: foobar.with($title$",
meintitel: " )
Beachtet, dass $title$
in Anführungszeichen gewickelt werden muss. Wir können hier noch sicherstellen, dass die Zuweisung nur dann erfolgt, wenn der Parameter auch wirklich im YAML angegeben ist:
typst-show.typ
#show: foobar.with($if(title)$
$title$",
meintitel: "$endif$
)
- In der Datei
typst-template.typ
geben wir an, dass die Variablemeintitel
zuvor ausgelesen wurde. Somit steht uns im unteren Teil des Templates die Variable#meintitel
zur Verfügung, und der Befehl zur Titelausgabe ändert sich entsprechend intext(36pt)[#meintitel]
.
typst-template.typ
#let foobar(// Welche Werte erwartet mein Template?
: none,
meintitel
body= {
) // Hier beginnt die Ausgabe
// title anzeigen
text(36pt)[#meintitel]
body}
Im oberen Teil haben wir meintitel: none,
angegeben, was bedeutet, dass die Variable leer bleibt, sofern sie nicht im YAML angegeben ist. Natürlich können wir hier auch Standardwerte hinterlegen, z.B:
typst-template.typ
#let foobar(// Welche Werte erwartet mein Template?
: "Du hast den Titel vergessen",
meintitel
body= {
) // Hier beginnt die Ausgabe
// title anzeigen
text(36pt)[#meintitel]
body}
Wenn Sie nun in template.qmd
den YAML-Parameter title
entfernen, greift typst auf den Standardwert "Du hast den Titel vergessen"
zurück.
Was ist nun besser?
Ich habe noch nicht genau verstanden, wie die Parameter “am besten” abgegriffen werden. Es funktioniert jedenfalls alles wunderbar, wenn typst-show.typ
quasi leer bleibt, und alle Parameter direkt in der typst-template.typ
verarbeitet werden. Naja, ihr kennt nun beide Vorgehensweisen und könnt selbst auswählen…. :-)
Bilddateien bereitstellen (Sonderzeichen escapen)
Manche meiner Extensions bringen Logo-Dateien mit (z.B. meine Briefvorlage an der Hochschule). Die Logos liegen ebenfalls im _extensions
-Ordner und werden über die _extension.yml
angegeben:
_extension.yml
title: Foobar
author: Joe Slam
version: 1.0.0
quarto-required: ">=1.5.0"
contributes:
formats:
typst:
logo: MeinLogo.png
template-partials:
- typst-template.typ
- typst-show.typ
Dateistruktur im Ordner foobar
template.qmd
README.md
_extensions/
_extensions/foobar/
_extensions/foobar/_extension.yml
_extensions/foobar/typst-show.typ
_extensions/foobar/typst-template.typ
_extensions/foobar/MeinLogo.png
Das Problem besteht darin, dass der relative Pfad zur Logodatei ein Sonderzeichen _
enthält. Dieser wird von Typst in \_
“escaped”, so dass der Pfad nicht als _extensions/foobar/MeinLogo.png
sonder als \_extensions/foobar/MeinLogo.png
erkannt wird. Um dies wieder rückgängig zu machen, kann innerhalb der .typ
-Dateien die Funktion OBJEKT.replace("\\", "")
verwendet werden.
Zunächst greifen wir den Logopfad in der Datei typst-show.typ
ab.
typst-show.typ
#show: foobar.with($if(title)$
$title$",
meintitel: "$endif$
$if(logo)$
$logo$",
logo: "$endif$
)
In der Datei typst-template.typ
melden wir die Variable logo
an und reparieren den kaputten Pfad.
typst-template.typ
#let foobar(// Welche Werte erwartet mein Template?
: "Du hast den Titel vergessen",
meintitel: none,
logo
body= {
) // Hier beginnt die Ausgabe
// Logo-Pfad escapen
let logo_path = logo.replace("\\", "")
// Logo anzeigen
, width: 70mm)
image(logo_path
// title anzeigen
text(36pt)[#meintitel]
body}
Ausgabe stylen
Auf diese Weise erweitere ich meine Extension nach und nach, so dass alles nach meinen Wünschen ausgegeben wird.
Wie man genau die Seiteneigenschaften (DIN-A4, deutsche Sprache, Kopf- und Fußzeilen, etc.) beeinflusst, habe ich in der Typst-Dokumentation nachgelesen, siehe https://typst.app/docs/. Sehr hilfreich war für mich deren Guide for LaTeX users.
Beispiel
Herausgekommen ist beispielsweise diese simple Extension, die ich für Aushänge an der Hochschule nutze. Sie nimmt die Parameter title
und logo
entgegen. In der Kopfzeile wird rechts das Logo ausgegeben, und links ein schöner blauer Kasten mit dem title
in weißer Schrift.
In unserer foobar
-Extension müssen die Dateien wie folgt geändert werden:
_extension.yml
title: Foobar
author: Joe Slam
version: 1.0.0
quarto-required: ">=1.5.0"
contributes:
formats:
typst:
logo: MeinLogo.png
lang: de
font: "Times New Roman"
font-size: 12pt
template-partials:
- typst-template.typ
- typst-show.typ
typst-show.typ
#show: foobar.with(
// Diese Werte kommen aus dem YAML$title$",
title: "$lang$",
lang: "$logo$",
logo: "$font$",
font: "$font-size$,
font-size: )
typst-template.typ
#let foobar(// welche Wert werden aus dem YAML-Header gelesen?
: none,
title: none,
logo: none,
lang: none,
font-size: none,
font
body= {
)
// Hier startet die eigentliche Funktion
// Der Logo-Pfad muss escaped werden
let logo_path = logo.replace("\\", "")
// Schriftart und Sprache einstellen
: font,
set text(font: font-size,
size: lang,)
lang// Blockschrift aktivieren
: true)
set par(justify
// Farben definieren
let HSNRblue1 = rgb("185191")
let HSNRblue2 = rgb("07A1E2")
// Seitengröße und -ränder festlegen
: 210mm,
set page(width: 297mm,
height: (top: 30mm, bottom: 30mm, left: 20mm, right: 20mm),
margin: "1",
numbering-align: center,
number// Kopfzeile
: grid(
header: (1fr, 1fr),
columns: (left, right),
align: HSNRblue1,
rect(fill: 70%,
width: (x: 54pt))[#text(white, 18pt)[#title]],
outset, width: 70mm),
image(logo_path,
)// Fußzeile
: align(center)[#context counter(page).display("1 von 1",both: true,)]
footer
)
// Abstand zwischen Header und Body
v(5mm)
// Hauptteil des Dokuments
body}
Das sieht dann so aus:
Zudem habe ich meine quarto-letter
-Extension auf typst angepasst und bei Github veröffentlicht, siehe https://github.com/produnis/quarto-letter.
Weblinks
- https://typst.app/docs
- https://quarto.org/docs/output-formats/typst.html
- https://quarto.org/docs/output-formats/typst-custom.html
- https://www.produnis.de/blog/posts/2022-09-12-quarto-briefvorlage/
- https://nrennie.rbind.io/blog/pdf-quarto/making-pdf-with-quarto-typst-latex/
- https://typst.app/docs/guides/guide-for-latex-users/
- https://github.com/quarto-dev/quarto-cli/discussions/11364
- https://github.com/quarto-dev/quarto-cli/discussions/11392
- https://github.com/produnis/quarto-letter