この記事は、Zennにも投稿しています。
最近なんだか話題ですね、Typst。その簡潔な構文や環境構築の容易さが注目されているのだと思います。
そんなTypstですが、プラグインシステムを備えており、WASMを使って拡張することが可能です。
そんなTypstですが、プラグインシステムを備えており、WASMを使って拡張することが可能です。
Plugin Type – Typst Documentation
Documentation for the Plugin type.
typst.app
公式のパッケージリストに掲載されているパッケージの中にも内部でWASMプラグインを使用しているものが既に多々あります。例えばQuickJSを利用してJavaScriptを実行する「Jogs」やMarkdownをTypstに変換する「cmarker」、さらにはLaTeXをTypst構文に変換して表示する(!)「mitex」なんていうものもあります。
この記事ではRustを使ってTypstのプラグインを作成します。Typst自体もRustで作られているためRustの環境がよく整備されていますが、もちろんWASMにコンパイルできる言語であればどのような言語も使用可能です。ただし、WASIはサポートされていないため、WASIが必須な言語やライブラリを使用する際にはwasi-stubを使用する必要があります。
ZigとCの例がここにある他、その他の言語でもTypstのwasm protocolに従って関数をエクスポートすることでTypstプラグインを作成できます。
基本的なRustの知識があることを前提にしています。
プラグインとパッケージ
Typstでのプラグインというのは
wasm
ファイルのことを指します。一方、パッケージはプラグインをロードする処理などが記述されたtyp
ファイルなどを含んだ一連のファイル群のことを指します。パッケージはwasm
ファイルを含んでいる必要はありません。Greetプラグイン
まずは
Hello {name}
という文字列を出力するだけのプラグインを作ります。を実行してRustのプロジェクトを作り、wasmにビルドできるようにしておきましょう。
次に
次に
Cargo.toml
に以下を追記します。crate-type = ["cdylib"]
はwasmにビルドするのに必要です。また、wasm-minimal-protocol
クレートでは、関数を先述したプロトコルに合うように変換するマクロを提供してくれています。また、
.cargo/config.toml
ファイルを作成し、デフォルトでwasmがコンパイルされるようにしておきます。次に
lib.rs
を以下のように書き換えます。initiate_protocol!()
を実行した後、wasm_func
アノテーションを関数に付与することでマクロがよしなに関数をTypst向けにエクスポートしてくれます。Typstプラグインは基本的にバイト列を受け取りバイト列を返すことしかできません。ただし戻り値には
Result
typeを使うこともできます。詳しくはwasm-minimal-protocol
のサンプルを見ていただければわかると思います。最後に以下のコマンドでビルドします。
target
ディレクトリ内にwasmが生成されたはずです。では実際にTypstで読み込んでみましょう。以下のようなTypstファイルを作成します。プラグインはバイト列を受け取りバイト列を返すので、引数は
bytes()
で変換して渡し戻り値はstr()
関数で文字列に戻します。これを
でコンパイルすれば…
このようなpdfファイルが生成されているはずです。非常に簡単ですね。
このようなpdfファイルが生成されているはずです。非常に簡単ですね。
Excel読み込みプラグイン
これだけでは面白くないのでもう少し実用的なものを作りましょう。
自分は表を作る時に雑にExcelで作ることが多いのですが、Typstでxlsxファイルは読み込めないのでCSVにいちいち変換しなければなりません。
これは面倒なのでxlsxファイルを直接読み込んでくれるTypstプラグインを作ろうと思います。
これは面倒なのでxlsxファイルを直接読み込んでくれるTypstプラグインを作ろうと思います。
xlsxファイルを読み込むのは大変そうだな…と思った方もいるかもしれませんがそこはRust、calamineという素晴らしいクレートが存在します。これを使うことで手軽にxlsxの解析が行えます。
まずは前節と同様にRustプロジェクトを作成してから
で依存関係を追加し、以下のコードを
lib.rs
に書きます。ソースコードを見てもらえれば大体何をしているのかわかると思います。
ポイントとしては、TypstのWASM環境は完全に外部と分離されているため、外部のファイルにアクセスするために
プラグイン側ではxlsxデータを読み込み、指定された範囲のデータをtsv形式で返しています。
CSVやTSVはTypstで読み込めるため後は自由にデータを弄ることができます。
ポイントとしては、TypstのWASM環境は完全に外部と分離されているため、外部のファイルにアクセスするために
.typ
ファイルのほうでxlsxファイルをバイト列として読み込みそれをプラグインに渡しています。プラグイン側ではxlsxデータを読み込み、指定された範囲のデータをtsv形式で返しています。
CSVやTSVはTypstで読み込めるため後は自由にデータを弄ることができます。
では以下のような
するとこのように期待通りの表が得られました!
少し意外だったのですがxlsxって計算結果もファイルの中に保持してあるんですね。これは嬉しい。数式を取りたければコード内の
Book1.xlsx
を作ってtypst compile
を実行してみましょう。するとこのように期待通りの表が得られました!
少し意外だったのですがxlsxって計算結果もファイルの中に保持してあるんですね。これは嬉しい。数式を取りたければコード内の
worksheet_range
をworksheet_formula
に変えればよさそうです。最後に
いかがでしたか?とても簡単にTypstのプラグインを作成できることがお分かり頂けたかと思います。既存の言語のエコシステムを使って比較的容易に複雑なプラグインを開発することができることはTypstの大きな利点だと思います。
ちなみに、パッケージを作ったら
typst/packages
リポジトリにPRを送ることで公式のプラグインリストに載り、import "@preview/..."
でインポートできるようになります。参考:
Typstの日本語Lipsumパッケージを作ってみた件
zenn.dev
また、今回使用したソースコードは
playground/other/typst-plugin at c0fb192f71e71fbbaafcc57673bdc4e931f3dd39 · nazo6/playground
Contribute to nazo6/playground development by creating an account on GitHub.
github.com
で公開しています。
是非みなさんもTypstプラグインを作ってみてください。