254 lines
11 KiB
Markdown
254 lines
11 KiB
Markdown
---
|
||
Title: Typesetting with Typst
|
||
Date: 2024-10-19 18:00
|
||
Modified: 2024-10-19 21:00
|
||
Lang: en
|
||
Author: Fabrice
|
||
Category: software
|
||
Tags: vim, neovim, typst
|
||
Slug: typst-intro
|
||
table-of-contents: true
|
||
Summary: An overview of Typst for simple usage.
|
||
Header_Cover: ../images/covers/printing-press.jpg
|
||
---
|
||
|
||
For about ten years now, I’ve been using _LaTeX_ to typeset any document which
|
||
aims to be printed. The main reason is that I’m quite familiar with the syntax
|
||
to adjust the page setting to what I imagine. Other solutions exist to ease this
|
||
workflow, such as [Pandoc](https://pandoc.org/) to convert easier to write syntax to
|
||
other formats. However, this solution was not palatable to me as the universal
|
||
aspect of Pandoc, makes it a pain to specify pagination properties. And, to
|
||
produce a PDF in the end, Pandoc calls _LaTeX_, and for the sake of simplicity I
|
||
prefer to directly write in _LaTeX_ (see the conclusion for clarification).
|
||
|
||
However, for some kind of documents that I don’t write very often, such as
|
||
letters, it’s sometimes a pain to find the syntax of the [LaTeX class for
|
||
letters](https://texlive.mycozy.space/macros/latex/contrib/lettre/lettre.pdf)<sup>(fr)</sup>
|
||
I use. Recently, I had to write small documents (approx 3 pages), with a
|
||
bibliography, and that just needed to have a nice and neat presentation. Before
|
||
going farther, I decided to give a try to [typst](https://typst.app/). It is an
|
||
open-source typesetting engine that is written in
|
||
[rust](https://rust-lang.org/), that promotes modern features such as
|
||
_incremental compilation_, and a scripting language that is actually readable by
|
||
humans. Moreover, the markup language is clean, and as in
|
||
[markdown] or [asciidoc], it can be read from the source (without a
|
||
[concealer](https://alok.github.io/2018/04/26/using-vim-s-conceal-to-make-languages-more-tolerable/))
|
||
to have an idea of the typeset text before compiling it.
|
||
|
||
|
||
The project is still in development and some features may break before the first
|
||
major version is out. However, to quickly generate a document, it can be a good
|
||
idea to consider. Also, please note that there is no native output from Typst to
|
||
HTML. However, Pandoc can read and write `.typ` files, so it’s an alternative
|
||
worth considering given that native LaTeX is **not** easy to write for that
|
||
purpose.
|
||
|
||
In the following, it will be a quick overview of the features that I find nice
|
||
in Typst. Please don’t expect an in-depth review, I only used it for a couple of
|
||
opportunities.
|
||
|
||
# Syntax
|
||
|
||
To illustrate Typst, here follows a simple document, with its corresponding [compiled
|
||
version]({static}/examples/typst-example.pdf).
|
||
|
||
```typst
|
||
/* Set some variables for the authors and the title */
|
||
#let title = [How to type in Typst]
|
||
#let authors = ("Fabrice Mouhartem", )
|
||
|
||
/* Set some document properties:
|
||
* - Numbering of sections (default: none)
|
||
* - PDF properties (it does not print anything) */
|
||
#set heading(numbering: "I.")
|
||
#set document(title: title, author: authors)
|
||
|
||
/* Now we can print the title and the authors */
|
||
#align(center, text(size: 17pt, strong(title)))
|
||
#for author in authors { // TODO: would be better in a grid
|
||
align(center, text(author))
|
||
}
|
||
|
||
/* Table of contents */
|
||
#outline()
|
||
|
||
/* To define a section */
|
||
= Introduction
|
||
/* And to write the content: */
|
||
To _type_ in Typst, you just have to… *type*.
|
||
|
||
= Conclusion
|
||
See, it was #strike[hard] easy.
|
||
```
|
||
|
||
Besides the programmatic part at the start, we can see that the syntax is close
|
||
to what we may know in other simple markup languages such as [markdown] or
|
||
[asciidoc]. However, it is its own and Typst [doesn’t
|
||
plan](https://github.com/typst/typst/discussions/2498) to converge toward
|
||
another markup language, especially knowing that the markdown syntax is
|
||
[ambiguous](https://roopc.net/posts/2014/markdown-cfg/).
|
||
|
||
For the preamble of the file, it can be deferred to another file to accentuate
|
||
the separation between content and typesetting. We won’t go into details, but it
|
||
was mostly there to illustrate some parts of the language, such as variable
|
||
declaration (`#let …`) or loops over arrays (`#for … in …`). We also set some
|
||
values about the document using either static values (for the numbering) or the
|
||
defined variables (authors and title options).
|
||
|
||
Let us now check that these options are indeed well set:
|
||
```bash
|
||
❯ pdfinfo "typst-example.pdf" | head -n 3
|
||
Title: How to type in Typst
|
||
Author: Fabrice Mouhartem
|
||
Creator: Typst 0.12.0
|
||
```
|
||
|
||
The generated document is a bit bare, but we can easily change it, and as easily
|
||
create a template to automate this work for us.
|
||
|
||
# Example: a letter (the French way)
|
||
|
||
For a simple example, I’ll take the letter one, for which I wrote a simple
|
||
template to generate them. The template is available in [this
|
||
repository](https://git.epheme.re/fmouhart/typst-lettre). The main issue I had
|
||
is that the French way of doing letters revert the order of the addresses of the
|
||
sender and recipient are… reverted compared to the English style.
|
||
|
||
Let us dig in what it does by looking at the example file.
|
||
|
||
First thing first, the file is loading the template from `lettre.typ`. This file
|
||
defines the typesetting and the paginations properties, and provide an
|
||
initialisation function to define the different headers, which you can look into
|
||
if you feel curious. If you find it a bit unbearable, you can create a new file
|
||
`preamble.typ` to hide everything, and include it with `#include "preamble.typ"`
|
||
at the outset of the file.
|
||
|
||
```typst
|
||
#import "lettre.typ": *
|
||
|
||
#show: doc => lettre(
|
||
de: [
|
||
Sender\
|
||
Address
|
||
],
|
||
pour: [
|
||
Recipient\
|
||
Address
|
||
],
|
||
objet: "subject of the letter", // optional
|
||
date: "date of sending", // optional
|
||
lieu: "location",
|
||
introduction: "opening",
|
||
cloture: "closing",
|
||
signature: "signature",
|
||
post: [
|
||
post-letter (e.g., post-scriptum)
|
||
],
|
||
doc
|
||
)
|
||
```
|
||
|
||
This will generate the template with the elements where they should be, in a
|
||
very simple fashion. Now, we just have to write the content of the letter and
|
||
have a `pdf` file pretty easily with `typst compile` without all the files that
|
||
_LaTeX_ generates for us. As a bonus, it also set some PDFs metadata from the
|
||
input variables.
|
||
|
||
# Bibliography
|
||
|
||
Another nice feature is that Typst embeds a bibliography engine, that is
|
||
compatible with the bibtex format. Meaning that I don’t have to change the way I
|
||
manage my bibliography or directly use [community-managed
|
||
bibliography](https://cryptobib.di.ens.fr/).
|
||
|
||
For that you simply have to call the bibliography function where you want it to be generated:
|
||
|
||
```typst
|
||
#bibliography("bibliography.bib", title: "References", style: "springer-basic")
|
||
```
|
||
|
||
And cite the references you want with the `@bibkey` syntax (note that it’s the
|
||
same syntax for cross-referencing) or the `#cite` function. Note that if you
|
||
have a `+` in your bibliography key, the label won’t be recognized. It is my
|
||
case as my bibkeys are in the _alpha_ style with the initials of the authors +
|
||
year up to 3 names, and a `+` afterward… To be able to cite the reference
|
||
anyway, just do `#cite(label("bib+key"))`.
|
||
|
||
The full list of natively available style is given in the [Typst
|
||
documentation](https://typst.app/docs/reference/model/bibliography/#parameters-style),
|
||
however you can define your own in the [Citation Style
|
||
Language](https://citationstyles.org/). Meaning that you can pick the best one
|
||
for your usage in the [CSL
|
||
repository](https://github.com/citation-style-language/styles).
|
||
|
||
To put multiple citations (as in `\cite{ref1, ref2}` in _LaTeX_), you just have
|
||
to concatenate them, like `@ref1 @ref2`. If the citation style supports it, it would automatically
|
||
merge them under the same bracket (however, it’s not the case for all citation
|
||
styles).
|
||
|
||
# Tooling
|
||
|
||
Unlike my [blogpost about using nvim for LaTeX]({filename}./nvim-latex.md),
|
||
it’s pretty much easier here.
|
||
|
||
I just added the [`typst.vim`](https://github.com/kaarmu/typst.vim) plugin to
|
||
_neovim_, added a binding for the `:TypstWatch` command and that’s basically
|
||
all. It is possible to set the `g:typst_pdf_viewer` (`vim.g.typst_pdf_viewer` in
|
||
Lua) global variable as well if you want to have a different default PDF viewer
|
||
for your system and for edition.
|
||
|
||
Now, each time I save, the document is incrementally compiled (I think) and
|
||
updated in my PDF viewer.
|
||
|
||
I tried using typst language servers as well, but they don’t seem mature enough
|
||
yet. In the end, the `typst.vim` plugin suffices to my needs without being too
|
||
nosy.
|
||
|
||
Hopefully, the tooling will get better with time.
|
||
|
||
# Conclusion
|
||
|
||
For simple document typesetting, even with features such as bibliography,
|
||
cross-referencing, and table of contents, Typst seems to be a good choice.
|
||
However, for long-term support documents, such as documentation, I would wait to
|
||
see it being more stable. Even while writing this blog post, the _lettre_
|
||
template I made was done in Typst 0.11, and preparing it in a repository raised
|
||
some warnings about [breaking changes from
|
||
0.12](https://typst.app/docs/changelog/0.12.0/) which has been published…
|
||
[yesterday](https://typst.app/blog/2024/typst-0.12/) (at the time of writing):
|
||
|
||
> Added
|
||
> [`par.spacing`](https://typst.app/docs/reference/model/par/#parameters-spacing
|
||
> "Typst Documentation: paragraph spacing") property for configuring paragraph
|
||
> spacing. This should now be used instead of `show par: set block(spacing: ..)`
|
||
> **(Breaking change)**
|
||
|
||
Which also leads me to say that one other advantage of Typst is… the readability of
|
||
error messages. They are way much cleaner than the ones from _LaTeX_. Leading to
|
||
easier debugging as well. I, however, can’t say for sure as I didn’t typeset big
|
||
documents using Typst yet (which is unlikely to happen given my stance so far,
|
||
but who knows…).
|
||
|
||
Finally, to complete the note about compiling in _LaTeX_ from Pandoc in the
|
||
introduction of this blogpost… I’m apparently not up to date. For the sake of
|
||
transparency, it is possible to use different PDF engines with Pandoc according
|
||
to the [documentation](https://pandoc.org/MANUAL.html#option--pdf-engine). I
|
||
didn’t try them yet, so I can’t provide feedbacks about them. Note that Typst is
|
||
part of the PDF generators, as well as other nice typesetting projects such as
|
||
[pagedjs](https://pagedjs.org/) that aims at paginating HTML sources to have
|
||
great web page and print-ready PDFs. However, the argument about avoiding
|
||
intermediate steps if possible still holds (moreover when the syntax of Typst is
|
||
already clean enough).
|
||
|
||
## See Also
|
||
|
||
- [Awesome Typst](https://github.com/qjcg/awesome-typst): a repository listing
|
||
useful links for typst users.
|
||
- [Typst for _LaTeX_ users](https://typst.app/docs/guides/guide-for-latex-users/
|
||
"Typst documentation: guide for LaTeX users"): a comprehensive guide for typst
|
||
for _LaTeX_ users.
|
||
|
||
[markdown]: https://daringfireball.net/projects/markdown/
|
||
[asciidoc]: https://asciidoc.org/
|
||
|