Typst – Ein Next-Gen-Textsatzsystem?


Typst ist ein relativ neues (2023) Textsatzsystem. Es wurde in Rust komplett neu geschrieben. Anlaß für diese Entwicklung (gibt es nicht schon LaTeX u.a. Textsatzsysteme?) war angeblich der hohe Einarbeitungs- und Anwendungsaufwand mit der TeX-Syntax. Man kennt es: Einige LaTeX-Pakete sind miteinander inkompatibel, und auch sonst sind Anpassungen abseits der gängigen Makros für viele Nutzer (auch für mich!) schwer verständlich. Beim Kompilieren ergeben sich nicht nachvollziehbare Auswirkungen oder sie werden gleich mit Fehlermeldungen quittiert, für die man selbst die Foren durchsuchen muß.

Davon genervt, wurde das Rad also neu erfunden. Einfach in der Anwendung sollte es sein (so wie Markdown) und hochkonfigurierbar (so wie TeX), dabei verständliche ("sprechende") Fehlermeldungen erzeugen. Welche Vorzüge bietet nun diese Chimäre? Und ist sie für komplexe Dokumente weit genug gereift?

Was wird erzeugt?

Grundanspruch ist das Erzeugen bzw. Setzen von druckfertigen Dokumenten (meist PDF) mit erstklassigen Satzlayout, dabei mit Fokus auf wissenschaftliche Publikationen. Wie TeX bietet es daher die volle Palette an Formeldarstellungen, und kann mithilfe von zahlreichen Vorlagen (templates) in die jeweilige Darstellungsform des jeweiligen Verlages gebracht werden. Derselbe Dokumentinhalt (Definition von Titel, Autorenschaft, Abstract, Dokumentinhalt usw.) kann also mit Vorlagen in verschiedene Layouts übersetzt werden (z.B. Lebensläufe verschiedener Ausführung). Man denkt dabei gleich an austauschbare CSS-Dateien. Inwiefern bei so einem Vorhaben nicht gleich Jupyter sinnvoll ist, bleibt fraglich.

Was braucht man zum Starten?

Neben einem Online-Editor kann die Typst-Syntax auch in anderen Entwicklungsumgebungen geschrieben und gerendert werden. Ich verwende hierfür z.B. VSCodium mit der Tinymist-Erweiterung (Abb. 1).

Abb. 1: Im freien Editor VSCodium kann über die Erweiterungen (links, grüner Kasten) "tinymist" installiert werden. Anschließend läßt sich aus dem Quellcode (Datei-Endung: .typ) über die geteilte Ansicht (oben, roter Kasten) eine Vorschau darstellen. Der PDF-Export gelingt über den danebenliegenden Button (roter Pfeil).

Ein nativer Typst-Editor heißt Katvan (alle Betriebssysteme, portable auch für Windows). Ich habe das Gefühl, der Quellcode wird schneller als mit Tinymist kompiliert. Außerdem gibt es eine Anzeige, wie lange das Kompilieren dauerte (x Millisekunden), und in der Statusleiste wird direkt die Wortanzahl eingeblendet. Weitere Typst-Editoren heißen Typesetter (elegant und ablenkungsfrei!) und Typstify.

Wie sieht die Syntax aus?

Im Grunde tatsächlich sehr einfach. Eine Präambel, wie man sie von LaTeX kennt, entfällt. Im einfachsten Fall kann man die ersten Sätze ohne weitere Formatierungen eingeben und darstellen lassen. Werden keine Vorgaben zur Schriftart oder den Blatteinstellungen gemacht, gibt Typst den Text in einer voreingestellten Schriftart und mit voreingestellten Seitenrändern aus.

Zunächst zum weiteren Code: Ein doppelte vorangestelltes \\ entspricht der Kommentarfunktion. Alles, was dahinter folgt, bleibt also für die Interpretation unsichtbar.

Möchte man Seiteneinstellungen vornehmen, gibt man zu Beginn des Dokuments an:

// SEITE
#set page(
paper: "a4",
margin: (x: 3cm, y: 2cm),
numbering: "1 / 1",
fill: rgb(255, 254, 252),
header: align(right)[
Mein Dokument],
)

