ブログを typst ベースのものに移行した

はじめに

もうブログは 4 年くらい(!)書いてなかったのですが,やはり定期的なアウトプットを残すのは大事だなと思ったのでブログを改修しました.

改修自体はずっとやろうと思って放置していたのですが,最近はコーディングエージェントの性能も良くなったのでひたすらしばき倒すことで数時間でサイトの作成と記事の移行をやってくれました.良い時代ですね.

技術構成

記事は markdown ではなく typst で書けるようにしてます.
最近はもうレポートもスライドも全部 typst で作っていてそれに合わせた形です.

記法もコンパイル速度も優れてますし,ライブラリを含めたエコシステムも十分成熟してます.日本語環境はあと一歩という感じですが1だいぶ良くなってきました.もう LATEX には戻れないのですが,論文は相変わらず LATEX で書かなくていけないのが辛いところ2

今回は typst で記述→ html で出力 → Zola のファイルに埋め込み → Zola でコード生成という仕組みを取っています.

Zola は(Hugo や Jekyll などと同じ)static site generator (SSG) の一種で,Rust で書かれています3

フルスクラッチで開発しても良いかなと思ったのですが,特に凝ったつくりにする予定も無かったですし,デザインくらいならテンプレートの html や css を触って解決するので SSG を選びました.

typst の html 出力については,バージョン 0.13.0 で試験的に導入され4,現在も開発中ですがそこそこ多くの typst の機能をサポートしていますし,私が普段使っているライブラリでも多くが html にサポートしています.不十分ではあるものの精力的に実装されているという印象です.今後破壊的な変更があるかもしれませんが,まぁそのときはそのときでしょう.

色々ライブラリや記法を試す

数式と定理環境 (theorion)

theorion を使うと,定理・定義・証明などの環境をきれいに書けます.

Definition 1 (素数)

1 より大きい整数で,1 と自分自身以外に正の約数を持たないものを素数という.

Theorem 2 (素数の無限性)

素数は無限に存在する.

Proof. 有限個しかないと仮定し,それらを 𝑝1,𝑝2,,𝑝𝑛 とする. 𝑁=𝑝1𝑝2𝑝𝑛+1 を考えると,𝑁 はどの 𝑝𝑖 でも割り切れないため, 𝑁 自身が素数か,または 𝑁 の素因数が 𝑝1,,𝑝𝑛 に含まれない素数となる. これは仮定に矛盾する. ⁠ 

Example. 最初のいくつかの素数: 2,3,5,7,11,13,

4=22 は合成数なので素数ではない.

Remark

上の証明はユークリッドによるもので,紀元前 3 世紀ごろに書かれた 『原論』に記されている.

Lemma 3

𝑝 が素数で 𝑝𝑎𝑏 ならば,𝑝𝑎 または 𝑝𝑏 が成り立つ.

コードブロック (zebraw)

zebraw はコードを綺麗に載せられて行番号でハイライトしたりコメントを入れたりできます.また,カラースキームも(typst 標準機能で)sublime text の .thTheme 形式で指定できます.

ライン番号付き

rust
1
fn sieve_of_eratosthenes(limit: usize) -> Vec<usize> {
2
let mut is_prime = vec![true; limit + 1];
3
is_prime[0] = false;
4
is_prime[1] = false;
5
let mut p = 2;
6
while p * p <= limit {
7
if is_prime[p] {
8
let mut multiple = p * p;
9
while multiple <= limit {
10
is_prime[multiple] = false;
11
multiple += p;
12
}
13
}
14
p += 1;
15
}
16
is_prime.iter().enumerate()
17
.filter(|(_, &v)| v)
18
.map(|(i, _)| i)
19
.collect()
20
}

ライン指定ハイライト

python
1
primes = [
2
n for n in range(2, 100)
3
if all(n % i != 0
4
for i in range(2, n))
5
]
6
print(primes)

数式

ブロック数式:

𝑘=1𝑛𝑘=𝑛(𝑛+1)201𝑥𝑛𝑑𝑥=1𝑛+1,𝑛>1

テキスト装飾

ハイライトアンダーライン取り消し線 などのインライン装飾も使えます.

ブロック引用

“ Premature optimization is the root of all evil. ”

キャプション付き画像

Figure 1: 筆者のアイコン

テーブル

機能記法HTML タグ
ハイライト#highlight[...]<mark>
下線#underline[...]<span style="...">
取り消し線#strike[...]<s>

HTML 未対応の記法

以下は v0.15.0 時点で HTML export に対応していませんでした.今後に期待.

#grid — コンテンツが消える

typst
1
#grid(
2
columns: (1fr, 1fr),
3
[左], [右],
4
)

コンパイルエラーにはならず,内容が無言でぶっ壊れる仕様でした.残念.html.elem で再実装した #two-column を代わりに使うことに.

オイラーの等式

𝑒𝑖𝜋+1=0

バーゼル問題

𝑛=11𝑛2=𝜋26

ボックス

theorion#emph-box はネイティブで HTML に変換されるんですが,いつも使っている showybox をベースにした自作関数たちは未対応なのでひとまず html.elem で再実装しました.

mysect のタイトル
左ボーダー付きのセクションボックス.color 引数で色を変えられる.
カスタムカラー
color: "var(--accent)" のように CSS カラー文字列を渡す.
mybox のタイトル
タイトルバー付きのコンテンツボックス. 定義や重要事項の強調に使う.
カスタムカラー
こちらも color 引数で変更可能.

#text のスタイリング

typst
1
#text(fill: rgb("#FF6188"))[色付き]
2
#text(weight: "bold")[太字]
3
#text(size: 1.4em)[大きめ]

色付き 太字 大きめ

テキスト内容は出力されるんですがスタイルは一切反映されませんね…… 太字は *...*,イタリックは _..._ を使えますが.

#quote

typst
1
#quote(attribution: [著者名])[本文]

<blockquote> ではなく <p> として出力され,attribution も消えます.まぁそんなに使わないかな.

終わりに

どんどん記事を書いていきたいですね.

  1. 1特にソースコード内での改行によって pdf に半角スペースが入ってしまうのが惜しい(https://github.com/typst/typst/issues/792#issuecomment-3446559332).
  2. 2IPSJ さんそろそろ typst 対応しませんか?
  3. 3気づけば Rust で書かれていますとわざわざ言わなくてもいいくらい Rust は普及しましたね.
  4. 4https://typst.app/docs/changelog/0.13.0/