5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

明日すぐ使えない! Typstの小ネタ7選

Last updated at Posted at 2025-12-10

アドベントカレンダーの記事ということで、Typstに関するチョット軽めの話題をたくさん集めてみました:smiley::christmas_tree:

その①:「Typst」とは本当は何なのか

Typstは新しい組版ソフトウェアですが、今では「Tinymist」(言語サーバ)や「typstyle」(フォーマッタ)等の周辺ソフトウェアが登場しています。ではソフトウェアとしての「Typst」とは何を指すでしょうか。多くの人は「コマンドシェルでtypstと打って起動するやつ」、つまりTypstのコマンドラインツール(CLI)​を思い浮かべると思います。

例えばTeXの場合を考えると、ソフトウェアとしての「TeX」は「TeXのCLI」だけを指します。その他のもの、例えば「(La)TeX用のエディタ」や「(La)TeXのオンラインサービス」は「TeX」ではありません。

ところが、Typstについては事情が異なるようです。ご存じの通り、Typstの開発元(「Typst GmbH」という企業)はTypstのWebサービスを提供しています。

このWebアプリの名称は何でしょうか。自分が調べた限りではこのWebアプリを特に指す明確な名称は見当たりません。

  • Webアプリのタイトル(title要素)は単に「Typst」です。
  • 「About」のダイアログ1では「Typst Web Application」となっています。
  • 「Terms and Conditions」のページ2ではこの無料版のサービスは「Typst App」と呼ばれています3
  • Docsの中のページでは「Typst web app」と呼ばれています。

これを見る限り、明確な名称を付ける意図はなくて、単に「TypstのWebアプリケーション」と呼んでいる感じです。さらに、Docs中のOSSをアピールするページを見ると、TypstのCLI(こちらはOSSであるがWebアプリはOSSではない)を指すときに明確に「Typst compiler」と呼んでいます。つまり「Typst」だけではCLIのことを指すとは考えていないようです。

以上を鑑みると、「Typst」の意味について以下のことがいえそうです。

  • 「Typst」というのは厳密にはマークアップ形式の名称であってソフトウェアの名称ではない。
  • 「Typst」が(慣用的に)ソフトウェアを指しているなら、それはCLIとWebアプリの両方の可能性がある。

その②:「Typst」の正しい発音

「TeX」の発音については、そもそも公式の規定がアレ:sushi:だったり、発音について論じる人がアレ:sushi:だったりするわけですが、Typstはそういうアレ:sushi:な話とは一切無縁です:sparkles: TypstのGitHubREADMEの中で明確にこう書かれています。

IPA: /taɪpst/. "Ty" like in Typesetting and "pst" like in Hipster.

つまり「Typst」の発音は /taɪpst/ です。日本語での(慣習に従った)語形は「タイプスト」となるでしょう。おしまい:blush:

その③:「Typst」のロゴ

TeXは(ry:sushi: Typstはを「文章中でソフトウェア名を“ロゴ”で書く」という奇習とは一切無縁です:sparkles: Typstにも(フツーの意味での)ロゴは存在していて、公式サイトのページの左上にあるのがロゴです。しかしサイトの文章を見てわかる通り、文章中ではフツーの文字で「Typst」と書くことが推奨されています。

image-1.png

なおロゴの文字は「typst」ですが、フツーに書く場合はフツーの固有名詞のように「Typst」と語頭を大文字にすることに注意してください。さっきのREADME中の文章の続きにこう書かれています。

When writing about Typst, capitalize its name as a proper noun, with a capital "T".

おしまい:blush:

その④:Typstの用語の発音

その②でTypstの発音の話をしたので、Typstの用語の発音に関する話をします。

  • par関数には段落の行間を指定するためのleadingというパラメタがあります。この “leading” は「行間」という意味の専門用語ですが、その発音は /ˈlɛdɪŋ/(日本語語形は「レディング」)です。活版印刷において行間に鉛(lead)の詰め物をしたことが由来になっています。

  • Typstには“相対的な長さ”を表すrelativeというデータ型があります。“relative” は一般的な英単語だと思いますが、その発音が /ˈrɛlətɪv/レラティヴ)であることに注意しましょう。3音節以上の語では多くの場合4に語尾の -ative には強勢がなく発音は /-ətɪv/ となります。conservativeやgenerativeなどの語と同様です。

その⑤:コードモードでも使えるマークアップ

