Can I configure my document (e.g. draft/release version, color theme) when creating a PDF without modifying the Typst file directly?

Basically, are there ways to to create multiple structurally similar PDFs from the same Typst document, by configuring it in some way? Use cases that come to mind:

  • draft version (with watermark, comments, …) vs. release version
  • different themes, e.g. light/dark, serif/sans
  • exam and solution sheets
  • slides, handout, and speaker notes
  • rendering different data, serial letter style

Is there a mechanism that lets one achieve that without having to modify the input Typst document itself?

2 Likes

You can use system.inputs (System Functions – Typst Documentation) to get the command-line inputs at compile time, and then check for the presence of specific inputs to define the document style in different ways.

There absolutely is: the sys.inputs dictionary contains values that have been set from the command line, via the --input key=value syntax. To my knowledge, the web app currently doesn’t have a way to put values into that dictionary, so be aware of that.

It’s often useful to have default values for these parameters, and check whether values are valid. Let’s say you want to assume --input theme=light and --input solutions=false, you could process the sys.inputs dictionary like this:

let theme = {
  let valid-values = ("light", "dark")
  let value = sys.inputs.at("theme", default: "light")
  assert(value in valid-values, message: "`--input theme` must be light or dark")
  value
}

let solutions = {
  let valid-values = ("true": true, "false": false)
  let value = sys.inputs.at("solutions", default: "false")
  assert(value in valid-values, message: "`--input solutions` must be true or false")
  valid-values.at(value)
}

Using this code, theme will be a string value (default "light") and solutions will be a boolean value (default false).

For more complex data input needs, using one of the data loading functions is probably the best idea:

  • directly in the command line: --input 'data={"some-num": 1, "some-bool": true}'
    then read via json.decode(sys.inputs.data)
  • in a separate file: --input 'file=data.json'
    then read via json(sys.inputs.file)
    For this to work, the file must be accessible to Typst, i.e. it must be in the Typst root directory. By default, that is the directory where the main Typst file you’re processing is located.

(JSON is of course just one option for a data format that can be read like this.)

6 Likes