Colored Text, Two Outputs, One Filter

Guten Tag! šŸ‘‹ 

Many greetings from Munich, Germany. First off, a big thank you to everyone who has already grabbed a seat for the workshop ā¤ļø

But I know a lot of you are still deciding. And honestly, that’s fair. So far I’ve mostly talked about ideas: branding, dual outputs, the Lua filter pattern. That’s all still pretty abstract.

So let me make it specific with something small. If you’ve been paying attention to my previous mails then you know that the Quarto extension we’re building allows Quarto code like this:

The Fund continues to maintain a [low-risk strategy]{.text-primary}

That {.text-primary} bit is a span class. On the HTML side, plain CSS just colors that text in the brand’s primary color. Nothing too fancy there.

On the Typst PDF side, there’s no built-in concept of ā€œcolor this span using my brand colorā€. So a small Lua filter step

  • catches any span marked .text-primary or .text-muted,

  • converts its contents to real Typst syntax, and

  • wraps it in a call to a small Typst function.

And it’s this latter Typst function that knows how to apply the right color. That’s how you get the output you want.

That’s a small taste of the pattern I walked through a couple of emails ago. Don’t remember that? Well, let me remind you. The idea was a three step process:

  • A Lua filter finds the marked content

  • That content is modified as little as possible and then handed off to Typst

  • A Typst function does the actual styling

Let’s go over the actual Lua code.

Target the right content

First, you specify the color classes and a filter for span elements.

Then, you will have to iterate over all your color classes that you specified. After all, you don’t know which one might be attached to your span element.

Inside that iteration, you can run a simply check on the classes of the element. Basically you ask ā€œDid Quarto attach one of the color classes to the inline elementā€?

Modify the content as little as possible

And once you’e established that you’re currently with one of the desired inline elements, you ideally use the content of the element with el.content.

But Pandoc does not like that, so you use a little helper function (here not shown) to wrap this into a format that Pandoc likes. That’s a technical hiccup that’s best shown live and hard to describe in an email.

But once you have the content body, you pass that off to Typst by filling a Typst function called colored-text with arguments that your Lua filter extracted for you.

Pass that off to a Typst function

This Typst function is defined in your Typst template and then takes care of the actual rendering.

It’s a small example, but it’s the same shape you’ll see again and again once you know what to look for. Doesn’t matter if it’s coloring text, wrapping a table, or laying out a header. The pattern is the same.

If that’s the kind of thing you want to learn about with the full BIRD Investment demo document, you can grab a seat here:

This 3-hour live workshop teaches you how to build branded, dual-output Quarto documents (HTML and PDF) using Typst, Lua filters, and a reusable Quarto extension.

And if this preview leaves you with questions, don’t hesitate to hit reply. I’d rather answer them now than have you sit on the fence.

Best,
Albert

Whenever you’re ready, there are three I can help you:

  1. Automate Your Data Reports: This course helps data analysts eliminate manual copy-paste reporting by automating PDF reports end-to-end, saving hours every cycle and preventing costly mistakes. (Using the lovely Typst language šŸ˜)

  2. Generate Insights in Minutes, not Hours: This comprehensive course teaches you to handle data faster, smarter, and more efficiently.

  3. Bespoke Data Science Solutions: I’ve helped clients build their own data science solutions. Whether building custom web apps, PDF reports, AI automations or teaching workshops, I’ve got you covered. You can reach out to me via this form (or simply hit reply to this email)

Reply

or to participate.