Markdown の $…$ が、プレビューでただの文字のまま出てくる

Markdown の $…$ が、プレビューでただの文字のまま出てくる

書かせた説明を読み返していて、途中で目が止まります。

誤差は $\sum_{i=1}^{n} (y_i - \hat{y}_i)^2$ で測ります。

ドルマークのまま出ています。プレビューで開いたはずなのに、文字が並んでいるだけです。

頭の中で組み直せば読めます。ただ、それは読み返しではありません。

読み返せません

文章は読み返せば確かめられます。数式は、記号の形になっていないと確かめられません。

\hat{y}_i が何を指すのかは、組まれた形で見れば一目です。文字列のままだと、頭の中で組み直すことになります。それは読み返しではなく、再計算です。

AI に書かせる量が増えると、ここが効いてきます。確かめにくいものが積み上がります。

なぜそのまま出るのか

Markdown の決まりに、数式は入っていません。

もとの Markdown は、見出し・箇条書き・強調・リンクを決めただけのものです。数式は後から各所が勝手に足したもので、$…$ という書き方も、広く使われてはいますが標準ではありません。

そのため、プレビューを作る側が明示的に対応しないと、ただの文字として通過します。対応している所としていない所が混ざるのは、このためです。

どこで組むか

対応するには、どこかで数式を組む必要があります。選べるのは2つです。

ブラウザで組む方法は、よく使われます。ページを開いたときに、ブラウザが数式を探して組み立てます。手軽ですが、組み立てる部品をブラウザに読み込ませる必要があり、表示されるまで一拍あります。

もう1つは、サーバーで組んでから送る方法です。ブラウザは組み上がった図を描くだけなので、速いです。

MulmoTerminal 10.2.0 は後者にしました。全画面のプレビューで $…$ と $$…$$ を見つけて、サーバー側で SVG に組んでから送ります。組み立ての部品は、最初に $ を含む文書が来たときに読み込まれます。

組むと穴が開きます

ここからが、やってみないと気づかない部分です。

数式を組むと、HTML の断片ができます。これをそのまま送ると、文書の中身が HTML としてページに入ることになります。Markdown を書いたのが AI であれ人であれ、そこに仕込みがあれば、そのまま効いてしまいます。

ブラウザで組む場合は、ブラウザ側の掃除の仕組みが使えます。サーバーで組む場合は、それがありません。

MulmoTerminal では、通す要素と属性を名簿にして、そこに載っているものだけを残す形にしました。

最後の2つが、見落としやすいところです。組版の仕組み自体は正しく動いていても、エラーのときに入力をそのまま書き出す経路が残っていると、そこが穴になります。

名簿方式にしたあと、攻撃用の入力を食わせて、HTML の解析器が何を組み立てるかを確かめる検査も入れました。

自分で用意する場合

サーバー側で組むなら、同じ順番を踏むことになります。

  1. Markdown を解析するときに、数式の区切りを見つける規則を足す
  2. 見つけた部分を組版に渡して、SVG を受け取る
  3. 受け取った HTML を、通す名簿で濾す
  4. エラーの文面が混ざる経路を潰す

3番目を飛ばすと動いてしまうので、飛ばしたことに気づきません。ここが一番危ないところです。

ブラウザで組むほうを選ぶなら、掃除は任せられます。代わりに、表示までの間と、読み込ませる部品の分だけ重くなります。

使ってみる

npx mulmoterminal@latest

枠の中でファイルを開いて、全画面のプレビューに切り替えると、数式が組まれた形で出ます。ペインに埋め込んだほうでも、別のタブで開いたほうでも同じです。

まとめ

Markdown に数式の決まりはないので、対応している所としていない所が混ざります。AI に書かせる量が増えると、確かめられない記述が積み上がります。

サーバーで組むと速くなりますが、掃除を自分でやることになります。そこを引き受けるかどうかが、どちらで組むかの分かれ目です。

この記事をシェア

関連記事

記事一覧に戻る