Die Interpretation ist selbsterklärend: Die Seitengröße ist A4, der Rand rechts und links sind je 3 cm, oben und unten sind es je 2 cm. Mit numbering gebe ich die Formatierung der Seitenzahlen vor, also: Seite "1" von "(Gesamtzahl). Man kann auch nur 1 schreiben, dann erscheint eben nur die Seitenzahl. Mit fill wird eine Seitenfarbe (RGB) festgelegt. Ein header mit dem Inhalt "Mein Dokument" erscheint oben rechts auf jeder Seite. Jede Anweisung wird mit einem Komma beendet.

Wie bei TeX folgt also einer Anweisung in Klammern eine Spezifikation. Bei der Kopfzeile (header) wird also definiert: align (= Ausrichtung) ist "rechts" (in runden Klammern), gefolgt vom Inhalt in eckigen Klammern.

Die Schriftart wird genauso eingestellt:

// TEXT
#set text(
font: "Source Sans 3",
size: 10pt,
lang: "de" //führt zu deutschen Anführungszeichen
)

Die Anweisung der Sprache ist insofern bedeutend, weil damit die Art der Anführungszeichen bestimmt und der jeweilige Trennalgorithmus der Sprache angewendet wird.

Wer sich gleich auf Blocksatz einschießen will, legt das mit der generellen Absatzformatierung fest:

// ABSATZ
#set par(
justify: true, // Blocksatz
leading: 0.65em, // Zeilenabstand
)

justify (true/false) bestimt die Ausrichtung, und mit leading kann gleich der Zeilenabstand beeinflußt werden.