Typstには3つのモード(マークアップ・数式・コード)があり、それぞれのモードの文法は大きく違います。従って、マークアップモードで使えるエレメントの記法(*で強い強調、#で見出し、等)はコードモードでは使えず、もし使いたいなら[~]のブロックを使って一旦マークアップモードに移行する必要があります。

(コードモード)
// これはstrongエレメントになる
let default_name = [*名無しさん*]
// 以下の文と同じ動作
// let default_name = strong("名無しさん")

ところが、エレメントの記法5の中にはコードモードでも使用可能なものが2つあります。その1つは数式を表す$~$です。これはモード移行の一種でもあるため把握している人も多いでしょう。

(コードモード)
// これはmath.equationエレメントになる
let variable = $x$
// 以下の文でも同じ
// let variable = [$x$]

// 非公開の"symbol"のエレメント関数を取得する
let msymbol = $x$.body.func()

それでは、もう1つの記法は何でしょう? 正解は生テキスト(raw text)の記法である`~`です。

(コードモード)
// これはrawのエレメントになる
let value = `None`

// 言語タグも使用可能
let value = ```python None```

コードモードで生テキスト自体を扱う場面は少なそうですが、生テキストを「エスケープが不要な文字列リテラル」の役目で流用するテクニックはとても有用です。

(コードモード)
// rawエレメントのtextフィールドでstr値を取り出せる
let pattern = `\*(\w[\w\.\-]*)\*`.text
// 直接strリテラルで書くとこうなる
// let pattern = "\\*(\\w[\\w\\.\\-]*)\\*"

その⑥:コードモードを終わらせる方法

マークアップモードの中でTypstの変数を参照したい場合は、#記法を用いて一旦コードモードに切り替えることになります。

(マークアップ)
#let name = "Typst"

// 変数「name」を参照する
Yes, #name is great!

image-2.png

しかし時々コードモードが意図した位置を超えて続いてしまう場合があります。日本語の文章で変数を参照する場合に起こりがちです。

(マークアップモード)
#let name = "Typst"

// 「nameはスゴイ」という未定義の変数を参照しようとする
やっぱり#nameはスゴイ!
//==> エラー「unknown variable: nameはスゴイ」

後ろに記号が続くときにそれがコードモードの一部と解釈される場合もあります。

(マークアップモード)
#let version = "1.2.345"

// 「"1.2.345".zip」というTypstコードを評価しようとするが
// そもそもstr値はフィールドを持っていない
Download "foobartool-#version.zip" from the site.
//==> エラー「cannot access fields on type string」

このように「コードモードがどこまで続くか」を判断するのは難しいので、コードモードを確実に終結させる手段がほしいところです。実はTypstではそれが用意されていて、#記法で埋め込んだコードモードはセミコロン;を書くことで確実に終結できます。

(マークアップモード)
#let name = "Typst"
// ';'でコードモードが終結する
やっぱり#name;はスゴイ!

#let version = "1.2.345"
Download "foobartool-#version;.zip" from the site.

image-3.png

「別のマークアップ形式からTypstに変換する」ようなプログラムを作成していてマークアップモードの埋込を利用する場合には、その後ろに続くテキストが予測できないため、コードモードを;で終結させる必要があるでしょう。

ファイル名は「仕様-*機能名*~~-暫定~~.xlsx」とする。

↓ GFM形式→Typst形式に変換.

ファイル名は「仕様-_機能名_#strike[-暫定];.xlsxとする。
// ';'がないと意図した結果にならない!

コードモードの終結の規則はかなり複雑で「文法的に続けられる限りは続ける」というものでもありません。このため先述の問題とは逆にコードモードが意図した位置より前で終わってしまうという問題も起こりえます。

(マークアップモード)
This is #calc.pi*2 and
// 空白文字に注意. 例えばコードが長くなって途中で改行したいと
// いう場合にこれと同等の状況になりえる.
that is #calc .sqrt(2025).

image-4.png

この問題に対しては「所望のコード全体を{~}」という対処法が使えます。

(マークアップモード)
This is #{calc.pi*2} and
that is #{calc .sqrt(2025)}.

// "{~}"と";"を併用すると範囲が明示的に決まる
Blah blah #{calc .sqrt(2025)}.foo blah.

image-5.png

その⑦:数式モード中の空白文字

LaTeXでは「数式モード中の空白文字は(トークンの区切りの意味を除き6)無視される(組版結果に影響しない)」という規則があります。Typstの数式モードでも空白文字は大抵は無視されているように思えますが、果たして「Typstの数式モード中の空白文字は(トークンの区切りの意味を除き)無視される」は成立するでしょうか?

正解は「成立しない」です。次の例をみてください。

(マークアップモード)
$bold(A)$ versus $bold (A)$

image-6.png

つまり、関数呼出の構文においては関数名7と丸括弧の間に空白文字を挟むことが許されていません。そのため空白が入ったbold␣(A)は数式関数呼出とは解釈されず、bold8(A)が別々に出力されたわけです。

数式関数呼出9(math function call)の構文については他にもヤヤコシイ話があります。次の数式をみてください。

(マークアップモード)
$exp(x + 1)$

image-7.png

いたってフツーの数式ですが、Typstの文法上の扱いは厄介です。expの直後に空白無しで丸括弧があるのは数式関数呼出の恰好ですが、しかしこのexpは関数10ではありません。出力を見る限りはexp(x + 1)が別々に出ていて特に問題がないわけですが、実は内部的にはこの記述は“一旦数式関数呼出扱いになっている”ようなのです。次の例をみてください。

(マークアップモード)
$exp (x, y: 1)$ /
$exp (x; 1)$ /
$exp (#42)$

image-8.png

最後の例の#42はint値の42を表しています。数式モードで単に42と書いた場合はそれはint値でなくcontent値(つまり「42」というテキスト)と解釈されます11

何れも(数学的に無意味なものもありますが)Typstの数式モードの文法的に妥当な記述です。ところがexpの後の空白文字を除いて数式関数呼出の恰好にすると不可解なエラーが発生します。

(マークアップモード)
$exp(x, y: 1)$ /
//==>エラー「unexpected argument: y」
$exp(x; 1)$ /
//==>エラー「expected content, found array」
$exp(#42)$
//==>エラー「expected content, found integer」

1番目の例でエラーが出るのはTypstの0.14.0版以降の仕様です。それより前の版では, y: 1の部分が黙って無視されて(つまり期待に反する出力になって)いました。

このエラーの原因は「丸括弧の中が単なるテキストではなく数式関数呼出の引数の指定と見なされたから」です。1番目の例ではy: 1が名前付き引数と解釈され、2番目では;が配列化指定(つまりarray型の値を“渡した”扱い)と解釈され、3番目ではint値を“渡した”12と解釈されています。expは実際にはfunction値ではなかったのでフォールバックして「“引数”をコンマ区切りで出力」しようとしますが、その際に名前付き引数やcontent以外の値が受け付けられなかったと考えられます。

実用上は、次のようなパターンで当該の問題が起こりえます。

(マークアップモード)
#let answer = 1 + 5 * 8 + 1
$exp(#answer)$ // 括弧内にanswerの計算結果を出したい
//==>エラー「expected content, found integer」

数式関数呼出モドキの形を書くのは少しリスクがある」と留意しておくのがよいかもしれません。

まとめ

今年のTypst Advent Calendarも素敵な記事がいっぱい集まればいいですね!:gift::snowman2:(まとめろ:anger:

  1. メニューから「Typst」→「About Typst」を選択します。

  2. 「About」のダイアログの中にリンクがあります。

  3. ちなみに「Terms and Conditions」の中では単なる「Typst」は企業(Typst GmbH)をを指します。

  4. 例外にはcreativeやinnovativeなどがあります。なおnativeなどの2音節語では a に強勢が置かれて /-ˈeɪtɪv/ となります。

  5. コメントの記法は3つのモードで共通ですが、コメントはエレメントでないので今の話では除外します。

  6. 例えば\sin␣h\sinhは当然異なります。Typstでもsin␣hsinhは異なる結果になります。

  7. 正確にいうと「function値を表す式」。

  8. 「function型の値を出力する」のは明らかに普通の組版ではないので、Typstはこの場合は関数名を生文字列(raw)の書式で出力します。マークアップモードで#math.boldと書いたときも同様の出力になります。

  9. 「数式関数呼出」というのは数式モード中で#を付けずに(つまりコードモードに移行せずに)行う関数呼出のことです。コードモード中の関数呼出とは文法がかなり異なります。

  10. もちろんここでの「関数」は「Typstのfunction型の値」の意味です。expの型がcontentであることはtype(math.exp)の値を調べれば判ります。

  11. ただし、int値の42を出力しようとする場合は結局content値に変換されるので通常は両者は同じ結果になります。

  12. なお、exp(42)は丸括弧の中にある42がcontent値なので大丈夫です。

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?