先日の某言語1キャンペーン🌸用のネタ記事においてMiTeXを紹介した。折角なのでMiTeX自体についてもう少し解説したいと思う。
MiTeXの概要
端的にいうと、MiTeXは「LaTeXのコードをTypstのコードに変換するソフトウェア」である。メインの部分はRustで実装されていて「コマンドラインツール」「Typstパッケージ」「Webアプリ」の3つの形態で利用できる2。
同様の目的のソフトウェアは既に存在する(例えば tex2typst 等)がMiTeXの大きな特徴は「Typstでで組版するのが目的であり、マークアップの形式変換自体は目的ではない」ということである。つまり「変換結果のTypstコードの(人間にとっての)可読性」は重視していない。例えば、次のようなLaTeXの数式コードを考える。
\left(\frac{1}{2}x + 30\right)^4
この数式はTypstでは次のように簡潔に書けて、またそのように書くのが普通である。
(1/2 + 30)^4
従って、形式変換を目的とするならこれを出力すべきだろう3。しかしMiTeXは次のような、LaTeXよりも長くて複雑なコードを出力する。
lr(\( frac(1 ,2 )x + 3 0 \) )^(4 )
MiTeXは出力のコードについて「人間が関与せずに単にTypstの入力に与えるだけ」という状況を想定しているため、変換のロジックがより簡潔で高速になることを優先しているわけである。
MiTeXのキホンの使い方
「Typst文書中でLaTeXのコードを組版する」という目的で必要な範囲の機能について説明する。
mi(«LaTeX記述»)[content]: LaTeXの数式モードのコードをTypstのインライン数式に変換する。mimath(«LaTeX記述»)[content]: LaTeXの数式モードのコードをTypstのブロック数式に変換する。mitext(«LaTeX記述»)[content]: LaTeXのテキスト(非数式)モードのコードをTypstのエレメントに変換する4。- これらの関数の引数の
«LaTeX記述»は文字列(str値)またはrawエレメントで指定する。LaTeXのコードには\が大量に出現するので\のエスケープが不要なrawエレメント(`…`)の方が便利であろう。
これらの機能を用いた簡単な例を以下に示す。
#import "@preview/mitex:0.2.5": *
#set page(paper: "a5")
// mimathの出力は通常のTypstのブロック数式となるので,
// Typst側で数式番号を制御できる.
#set math.equation(numbering: "(1)")
Now we're using *Typst*, and we can write
- #mi(`\sqrt{3+2\sqrt{2}} = 1+\sqrt{2}`),
- #mi(`(x^3)'=3x^2`) and
- #mi(`\lim_{x\to\infty}(1+1/n)^n = e`).
We also have
#mitex(`
\left( \int_0^\infty \frac{\sin x}{\sqrt x}\,\mathrm{d}x \right)^2
= \prod_{k=1}^\infty \frac{4k^2}{4k^2-1}.
= \frac{\pi}{2}.
`)
and thus it follows that
// mimath自体は数式番号を出力できない
#mimath(`\begin{align}
\sum_{k=0}^n \binom{n}{k}
&= \sum_{k=0}^n \binom{n}{k}1^k1^{n-k} \\
&= (1 + 1)^n = 2^n.
\end{align}`)
Note again that
#mitext(`we're using \textbf{Typst} and \emph{not} LaTeX.`)

MiTeXのホンキの使い方
以下では、MiTeXパッケージの使い方(インタフェース)の詳細について説明する。
引数
複数の関数に共通して表される引数について、その意味を先に解説しておく5。
«LaTeX記述»[str|content]: 変換元のLaTeXのコードの文字列。str値ならその値そのもの、content値ならtextフィールドの値が使われる。- オプション引数
mode[str]: モード。有効な値はtextまたはmathの何れか。概略としては、textは「テキスト(非数式)を処理対象とする」、mathは「数式を処理対象とする」ことを表す。
機能一覧
mitext(«LaTeX記述»)[content]: LaTeXのテキストモードのコードを変換して組版した結果のコンテンツ。mimath(«LaTeX記述»)[content]: LaTeXの数式モードのコードを変換して組版した結果のmath.equationエレメント。
オプション引数:block[bool;既定値=true]: ブロック数式であるか。- 残りの引数:
math.equation()に移譲される。
mi(«LaTeX記述»)[content]:mimath関数のblockの既定値をfalseに変えた版。オプション引数はmimathと同じ。mitex(«LaTeX記述»)[content]:modeの値に応じてmitextとmimathの何れか一方に移譲する。
オプション引数:mode[str;既定値="math"]: モード。textの場合はmitext、mathの場合はmimathを移譲先にする。- 残りの引数:
mitextまたはmimathに移譲される。
mitex-convert(«LaTeX記述»)[str]: LaTeXのコードを変換した結果のTypstのコード。
オプション引数:mitex-scope[dictionary]: パッケージが用意する標準の「eval用スコープ」。つまり実際に組版をする場合はmitex-convertで得たTypstコードをこのスコープの下でevalする。mitex-wasm[module6]: WASM実装のプラグイン。
プラグインの関数7:
命令スペック(mitex-convertのspec引数)と「evalのスコープ」を自分で用意することでLaTeXコード中で使用可能なLaTeXの命令のセットをカスタマイズできるようになっている。
まとめ
というわけで、「Typstは気に入っている😍がTypstの数式表記はトッテモ複雑で気に食わない😩」という人はMiTeXパッケージを利用してLaTeXの数式をドンドン書きましょう!💁
- Typst以外🤮😱🤯↩
- TypstパッケージとWebアプリはRustコードをWASMにコンパイルすることで実現している。↩
- 実際に、tex2typstはこのコードを出力する。↩
- テキストモードの変換は開発中でありまだ不完全である。↩
-
つまり、
«LaTeX記述»および「modeというオプション引数」については、この節にある説明が(も)適用される。↩ - Typstの0.13.0版以降ではインポートしたプラグインを指す値はmodule型として扱われるようになった。旧来の版で使われていたplugin型は廃止された。↩
- Typstの仕様で決まっている通り、WASMプラグインの関数の引数と戻り値は全てbytes型である。↩