Die Überschriften werden mit dem Gleichheitszeichen (und Leerzeichen) eingeleitet. Das ist also so ähnlich wie bei Markdown, wo es Kreuzchen (#) sind. Die Anzahl der Kreuze oder Gleichheitszeichen bestimmt dabei die Anzahl der Ebene:

= Hauptüberschrift
== Unterüberschrift 2. Ebene
=== Unterüberschrift 3. Ebene usw.

Die Überschriften werden ohne Formatierungsanweisungen in Fettschrift und unnumeriert ausgegeben. Um das anzupassen, stellt man dem Dokument weitere Anweisungen voran:

// hiermit erhalten Überschriften eine Numerierung in der Form …
#set heading(numbering: "1.")
// hiermit wird das Gewicht der Überschrift auf "normal"
// gesetzt, d.h. sie sind nicht mehr fett:
#show heading: set text(weight: "regular")
// hiermit wird über und unter der Überschrift etwas 
// Platz zum umgebenden Text geschaffen:
#show heading: set block(above: 1.4em, below: 1em)

Zuletzt noch zwei weitere nützliche Anweisungen:

// dies definiert die Schriftart und Farbe ("maroon") 
// des unformatierten Textes (Code-Umgebungen)
#show raw: set text(maroon, font: "JetBrains Mono")
// dies setzt Links auf eine blaue Farbe, damit sie 
// sichtbar sind:
#show link: set text(blue)

Dann endlich kann der Dokumentinhalt folgen. Ein fertiges Beispieldokument mit weiteren Anweisungen stelle ich zum Download bereit:

Download
Vorlage für ein Standard-Typst-Dokument
Typst-Vorlage.zip
Komprimiertes Archiv im ZIP Format 333.2 KB

Vorteile gegenüber TeX

Welche Vorteile ergeben sich nun gegenüber TeX?

  • Die Syntax ist ausgesprochen einfach und "sprechend", ähnlich Markdown (Beispiele siehe unten). Das macht es für Anfänger verlockend, sich mit dieser Art Textsatzsystem zu beschäftigen. Im Zweifel entfällt sogar das Einrichten einer großen und komplizierten Präambel: Direkt eingegeben Wörter und Sätze werden bereits zu einem Typst-Dokument gesetzt. Der Quellcode ist durch die verkürzte Syntax auch übersichtlicher und kürzer.
  • Das gesamte Ökosystem wirkt wie "aus einem Guß" (ähnlich ConTeXt). Zwar gibt es Drittpakete, die man einbinden kann, aber insgesamt sind viel weniger Komplikationen zwischen Paketen zu erwarten, aus denen man Funktionen und Makros verwendet. Wo man bei TeX Sonderpakete einbinden muß, um beispielsweise Sonderzeichen zu erzeugen, ist das in Typst bereits alles enthalten!
  • Das Kompilieren (Setzen) des Dokuments geschieht quasi "in-situ", d.h. bereits beim Tippen sieht man im Vorschau-Fenster (meist zweigeteilte Typst-Editoren) sofort das Ergebnis. Das ist kein Vergleich zu einem TeX-Dokument, wo man das Kompilieren (ggf. mehrfach) anstößt und es einige Sekunden dauert, bis man das Ergebnis wahrnimmt. Auf diese Weise läßt sich zügig arbeiten.
  • Typst benötigt keine riesige Distribution mit hunderten Paketen. Wer lokal auf dem Desktop arbeitet, installiert sich einen Editor und kann sofort loslegen (Flatpak: ca. 50 MB, portable-Win: ca. 30 MB). Beispielsweise ist im Editor Katvan alles enthalten, was man braucht. Die Installation einer Extra-Paketesammlung entfällt.
  • Syntax-Fehler müssen im Dokument sofort behoben werden, sondern wird keine Ausgabe erzeugt. Fehlende Klammern oder unverständliche Befehle werden im Quellcode und im Log hervorgehoben. Das zwingt den Anwender dazu, sich sogleich mit dem Problem zu beschäftigen, als im Nachgang (TeX) auf Fehlersuche zu gehen.
  • Mit Verwendung von Typst endet die leidige Wahl zwischen pdfLaTeX, XeTeX und LuaTeX (und was es sonst für Abwandlungen gibt). Jedes dieser Programme hat nämlich seine Eigenheiten und speziellen Befehle, die mit den anderen inkompatibel sind.
  • Unicode-Zeichen können jederzeit direkt eingegeben werden. Das ist ein großer (und moderner) Fortschritt gegenüber pdfLaTeX, wo das nur über Umwege und nicht immer erfolgreich möglich ist.
  • Während des Kompilierens werden nicht mehr ein halbes Dutzend Metadaten erzeugt, die das Verzeichnis zumüllen.

Beispiele für vereinfachte Syntax

Listenumgebungen werden unter TeX traditionell in eine itemize- oder enumerate-Umgebung eingezäunt; jeder Anführungspunkt (oder Nummer) wird dann mit \item eingeleitet. Das ist in seiner verschachtelten Komplexität schon kurz vor HTML! Außerdem muß man peinlich genau darauf achten, die geöffneten Umgebungen wieder ordentlich zu schließen – Editor-Automatismen helfen dabei. Mit Typst reicht es (wie bei Markdown), jedem Anführungspunkt einen Bindestrich, oder jedem Nummernpunkt ein Plus voranzustellen.

Die Eingabe wörtlicher Rede ist mit Typst viel einfacher: Zwar gibt es auch unter TeX Pakete für eine erleichterte Eingabe (z.B. enquote, siehe Abbildung), aber was ist einfacher als vorne und hinten je ein doppeltes ASCII-Anführungszeichen zu setzen? In der Typst-Präambel wird dann je nach Dokumentsprache und Einstellung geregelt, ob daraus (im Deutschen gebräuchliche) Gänsefüßchen oder Guillemets werden.

Auch das Setzen von Formeln ist mit Typst vereinfacht und "sprechender". In beiden Fällen (Typst und LaTeX) werden Formeln in Dollar-Zeichen eingefaßt. Inline-Formeln werden ohne Leerzeichen gesetzt ($1 / 2$), während abgesetzte Formeln noch ein Leerzeichen zum Inhalt erwarten: $ 1 / 2 $

$ 2 pi dot r^2 = 4 Sigma $
$ x < y => x gt.eq.not y $

Umgang mit Schriftarten

Persönlich finde ich die Festlegung von Schriftarten recht elegant gelöst. Es lassen sich System- und Drittschriftarten einfach durch ihren Namen angeben, und auch Open-Type-Features (z.B. hlig für besondere Ligaturen oder verschiedene Style Sets) können angesprochen werden.

Manchmal jedoch werden Systemschriftarten vom Typst-Editor nicht erkannt (obwohl sie ganz sicher installiert sind!). In diesem Fall wechselt man (zumindest auf GNU/Linus) vom Editor ins Terminal und kompiliert manuell:

typst compile --font-path=/home/user/.fonts/ Datei.typ Datei.pdf

Relative Pfade

Typst versteht beim Verweis auf externe Dateien (eingebundene Vorlagen oder Bild-Dateien in figure-Umgebungen) ausschließlich relative Pfade, d.h. das Wurzelverzeichnis ist immer dort, wo der Typst-Quellcode liegt. Wer also auf entfernte (lokale) Dateien im Dateisystem verweisen möchte, muß ggf. lange und komplizierte Pfadanweisungen geben, z.B.

#figure(image("../../../../images/Bild.jpg"),)

Liegt die Bilddatei direkt im Quellcode-Verzeichnis, genügt dagegen:

#figure(image("Bild.jpg"),)

Vergleich der Textsatzqualität

Für einen Vergleich der Satzqualität wurde derselbe Text unter denselben Bedingungen einmal mit LaTeX, einmal mit Typst und einmal mit LibreOffice Writer gesetzt. Der Text ist jeweils 11pt groß und aus der Libertine gesetzt. Die Seitenränder betragen rechts und links je 2 cm, bei einem Seitenformat von A5.

Abb. 2: Vergleich desselben Textblocks, erzeugt unter LaTeX (links), Typst (mittig) und LibreOffice Writer (rechts).

Die Satzqualität ist allgemein in Ordnung, sticht bei LaTeX aber positiv heraus: Der Satz gelingt so eng, daß er sich auf nur 15 Zeilen verteilt, während er sich bei den anderen beiden Programmen auf je 16 Zeilen erstreckt. Typst setzt dabei etwas enger, während bei LibreOffice Writer hier und da unangenehme Lücken zu sehen sind (Ursache in Abb. 3 sichtbar).

Abb. 3: Typographie im Detail: Typst setzt den Text mit sog. optischem Randausgleich (Bindestriche ragen in den weißen Seitenrand hinein), LibreOffice Writer setzt ohne optischen Randausgleich, d.h. die Trennstriche schließen mit den sonstigen Buchstaben bündig ab.

 

Beim optischen Randausgleich werden Trennstriche minimal verschoben, ohne daß das Auge eine unangenehme Störung des Blocksatzes wahrnimmt. Diese geringe Änderung führt aber zu etwas mehr "Spielraum" beim Verteilen der Buchstaben, so daß der Umbruch ggf. besser aussehen kann.

 

Der Satz mit LaTeX erfolgt selbstverständlich auch mit optischem Randausgleich (im Vergleichsbild hier links aber nicht dargestellt).

Geht es also um Satzqualität, eventuell auch um eine möglichst geringe Anzahl an Seiten unter denselben Bedingungen, ist der Satz mit LaTeX nach wie vor erste Wahl. Der Abstand zwischen Typst und TeX ist aber nicht mehr allzu groß, und die viel einfachere Syntax ist eine verlockende Sache.

Eine .bib-Literaturdatenbank läßt sich ebenfalls anbinden, und im Dokument selbst können mit entsprechender Syntax Zitate erzeugt werden.

Vorteile gegenüber HTML oder Markdown

Markdown und HTML eignen sich hervorragend zum Setzen reiner Bildschirm-Dokumente (Onscreen, Webseiten etc.), z.B. auch für dynamische Handbücher und begleitende Erläuterungen, Tutorials usw. Welche Vorzüge gibt es nun gegenüber HTML oder Standard-Markdown?

Es gibt mehrere. Die folgenden Möglichkeiten sind bei HTML und Standard-Markdown NICHT oder nur auf Umwegen gegeben:

  • Inhaltsverzeichnisse
  • automatisch numerierte Überschriften
  • Seitenzahlen
  • Fußnoten
  • Verlinkung von Abbildungs- und Überschriftennummern
  • Blocksatz mit einem Wortumbruch-Algorithmus
  • Bibliographie (Anbindung einer Literaturdatenbank, Setzen von Zitaten)

Das sind wenige, aber erhebliche Argumente für einen angenehmen Textsatz!

Gegenüber HTML ist Typst-Code VIEL kürzer und übersichtlicher. Auch das Anbinden einer separaten CSS-Datei für die Formatierungen entfällt. Gleichwohl könnte man auch bei Typst alle Formatierungsanweisungen in eine separate Vorlagen-Datei auslagern, um sie für andere Dokumente nutzbar zu machen. Auch das Definieren von Links (auf URLs oder lokale Dateien) finde ich bei Typst übersichtlicher und einprägsamer als bei HTML oder Markdown.

Ausblick

Typst ist ein junges Projekt und befindet sich in stetiger Weiterentwicklung. Es muß erst noch beweisen, daß es mit den großen Brüdern mithalten kann. Der erste Eindruck ist – vielversprechend!