ExTypst - Elixir bindings for the Typst typesetting system

Hello! This weekend I’ve discovered the Typst typesetting system and decided to create the necessary elixir bindings to use it.

The source code and examples can be found in this repository, and the library is already available in Hex under the name ex_typst.

I think there’s space for some awesome projects using it, like generating reports in web applications or creating collaborative writing applications.

If you have any questions, feel free to comment in this thread.

21 Likes

As a long-time LaTeX user, I was secretly pleased with myself, shelling out from Elixir to do elaborate typesetting and bringing it back. I am blown away by what the Typst project and ExTypst could do together.

I’m still exploring the setup, but I feel that this could also go back towards Elixir documentation (some kind of mix task), or enhancing some of the CMS (OrangeCMS, Phoenix Pages, Beacon, Nimble Publisher) to auto-generate PDF (would need some markdown → typst conversion).

3 Likes

If you’re exploring the space of integration with existing Elixir tooling, check out:

3 Likes

Thanks for the library. I’m having trouble showing images in produced PDFs from either external paths (“https://…”) or internal paths. Do we need to have a way to set TYPST_ROOT? By default, when using the command line version, paths need to be either relative to the current file or relative to the compiled file. So I’m not sure how to reference an image using your library. Perhaps the example could be extended to show different ways to reference images.

So, answering my own question, you have to explicitly prefix your static images with, for example, priv/static/img/. And external images are explicitly not allowed by Tryst. For example, it will convert the double slashes in a URL to single slashes before reporting a file not found error; for example: http:/localhost:4000/.

As someone with a passing familiarity with Makeup, I believe this should be very easy. But I guess this would only make sense if you also implemented a typst backend for one of Elixir’s markdown implementations (which is probably a bit harder).

If I were to do it, I’d generate HTML from markdown and then use an HTML parsing library (floki, for example) to get an HTML parse tree and convert that into Typst.

I’m quite excited about being able to use Typst as a backend for an Elixir plotting library. Tpst has all the low level goodness you need to properly render, size and rearrange arbitrary blobs of content (with support for rich text and math) according to the measured sizes.

I’m currently writing the Typst “backend”, and Typst is actually very easy to write and quite powerful.

1 Like

Would it be possible to support SVG and bitmap (PNG?) output too? If one wants to generate individual figures with Typst (as opposed to complete documents), those formats are useful when publishing on the web or working with certain publishers.

Typst is pretty nice and useful, but I still found it was hard to incorporate into existing TeX based workflows.

The older “Tectonic typesetting” project aims to basically continue the legacy of things like latexmk, and provides a lot of the same features Typst provides, but for plain-ol Tex

1 Like

You’re not supposed to integrate them at all. They are alternative typesetting systems. You’re supposed to commit to one or the other

Here it is: Quartz (previously Playfair) - Data Visualization Library (aimed at publication, not interactive display)

1 Like

I am wondering: in the example in the repo, what if we fetch data from a database and an employee decided to put typst markup into their name - would we need something like Phoenix.HTML.Safe for ex_typst?

A brief look at the code does not seem like there’s any escaping done currently.

Indeed, currently escaping is not implemented into ex_typst. I’ll see about implementing it in the future, as it’s something I don’t want to rush and end up with a poor implementation. But in the mean time pull requests for it would also be very welcome :slight_smile:

1 Like

According to the Typst docs and my experiments, a “naked string” cam be used in all the same places as content, and results in the literal contents of the string being inserted in the document. Effectively, naked strings escape the content.

@viniciusmuller would you be interested in adding some functionality to generate some kind of Typst AST (or at least an approximation of it) and some functions that could serialize that AST into typst code and convert Elixir values into said AST?

Yes, that would be really nice. That was the initial idea, I ended up just implementing compiling from raw strings because at time typst’s syntax seemed very flexible and I wouldn’t be able to model all of it into the library. But I think it would be ok to start adding this support gradually, as it makes the library much easier to use.

I experimented with a protocol similar to Phoenix.HTML.Safe in Add ExTypst.Safe protocol by SteffenDE · Pull Request #2 · viniciusmuller/ex_typst · GitHub. This basically wraps any content in quotes by default, unless one uses <%= ExTypst.raw(my_content) %> in the template.

Hello Everyone, i hope you are doing fine!

I’ve added ExTypst to my application but running into the following compilation error

** (ErlangError) Erlang error: :enoent
    (elixir 1.15.4) lib/system.ex:1092: System.cmd("cargo", ["metadata", "--format-version=1"], [cd: "native/extypst_nif"])
    (rustler 0.28.0) lib/rustler/compiler/config.ex:83: Rustler.Compiler.Config.metadata!/1
    (rustler 0.28.0) lib/rustler/compiler/config.ex:70: Rustler.Compiler.Config.build/1
    (rustler 0.28.0) lib/rustler/compiler.ex:9: Rustler.Compiler.compile_crate/2
    lib/ex_typst_nif.ex:4: (module)

I am using this Elixir and Erlang versions:

Erlang/OTP 26 [erts-14.0.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit] [dtrace]
Elixir 1.15.4 (compiled with Erlang/OTP 26)

and this version of Phoenix:

Phoenix installer v1.7.3

I am new to this whole ecosystem and tbh i have no clue where to start, to tackle this error message. But i am more than happy to assist and provide any information needed to solve this :slight_smile: Thanks!

Edit:

I’ve run the commands mix deps.compile ex_typst --force, mix deps.update ex_typst and mix deps.clean ex_typst but without luck. mix is not able to compile the package.

You need to have Rust installed on your system, see: Install Rust - Rust Programming Language

Cargo (what the error says it cannot find) is the Rust build tool.

In the future ex_typst could probably use rustler_precompiled, then this wouldn’t be needed.

2 Likes

It is working now and i can generate PDFs :slight_smile: Thank you!