状態管理したい(state

 1// stateを作成
 2#let s = state("key", initial_value)
 3
 4// 値を取得(必ずcontext内でget)
 5#context s.get()
 6
 7// 値を更新
 8#s.update(new_value)
 9#s.update(old_value => new_value)
10
11// タイムトラベル機能
12#context s.at(<label>)    // 特定のラベル位置での値
13#context s.final()      // 最終値

stateはドキュメントの状態を管理するための機能です。 Typstでは、関数の外部にある変数は読み取り専用となり、上書きできません。 また、Typstの内部処理において評価順序(evaluation order)と レイアウト順序(layout order)があり、それぞれ更新のタイミングが異なります。 stateで管理されたオブジェクトは常にレイアウト順序で更新されるため、 ドキュメントの最終的な見た目に基づいた正しい(=より直感的な)順序で状態を取得できます。

さらに「タイムトラベル機能」があり、ドキュメント内の任意の位置から、 ラベルした他の位置での状態値を取得できます。

見出しカウンターしたい

 1#let chapter = state("chapter", 0)    // 章番号を初期化
 2#let section = state("section", 0)    // 節番号を初期化
 3
 4// 見出し1が呼ばれるときに・・・
 5#show: heading.where(level: 1): it => {
 6    chapter.update(n => n+1)    // 章番号をインクリメント
 7    section.update(0)           // 節番号をリセット
 8    block[
 9        // 第 n 章 : 見出し1のテキスト
10         #context chapter.get()  : #it.body
11    ]
12}
13
14// 見出し2が呼ばれるときに・・・
15#show: heading.where(level: 2): it => {
16    section.update(n => n+1)    // 節番号をインクリメント
17    block[
18        // 第 n.m 節 : 見出し2のテキスト
19         #context chapter.get().#context section.get()  : #it.body
20    ]
21}

「第n章」「第n.m節」のように見出しをカスタマイズするサンプルです。 章番号と節番号でそれぞれのstateを定義し、見出しが呼ばれたときに更新しています。 #contextを使って値を取得することで、レイアウト順序にしたがって適切に番号を振ることができます。

多言語対応

 1#let language = state("lang", "en")
 2#let translations = (
 3    en: (title: "Document", page: "Page"),
 4    ja: (title: "ドキュメント", page: "ページ"),
 5    fr: (title: "Document", page: "Page"),
 6)
 7
 8#let t(key) = context {
 9    let lang = language.get()
10    translations.at(lang).at(key)
11}
12
13#language.update("ja")
14#t("title"): My Document
15#t("page") 1 of 10

リファレンス