Drop #357 (2023-10-20): Weekend Project Edition

Touch Typst-ing

We covered Typst back in March, but the team behind Typst has been super busy, as has the Quarto team. If you’re willing to run the bleeding edge of Quarto, they’ve assimilated the Typst binary into the Quarto CLI and have nascent Qmd support for it. This is possible because the venerable Pandoc added Typst support back in March.

You can see what Pandoc does under the hood with Typst by default by going here — https://pandoc.org/try/, entering #lorem(300) (which makes 300 words of lorem ipsum) into the input box, and selecting typst for both input and output.

The base Quarto docs for Typst are pretty decent, but nothing beats some examples and hands-on experimentation.

So, I’m going to (lightly) walk folks through the creation of a Quarto Typst template extension and challenge y’all to extend them or create your own for this week’s WPE.

You can find all the support files over at GitLab.

Quarto Template Extensions Redux

gray scissor with envelope and pencils

There is nothing fancy or scary about a Quarto extension. They’re just a set of (required) files in a pre-determined directory structure. For our custom Typst Quarto template extensions, this is the directory structure:

blank
├ _extensions
│ └── blank <================= This will be the template base name
│   ├── _extension.yml <====== Template metadata
│   ├── template.typ <======== A "vanilla" pandoc Typst template
│   ├── typst-show.typ <====== A "parameters"/"setup" Typst template
│   └── typst-template.typ <== The actual document template
└ template.qmd <============== Example Quarto Typst Qmd

The default Typst Quarto template has support for more academic-setting tailored bits that aren’t always needed.

This is what is in _extension.yml:

title: Blank
author: hrbrmstr
version: 0.1.0
quarto-required: ">=1.4.429"
contributes:
  formats:
    typst:
      template: template.typ
      template-partials:
        - typst-template.typ
        - typst-show.typ

It provides some basic metadata for Quarto, including what it needs to include when compiling the document.

This is what is in template.typ:

$definitions.typ()$

$typst-template.typ()$

$typst-show.typ()$

$for(header-includes)$
$header-includes$
$endfor$

$for(include-before)$
$include-before$
$endfor$

$body$

$for(include-after)$
$include-after$
$endfor$

You can see the order in which the partials are loaded. This is what I’d recommend as the bare minimum, but you should experiment to see what removing various lines does.

Things start getting interesting in typst-show.typ:

#show: doc => article(
$if(margin)$
  margin: ($for(margin/pairs)$$margin.key$: $margin.value$,$endfor$),
$endif$
$if(papersize)$
  paper: "$papersize$",
$endif$
  doc
)

The #show is a show rule. Show rules re-define how Typst elements are displayed. The doc is the content from the pre-processed Quarto doc (after all chunks are executed) and it’s calling the article() function we’re defining in typst-template.typ. That function has slots for specifying a margin, paper size, and the body (doc) contents.

The ugly $ bits are for pandoc processing.

The typst-template.typ is fairly lean:

#let article(
  margin: (x: 1.25in, y: 1.25in),
  paper: "us-letter",
  lang: "en",
  region: "US",
  doc
) = {

  set page(
    paper: paper,
    margin: margin,
  )

  set text(
    lang: lang,
    region: region,
  )

  doc
}

We define our article function with some sensible defaults, set up the page and default text styling, and include the pre-preprocessed document.

To use this template, we can create a new project with:

$ quarto create-project base-test
$ cd base-test
$ quarto add ../base

I unimaginatively named the lean base test Qmd file: base-test.qmd. It’s just the default Quarto document with our format:

---
format:
  blank-typst: 
    keep-typ: true
---

## Quarto

Quarto enables you to weave together content and executable
code into a finished document. To learn more about Quarto 
see <https://quarto.org>.

That builds a full 8.5×11-inch page with this up top:

I like keeping keep-typ set to true to see how the sausage is made.

Getting Fancy

To show that neither Quarto nor Typst-ified Quarto is R-centric, I made blank-deno.qmd that uses this base template and the Deno Jupyter kernel we looked at last week, plus some fonts featured a while back.

It sets a document-wide background color and uses the Deno kernel to crank out an Observable Plot SVG inside the document:

To show I still 💙 R — and. because I need to write some Quarto support code for getting raw, dynamic text/markup output from Deno typescript blocks — I also made blank-r.qmd which shows how to use some in-document Typst blocks, and adds a {ggplot2} plot, plus a {gt} table for good measure.

The repo also contains another example extension that has more parameters that let you set a title and document footer.

FIN

This should be a pretty solid foundation to expand on. We’re going to be using Quarto + Typst for some PDF reporting at $WORK, so expect to see a few more Quart+Typst featurettes over the coming months. ☮️

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.