A small Zig ⚡ module, as a convenience for me when writing WebAssembly plugins for Typst
Requirements
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
Usage
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.1.0.tar.gzNote
You should now be able to update your build.zig as described below.
build.zig
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_module = b.createModule(.{ .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); }
hello.zig
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.write(res.ptr); for (0..len) |i| { res[i + len] = res[i]; } return typ.ok(res); }
hello.typ
#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")
