SvelteKitプロジェクト内でのMarkdownにおいてLaTeXを使う

## 概要

タイトルの通りです.

自作ブログでMarkdownを記事にするところまでできたのですが, ついでに$\LaTeX$を書けるようにしてみました.
めちゃくちゃ簡単で, 便利な世の中だと思いました（小並感）.
せっかくなのでやったことだけ書いておこうと思います.

## Markdownファイルをページとして扱う

これはこの記事と本来は関係ないため備忘録程度にしておきます.

`mdsvex`というパッケージを使います（読み方がわからん）.
[ここ](https://mdsvex.com/docs)（公式ドキュメント）と[ここ](https://joshcollinsworth.com/blog/build-static-sveltekit-markdown-blog)（詳しくブログ的な使い方が記載されている）に書いてあることを読めばいいです.
私は最初は後者の記事をほぼ写しました.

## LaTeX表示のために使用したライブラリ

とりあえず, 順番に列挙していこうと思います.

### KaTeX

ウェブ上でLaTeXを書きたいときにはMathJaxが有名と思いますが, おそらく後発のKaTeXというものもあります.
Qiitaとかでも使われているらしいです.
高速, 見た目の質, 依存性のなさ等で優れているようです.

### Remark

[Remark](https://github.com/remarkjs/remark)はMarkdownプロセッサであり, [unified](https://github.com/unifiedjs/unified)というプロジェクトの一部という位置づけのようです.

unifiedはテキストと抽象構文木を関連付けて操作するライブラリ全般を扱うようです.
その中で, Markdownの文法に対応したものがremarkだと理解しました.

関連ライブラリが様々にあるようで, 処理自体に影響を与えるもの, 構造要素に色々味付けができるもの, 他の構造化文書に変換するものなど多岐にわたります.

### rehype

これもunifiedプロジェクトの一部です.

こちらはHTML処理を担当するようで, 思想はremarkと似ています.
remarkと組み合わせて美味しいことができそうな感じがします.
こちらも大量に関連ライブラリがあります.

### mdsvex

前節にも登場しました.
SvelteのConfigファイルでこれをプリプロセッサとして書いてあげると, ビルド時にマークダウンファイルをよしなにSvelteの要素として扱ってくれます.

この`mdsvex`は上記の`remark`や`rehype`をさらに中で走らせることができます.
つまり, markdownを読みこんだときにremarkで処理したり, 処理したhtmlをrehypeで処理したりできます.
好きな機能を選んで使えることになります.

### 結局使ったもの

というわけでその中で使ったのが以下です.

- [`remark-math`](https://github.com/remarkjs/remark-math)
- [`rehype-katex-svelte`](https://github.com/kwshi/rehype-katex-svelte)

`remark-math`は, markdown中の$\LaTeX$構文をunifiedで扱える構造に置き換えるものです（だと思っています）.
`rehype-katex-svelte`は, [`rehype-katex`](https://github.com/remarkjs/remark-math/tree/HEAD/packages/rehype-katex)というプラグインをSvelteで扱えるようにチューニングされたものです（公式のrehypeプラグインとはなっていないようです）.
`rehype-katex`は適当なunified構造を`KaTeX`を用いてマークアップするものです.

ここまでで, できそうな気がしてきました.

## Svelteにおける設定

あとはほとんど用意してもらった構造を使うだけです.

`svelte.config.js`を以下のようにセットします.

```js
import { mdsvex } from "mdsvex";
import rehypeKatexSvelte from "rehype-katex-svelte";
import remarkMath from "remark-math";

const config = {
  preprocess: [
    preprocess(),
    mdsvex({
      extensions: [".md"],
      remarkPlugins: [remarkMath],
      rehypePlugins: [rehypeKatexSvelte]
    })
  ],
  ...
}
```

のようにします.
これで, markdown中に`$\LaTeX$`と書けば$\LaTeX$となります.

ディスプレイ数式も,

```latex
$$
\\frac{1}{c^2}\ddot{u}(x, t) - u_{,ii}(x,t) = 0, \\quad x\\in D, t>0
$$
```

でOKです.

$$
\frac{1}{c^2}\ddot{u}(x, t) - u_{,ii}(x,t) = 0, \quad x\in D, t>0
$$

となります.
なお, Qiitaではうまく表示されませんが`\\bm{x}`などとすれば正しく表示されるようです.

## 余談

### その1

`mdsvex`はPrism.jsを内包しているようで, コードブロックを見つけると自動で要素に分解してクラスを付与してくれます.
Prismのテーマを適当にダウンロードして使うようにしてやれば, いい感じにコードを掲載できます.
すごい.

### その2

今, 目次を自動で生成するようにしたいと考えています.

これもrehypeを使います.
`rehype-slug`というやつをpreprocessorに挟むと各見出しにidを付与してくれます（これをslugというそうです）.

で, `rehype-toc`というやつでslugがついている見出しをいい感じのhtmlにまとめて冒頭にくっつけてくれます.

これだけでできそうな気がするのですが, Svelteのビルドで弾かれてしまいます.
というのも, Svelteはリンクが壊れていないかどうかを巡回して確かめてくれるのですが, `rehype`系は日本語をそのまま扱うのに対してSvelteはURLエンコードをしてからチェックするようです.

例えば, 「テスト」という見出しについて考えます.
これをURLエンコードすると`%E3%83%86%E3%82%B9%E3%83%88`となります.
`rehype-slug`は`<h2 id="テスト">テスト</h2>`という要素を生成し, `rehype-toc`もこれに従って`<a href="#テスト">`のようなリンクを生成します.
しかし, Svelteは「idが`%E3%83%86%E3%82%B9%E3%83%88`っていう要素がないよ」と警告を出し, ビルドできません.

実は, `rehype-slug`側のコードをいじったら解決した（要素にidを挟んでいるだけのすごく簡単なコードでできているので, ここにURLエンコードを挟むだけで解決しました）のですが, GitHub Actionsで自動ビルドするのには使えません.

というわけで, Issueを立てるかプルリクエストなどと迷っていますが全く何をすればいいかわかりません.
だれか手ほどきしてくれ〜

## まとめ

というわけでSvelteKitで作ったブログで$\LaTeX$記法を使えるようになりました.
仕組みとかをあまり理解していないのでもうちょっと親しめたらいいと思います.