A small Zig ⚡ module, as a convenience for me when writing WebAssembly plugins for Typst
Note
Initially based on the hello.zig example in wasm-minimal-protocol
You will want to have a fairly recent Zig as well as the Typst CLI
Important
I had to rustup default 1.79.0
when compiling the latest typst
as there were some breaking change in 1.80.0
Tip
Some of the software that I have installed for a pretty nice Typst workflow in Neovim:
Use zig fetch
to add a .typ
to the .dependencies
in your build.zig.zon
zig fetch --save https://github.com/peterhellberg/typ/archive/refs/tags/v0.0.9.tar.gz
Note
You should now be able to update your build.zig
as described below.
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.resolveTargetQuery(.{
.cpu_arch = .wasm32,
.os_tag = .freestanding,
});
const hello = b.addExecutable(.{
.name = "hello",
.root_source_file = b.path("hello.zig"),
.strip = true,
.target = target,
.optimize = .ReleaseSmall,
});
const typ = b.dependency("typ", .{}).module("typ");
hello.root_module.addImport("typ", typ);
hello.entry = .disabled;
hello.rdynamic = true;
b.installArtifact(hello);
}
const typ = @import("typ");
export fn hello() i32 {
const msg = "*Hello* from `hello.wasm` written in Zig!";
return typ.str(msg);
}
export fn echo(len: usize) i32 {
var res = typ.alloc(u8, len * 2) catch return 1;
defer typ.free(res);
typ.in(res.ptr);
for (0..len) |i| {
res[i + len] = res[i];
}
return typ.ok(res);
}
#set page(width: 10cm, height: 10cm)
#set text(font: "Inter")
== A WebAssembly plugin for Typst
#line(length: 100%)
#emph[Typst is capable of interfacing with plugins compiled to WebAssembly.]
#line(length: 100%)
#let p = plugin("zig-out/bin/hello.wasm")
#eval(str(p.hello()), mode: "markup")
#eval(str(p.echo(bytes("1+2"))), mode: "code")