Typst入門
[2025-02-24] 以下で述べたようなことを取り込んだテンプレート typst-js がTypst Universeに入りました。
[2025-02-10] Typst 0.13.0の変更点を別記事にまとめました。1行目がインデントされないバグが直り、和欧混植に便利な機能も追加されたので、日本人には嬉しい更新です。
[2024-11-21] 日本語の組版ルールもご参照ください。
はじめに
Typst(タイプスト)はLaTeX代替とされる新しい組版ツールである。無料〜有料のサービスだが、GitHub でオープンソースのコマンド版(CLI)が公開されている。ここではオープンソース版について扱う。なお、TeX Liveを入れていれば、texdoc typstfun でTypstとLaTeXのコマンド対照表が表示される。
インストールはGitHubからダウンロードするか、あるいはMacならHomebrewで brew install typst と打ち込むか、Windowsなら winget install --id Typst.Typst -e と打ち込めば完了する。
typst --help
で簡単な使い方が表示される。
typst update
で自己アップデートできる。
Typstはシステムにインストールされたフォントをそのまま使える。それ以外のところにあるフォントは TYPST_FONT_PATHS という環境変数の設定で使うことができる。MacなどUnix系であれば例えば
export TYPST_FONT_PATHS=/usr/local/texlive/2024/texmf-dist/fonts/opentype
のようにしてTeX LiveのOpenTypeフォント群が使える。使えるフォント一覧は
typst fonts
で表示される。
最初のTypst文書
さっそく最初の文書をタイプセットしてみよう。
Einsteinは $E=m c^2$ と言った。
LaTeXと違って m c のようにスペースが必要である。これを test.typ というファイル名で保存し、
typst compile test.typ
と打ち込むと、test.pdf というPDFファイルが出力される。ただ、デフォルトのままでは、Windowsでは日本語部分がMeiryoになり、MacではSIL-Hei-Med-Jianといういわゆる中華フォントになる。ちなみに欧文はデフォルトでLibertinus、数式は『LaTeX美文書作成入門』第9版で採用したのと同じNewCMMath-Bookである。
明朝体のフォントにするには、typst fonts で出力されるフォントから適当なものを選んで指定すればよい。Macならヒラギノ明朝(Hiragino Mincho ProN)、Windowsなら游明朝(Yu Mincho)などが候補である。
#set text(lang: "ja", font: "Hiragino Mincho ProN") Einsteinは $E=m c^2$ と言った。
これで数式以外が明朝体になる。欧文「Einstein」の部分も明朝体の従属欧文フォントになる。
欧文はやっぱりLibertinusのほうがいいなら、
#set text(lang: "ja", font: ("Libertinus Serif", "Hiragino Mincho ProN"))
Einsteinは $E=m c^2$ と言った。
のようにする。これでとりあえず数式以外はデフォルトでLibertinusが使われ、Libertinusにない文字はヒラギノになる(後述の「LaTeXと比べて未完成の部分」参照)。欧文フォントと数式フォントが同じデザインのほうがよければ Libertinus Serif の代わりに New Computer Modern を指定すればよい。
pandocで使う
以上でも見たように、Typstでは # で始まる部分はTypstの命令である。Markdownと違って、見出しは # ではなく = で始める。数式もMarkdownで使うLaTeX風の記法とはかなり違う。LaTeX/Markdownに慣れていたら、最初は混乱する。そんな場合は、まずはLaTeXかMarkdownで書いて、pandocでTypstに変換すれば簡単である。
pandoc は物書きには必須の汎用ドキュメント形式変換ツールである。Homebrewなら brew install pandoc でインストールできる。markdown、html、latex、typst、docx、epub、ipynb などに対応する。
例えばMarkdownで
--- title: Typst入門 author: 奥村晴彦 date: 2024年11月11日 mainfont: Hiragino Mincho ProN --- # はじめに Einsteinは $E=mc^2$ と言った。
のように書いて、
pandoc test.md -o test.pdf
と打ち込むと、デフォルトでは test.md をLaTeXに変換して pdflatex でPDFにしようとするので、日本語があるとエラーになる。そこで
pandoc test.md --pdf-engine=typst -o test.pdf
とすると、LaTeXの代わりにTypstを使ってPDFに変換するので、とりあえずうまくいく。
中で何が起こっているかというと、pandoc -D typst で出力されるTypstテンプレートを使ってTypstでPDFに変換している。したがって、pandoc -D typst >mytemplate.typ のようにテンプレートをファイルに収めてそれを修正し、
pandoc test.md --pdf-engine=typst --template=mytemplate.typ -o test.pdf
のようにして適用すれば、好きな出力にできる。例えば
font: ("$mainfont$",),
を
font: $mainfont$,
に直せば、
---
title: Typst入門
author: 奥村晴彦
date: 2024年11月11日
mainfont: ("New Computer Modern", "Hiragino Mincho ProN")
---
# はじめに
Einsteinは $E=mc^2$ と言った。
のように欧文フォント・和文フォントを別に指定できるようになる。
以上はMarkdownで書いた文書をpandoc+TypstでPDFに変換する方法であった。直接Typstファイルに変換するには pandoc test.md -o test.typ とする。ただし、Markdown文書冒頭の --- で囲まれた部分はpandocのTypstテンプレートで処理されるので、これでは出力されない。さらにオプション --standalone=true を付ければテンプレートを埋め込んだ形のファイルが出力される。
パッケージ・テンプレートの利用
以下ではLaTeXに近い出力を得るために
export TYPST_FONT_PATHS=/usr/local/texlive/2024/texmf-dist/fonts/opentype
のようにしてTeX LiveのOpenTypeフォントディレクトリにある原ノ味フォント等を利用する。TeX Liveをインストールしていない場合は、typst fonts で列挙されるフォントの中から適当なものに置き換えられたい。
まずはどこかのディレクトリでターミナルに
typst init @preview/rubber-article myproj
と打ち込んでみよう。これは Typst Universe(LaTeXのCTANに相当する場所)から rubber-article というパッケージ(いわばスタイルファイル)をダウンロードし、カレントディレクトリ下に myproj というフォルダを作ってサンプルファイル main.typ を入れる。パッケージは環境変数 TYPST_PACKAGE_CACHE_PATH で指定した場所(デフォルトはLinuxなら ~/.cache の中、Macなら ~/Library/Caches の中、Windowsなら C:\Users\ユーザ名\AppData\Local の中)にキャッシュされる。
とりあえずサンプルファイルをコンパイルしてみよう。
cd myproj typst watch main.typ
このように typst compile main.typ でなく typst watch main.typ とすると main.typ が変化するタイミングで自動コンパイルしてくれる。生成される main.pdf を自動再読み込みに対応したPDFビューア(MacのPreviewなど)で開いておけばリアルタイムで編集結果が見れる。
ご覧のように、rubber-article はLaTeXのarticleドキュメントクラスとほぼそっくりの仕上がりになる。
この main.typ を適当に書き直してみよう。日本語メインの文書なら、おおよそ次のようにするとよさそうである(数値は調整の必要あり)。
#import "@preview/rubber-article:0.1.0": *
#show: article.with(lang:"ja", text-size:10pt)
#set text(font: ("New Computer Modern", "Harano Aji Mincho"), weight: 450)
#show heading: set text(font: ("New Computer Modern Sans", "Harano Aji Gothic"), weight: 450)
#show strong: set text(font: ("New Computer Modern Sans", "Harano Aji Gothic"), weight: 300)
#set par(first-line-indent: 1em, spacing: 1em, leading: 1em)
#show heading: it => {
v(2em, weak: true)
it
par(text(size: 0pt, ""))
v(0.3em, weak: true)
}
#maketitle(
title: "Typst入門",
authors: (
"奥村晴彦",
),
date: datetime.today().display("[year]年[month repr:numerical padding:none]月[day]日"),
)
= 日本語でTypstを使う
Einsteinは $E = m c^2$ と言った。
New Computer Modernについては、『LaTeX美文書作成入門』第9版ではRegularでなくBookのほうを使っている。TypstでBookにするにはweightを425〜575にすればよい(デフォルトは400)。原ノ味はRegularでいいのでここではweightを450に設定した。見出しについてはTypstのデフォルトでは強すぎるように感じたので少しweightを落としてあるが、好みに応じて加減されたい。
和文文字の組み方
日本語メインの文書の組み方で注意すべきは、行長が全角文字幅の整数倍になるようにマージンを調整しないと、不自然な伸びが生じてしまうことである。日本語の文字は、例えば
#set text(lang: "ja", font: "Harano Aji Mincho", 10pt)
のようにして10ptに設定すると、全角1文字の幅 1em は 10pt になる。したがって、例えばA4判に1行40文字とするならば、A4判の幅210mmから 10pt×40 を引いた長さの半分を左右のマージンとすればいい。
一方、
#set par(first-line-indent: 1em, justify: true, spacing: 1em, leading: 1em)
とすると、段落間 spacing も行間 leading も10ptになるので、行送りは20ptになりそうに思うが、そうはならない。これはTypstの認識する文字の高さが10ptでないからである。例えば
#context{ measure("あ") }
をコンパイルすると、原ノ味フォントでは (width: 10pt, height: 7.29pt) と表示されることから、高さは 7.29pt である。したがって、#set par(spacing: 1em, leading: 1em) で10行を組めば、高さは 7.29pt×10 + 10pt×9 になる。文字の高さはフォントによって異なり、"Hiragino Mincho ProN" では 7.43pt になる。
実はこの 7.29pt などという文字の高さは「大文字の高さ」(cap-height)で、Typstのデフォルトの設定 #set text(top-edge: "cap-height") に因むものである。
日本語フォントでは正方形の仮想ボディの下から12%のところにベースラインがあるのが一般的なので、#set text(top-edge: 0.88em) と固定値に設定すれば、和欧で別フォントを設定している場合でも、行送りが一定になる。[top-edge を固定値に設定できることをご教示いただいたおかげで以前の記述よりずっと単純化できました。感謝]
これらのことを考慮して、例えば10pt、行送り1.73emで、本文40文字×40行をA4判に組むには、次のようにすればよいであろう。
#let width = 210mm
#let height = 297mm
#let fontsize = 10pt
#let xmargin = (width - 40 * fontsize) / 2
#let ymargin = (height - (1.73 * 40 - 0.73) * fontsize) / 2
#set page(
width: width,
height: height,
margin: (x: xmargin, y: ymargin),
numbering: "1",
)
#set text(lang: "ja", font: "Harano Aji Mincho", fontsize,
top-edge: 0.88em)
#set par(first-line-indent: 1em, justify: true,
spacing: 1.73em - 0.88em, leading: 1.73em - 0.88em)
ただ、top-edge を調節したために、微妙にバランスが崩れる場合がある。例えばルビを振るパッケージ rubby を使う場合に、設定で dy: -0.16em くらいにしないとルビが離れすぎる。また、表組みは #show table: set text(top-edge: 0.76em) くらいに設定しないと文字の上が広くなりすぎる。
2段組にする場合でも
#set page(columns: 2) #set columns(gutter: 2em) // 段間隔
のように段間隔を調節して、各段の幅が全角幅の整数倍になるようにしなければならない。
LaTeXと比べて未完成の部分
和欧混植の仕組みが基本的に未実装である。上で採用した欧文フォントのフォールバックとして和文フォントを指定する方法では、例えば“ダブルクオート”は欧文フォントにも含まれているので全角扱いできない(Unicodeの「東アジアの文字幅」問題、『LaTeX美文書作成入門』第9版p.199参照)。和欧文のサイズ調整もできない。例えばLaTeXの(lt)jsarticleなどでは和文フォントサイズを欧文より少し小さくしているし、jlreqドキュメントクラスではまったく独立に指定できる。これらをTypstで実現するには、正規表現を使って例えば
#show regex("[\p{scx:Han}\p{scx:Hira}\p{scx:Kana}]"): set text(font: "Harano Aji Mincho", size: 0.925em)
のようにすることが考えられる。ただ、これでは約物(句読点・括弧類)の組版ルール(日本語組版処理の要件の例えばFigure 46参照)が正しく適用されない(「「あ」「い」、「う」」のように括弧や句読点が並ぶ例をタイプセットしてみればわかる)。提案されている Font Unicode Range の実装が待たれる。
なお、これは正規表現に限らず、#show "、": "," 等で句読点を置換する際にも生じるので、気をつけなければならない。
段落の最初の全角下げが最初の段落に適用されない。#set par(first-line-indent: 1em) と指定しても、各セクション2番目の段落からしか全角下げされない。これは欧文組版の一般的なルールであるが、それがハードコードされてしまっている。上に挙げたスタイルでは見出しに par(text(size: 0pt, "")) のようなダミーの段落を入れるというハックを使っているが、見出しのない文章では困るし、ページの最後が見出しになることが避けられない。[この不具合は Support first-line-indent for every paragraph #5768 で報告されてから2年近くを経て、ようやく解決されたようだ。次のリリースでは直っているはず。]
日本語組版処理の要件 3.1.5 行頭の始め括弧類の配置方法で、LaTeXの(lt)jsarticleなどはFigure 71の①の組み方に統一しているが、Typstの現状では段落頭で全角半アキ、段落途中で天ツキになってしまう。
以上に関連する日本語の組版ルールの解説を別に書いたので参照されたい。
和欧間のアキ(LaTeXの \xkanjiskip)は入るが、和文と数式の間にはアキが自動で入らない。数式に限らず、例えば A-B を途中で改行されたくないので #box[A-B] のように箱に入れたものも、和文との間にアキが入らない。とりあえずは半角空白を入れるので十分であろう(→ Typstで和文と数式の間の空きをどうにかしたい話)。
句読点のブラ下げ組ができない(これは需要が少ないと思われる)。
ルビや割注については roadmap に載っているが未実装である。ただし rubby というパッケージが開発されている(上に述べたようにデフォルトではルビと親文字の位置関係が正確でない)。typst-js でも ruby[親文字][よみ] という関数を実装した。
縦組ができない。
参考文献の並べ方は引用順にしかできないようなので、分野/ジャーナルによっては困るかも。
索引は in-dexter というパッケージがある。日本語に対応していないと思ったが、#index(display: "索引")[さくいん] のようにすれば、何とかなりそうである。
あと、欠点ではないが注意すべき仕様として、和文文字列の途中で改行すると欧文スペースが挿入されるので、長い段落も1行で書かなければならない。
参考
- 公式ドキュメント: Typst Documentation
- 非公式日本語ドキュメント: Typstについて(特に日本語組版情報が役に立つ)