📝

Typst 0.12.0 の内容を早めに深堀り

2024/10/19に公開

はじめに

本記事では、2024/10/19 にリリースされた Typst 0.12.0 の新機能や変更点を紹介します。

ピックアップ

多段組の文書にて、浮動図を段抜きで置けるようになった

公式でも目玉として取り上げられている機能追加です。v0.11 以前では多段組の本文中に #figure() を指定しても、1列の中で浮動図を置くことしかできませんでしたが、 v0.12 では figure()scope プロパティに "parent" を指定することで、段をぶち抜きつつ浮動図を置けるようになりました。


浮動図を段抜きで置く例。公式ブログ記事より。

余談ですが、本機能の実現のために裏側のレイアウトエンジンを再実装したそうです。浮動図を横に置き、図に合わせてテキストを流し込む機能も将来的には見据えているとのこと。追加されるのが楽しみですね。

Typst CLI における PDF 出力での絵文字が正式にサポートされた

今まで Typst CLI にて #emoji.snowman などの記法を用いて絵文字を出力すると、下図左のように線だけの表示となってしまっていました。そのため v0.11 時点では svg-emojis パッケージを用いるなどの回避が必要でしたが、v0.12 で下図右のように適切に表示できるようになりました。カジュアルなスライドを作成するときなどに重宝しそうですね。

なお、筆者環境では #emoji.snowman ではなく (U+26C4) をそのまま記述しても正常に表示されました。


絵文字のレンダリング結果。左: v0.11.0, 右: v0.12.0。

段落に行番号を振れるようになった

par.line 関数numbering プロパティを指定することで、段落の余白に行番号をふることができるようになりました。主に学術論文などでのユースケースを想定しているようです。


段落に行番号をふる例。公式ブログ記事より。

  • デフォルトは文の開始側(left-to-right な文書なら左側)に番号がつきます。 number-margin プロパティで挙動を変更できます。
  • numbering-scope プロパティを指定すると、「文書全体を通してインクリメントされる」か「ページごとにリセットされる」かの挙動を変更できます。

【破壊的変更】段落間空白が par() 関数のプロパティから直接指定できるようになった

今まで段落間の空白を指定するときは

#show par: set block(spacing: 2em)

などとする必要がありましたが、v0.12 では、新たに par() に追加された spacing プロパティを用いて

#set par(spacing: 2em)

と設定する方式となりました。

本変更は破壊的変更として扱われているため注意が必要です。前者で段落間空白を設定していた人は、後者で設定し直すようにしましょう。

【破壊的変更】ブロックレベルの要素が block() のプロパティの影響を受けるようになった

list(), grid(), stack() などで作られるブロックが、軒並み block() 関数に指定されているプロパティの影響を受けるようになりました。従来とは異なる挙動のため、既存の文書のレイアウトが崩れる可能性があります。

#set page(height: auto)
#set block(stroke: 1pt + red, spacing: 100pt)

#lorem(20)

#lorem(20)

- Poem
  - Roses are red.
  - Violets are blue.


set block で block のプロパティを変更したときの挙動の変化。左: v0.11.0, 右: v0.12.0。

ブロック直後の改行を抑制できるプロパティが追加された

block.sticky プロパティを使うことで、ブロック直後の改ページを抑制できるようになりました。見出し直後の改ページを避けたいケースなどで有用です。

import 構文のバリエーション追加

  1. 入れ子になっているモジュール構造において、孫の要素を直接インポートできるようになりました。

    // v0.11 以前では以下のように書く必要があった
    #import "@local/my-classfile:0.1.0": component; #import component: colors
    
    // v0.12 からはこう書ける
    #import "@local/my-classfile:0.1.0": component.colors
    
  2. インポートする要素をカッコで囲むことができるようになり、その結果、複数行にまたがってインポート文を書けるようになりました。インポートしたい関数やモジュールが多いとき便利そうです。

    #import "@local/my-classfile:0.1.0": (
        component,
        layout,
    )
    

std モジュールの追加

Typst には様々な組み込み関数が定義されており、中には text()align() といった使用頻度の高い英単語もあります。そのため、Typst でプログラミングを行うときに意図せず組み込み関数を別の変数で上書き(シャドーイング)してしまうことがありました。

// `align` 引数を省略したら中央揃え、明示的に指定したらその align で揃えるような関数を定義したい。
// しかし、以下は組み込み関数の `align()` を引数の `align` で上書きしてしまっているため、意図した挙動にならない。
#let myalign(align: center, body) = align(align, body)

// よって、名前を変えるなどして回避する必要があった
#let myalign(align_: center, body) = align(align_, body)

// キーワード引数名が "align" とならないのはちょっとイケてない…
#myalign(align_: right)[Example Text.]

v0.12 では std というモジュールが標準で使えるようになり、この問題が解決されました。

// `align` は上書きされるが `std.align` はそのまま使える
#let myalign(align: center, body) = std.align(align, body)

// スムーズに "align" という名前のキーワード引数が使える!
#myalign(align: right)[Example Text.]

パフォーマンス・ファイルサイズの改善

新機能ではありませんが、このあたりも地味に嬉しい改善点です。

  • レイアウトエンジン(テキストや図などを紙面に配置する処理)がマルチスレッドで動作するようになりました。pagebreak() 関数などによる明示的な改ページが行われている箇所からの配置を並列で行うことができます。大規模な文書でのパフォーマンス改善が期待できます。

  • 段落の両端を揃える paragraph justification という処理が高速化されました。短い段落が多い場合に効果が高く、最大6倍ほど高速になるとのことです。

  • フォントのサブセット化の方法を改善することで、PDF 出力のファイルサイズが少なくなりました。地味に嬉しい変更ですね。

その他の変更

変更点が非常に多いため、ここでは機能追加に関するものを中心に一部を取り上げます。バグ修正などは割愛しますので、全ての変更点が知りたい方は公式の Changelog を参照してください。

レイアウト関連

  • place.flush() 関数の追加

    • #place.flush() を呼び出すことで、それまでの浮動図を全て表示してから以降の contents を表示させることができます。
  • skew() 関数の追加

    • scale()rotate() と合わせれば任意の Affine 変換が行えます。
  • page.header / page.footer プロパティに auto が指定できるようになった

    • auto を指定すると、page.numberingpage.number-align プロパティに応じたページ番号が自動で付与されます。
    • 挙動としてはプロパティ省略時の挙動と同じですが、v0.11 以前は一度明示的に指定した後にデフォルトの挙動に戻せませんでした。 auto の追加により、デフォルトに戻すことが可能となりました。
  • repeat.gap 及び repeat.justify プロパティの追加

    • ピリオドなどを繰り返す際、文字間の余白を明示的に指定できるようになりました。
      また、横幅に合わせた伸長を行うかどうかも指定できるようになりました。
  • block, image, rect, square, ellipse, circleheight プロパティに fr 単位の長さが指定できるようになった

    • fraction (fr) は親要素の長さを分割するときの比率を示す単位で、グリッドの幅を均等にする際などに用います。 1frheight に指定したブロックを2つ並べれば、2ブロックが同じ高さになるように隙間を埋めてくれます。
    具体例
    #set page(width: 200pt, height: 200pt, margin: 10pt)
    
    #block(width: 100%, height: 1fr, fill: red.lighten(80%), radius: 5pt)[
      #align(center + horizon)[#lorem(5)]
    ]
    
    #block(width: 100%, height: 1fr, fill: blue.lighten(80%), radius: 5pt)[
      #align(center + horizon)[#lorem(5)]
    ]
    

  • scale() 関数の x, y プロパティに(相対値ではない)長さを直接指定できるようになった

    • 「横幅を3倍に拡大する」といった指定に加え、「横幅が 300pt になるよう拡大する」という指定ができるようになりました。
  • block.aboveblock.below の値が context 式中で取れるようになった

文字組み関連

  • デフォルトフォントが "Libertinus Serif" になった

    • もともとのデフォルトであった "Linux Libertine" の後継フォントです。
    • この変更により、組版結果が若干変わる可能性があります。
  • 利用できないフォントファミリーを指定した場合に警告を発するようになった

    • 今までは利用できないものを指定しても、単に無視していました。
  • スマートクォート機能のアルゴリズムを改善した

  • text.costs プロパティを追加し、行分割アルゴリズムに置けるコスト関数の重みをカスタマイズできるようにした

    • 以下のコストごとの重みを比率で指定できます。
    • hyphenation(1単語をハイフネーションで分割するコスト)
    • runt (段落の末尾が1単語で終わるコスト)
    • widow (段落の最終行だけが次のページに置かれるコスト)
    • orphan (段落の最初の行だけが前のページに置かれるコスト)
  • コードブロックのハイライト言語に「Typst の数式モード」が指定できるようになった

    • 言語に typm を指定すれば、Typst の数式部分だけを書いてハイライトさせることができます。
  • 以下の言語の基本的な国際化 (basic i18n)

    • ガリシア語
    • カタロニア語
    • ラテン語
    • アイスランド語
    • ヘブライ語
  • 一部の言語の "hyphenation duplication" を実装

    • 具体的には以下の言語です。
      • チェコ語
      • クロアチア語
      • 低地ソルブ語
      • ポーランド語
      • ポルトガル語
      • スロバキア語
      • スペイン語
    • これらの言語では、ハイフネーションを行うときに行末だけでなく行頭にもハイフンを置く必要があるそうです。 https://github.com/typst/typst/issues/3235
  • smallcaps()showset で指定できる関数 (element function) になった

    • smallcaps() を使うときだけフォントを変える、といったことが可能になります。
  • raw.theme プロパティnone を指定することで、シンタックスハイライトをオフにできるようになった

  • text.stylistic-set プロパティに複数の数字が指定できるようになった

数式

  • ブロックレベルの数式が複数ページにまたがるようになった

    • この挙動は show math.equation: set block(breakable: false) でオフにできます。
  • 行列やベクトルの大きさがより一貫するようになった

    • 詳しくは把握しきれていませんが、添字などによる高さの違いの影響を受けづらくなったようです。


      行列を組んだときの様子。カッコの大きさの違いに注目。左: v0.11.0, 右: v0.12.0。

  • stretch 関数 が追加され、等号や矢印などのグリフを伸ばせるようになった

    • $ H stretch(=)^"define" U + p V $ とすることで、"define" の幅だけ伸びた等号を作ることができます。
    • 引き伸ばせるグリフは一部のみで、数式フォント依存です。
  • mat.delim, vec.delim, cases.delim プロパティが、デリミタまたはフェンスとみなせるいかなる Unicode 文字も受け付けるようになった

    • フェンスとはたとえば "|" (U+007c) のような文字です。
    • ただし、 delim: "||" といった指定はできなくなりました。 delim: bar.double などで代替する必要があります。
  • vec.align, mat.align プロパティが追加され、行列やベクトルの要素の揃え方を指定できるようになった

    • 整数で構成されたベクトルなどは右揃えで書くと見栄えが良さそうです。
  • underparen, overparen, undershell, overshell 関数の追加

    • underbrace 系の仲間です。
    • "shell bracket" とはいわゆる亀甲括弧 〔〕 です。
  • ~ が二項関係子として解釈されるようになった

    • 今まで tilde.op と書いていたところのショートハンドとして ~ が使えるようになります。
    • 逆に単なるチルダとして書いていた部分も tilde.op として解釈されてしまうので注意。

その他、記法・組版周りの変化

  • #set document() ルールの制限が緩和され、文書の冒頭以外にも書けるようになった

  • list(), enum(), term() における spacing プロパティが、tight list のときにも反映されるようになった

  • tight list において、リスト前の余白の付け方が変わり、段落が先行しているときのみ余白がタイトになる仕様になった

  • quote() 要素が locatable(typst query などで検索できる要素)になった

  • 複数行にまたがる見出しの外観調整のため、heading() 関数に hanging-indent プロパティ が追加された

    • デフォルトの見出しも改善され、複数行にまたがるときは "1." などのナンバリングの幅だけ自動でインデントが付くようになりました。
  • path() および polygon() 関数にfill-rule プロパティが追加された

    • 星型のように辺が交差する多角形を塗るときの挙動を、"non-zero" または "even-odd" の2値で調整できます。
  • decimal 型の追加

    • 今まで少数を表す型は浮動小数点数の float 型のみですが、固定小数点数の decimal 型が新たに追加されました。小数の計算を厳密に行うことができます。
  • arrayへのメソッド追加

    • to-dict(): ((k1, v1), (k2, v2), ...) の形の配列を (k1: v1, k2: v2, ...) にするやつ。
    • reduce(): fold メソッドと似ているが、初期値を最初の配列の要素とするやつ。
    • windows(): (1, 2, 3, 4, 5,) から ((1, 2, 3), (2, 3, 4), (3, 4, 5)) を作るやつ。
  • array.zip() メソッドに exact 引数を追加

    • exact 引数に true を指定すると、組み合わせる2配列の要素の個数が一致しないときエラーになります。 false を指定したときは従来通り、長い方のあまりが無視されます。

エクスポート

  • PDF/A の部分的なサポート

    • エクスポート時に PDF/A を有効にすることで、より長期保存に適した形での PDF を出力できるようになりました。
      • CLI では --pdf-standard a-2b オプションを指定することで有効化できます。
    • 現時点では PDF/A-2b のみサポートしています。
  • page.fill プロパティnone にすると、PDF や SVG でエクスポートする際にも背景が透過するようになった

    • 従来の挙動(PDF での背景を透明に、PNG や SVG での背景を白にする)を指定したいときは auto を設定します。

CLI・ツール

  • --pages オプションの追加

    • エクスポートする際に特定のページ番号を指定できるようになりました。
  • --package-path, --package-cache-path オプションの追加

  • --ignore-system-fonts フラグの追加

    • システムフォントの読み込みを無効化します。システム依存の要素を減らし、より再現性の高い文書を作成するのに有効です。
  • 複数の画像ファイルにエクスポートするとき、 t (total pages), p (current page), 0p (0パディングされた page)が出力ファイル名に指定できるようになった

おわりに

約5ヶ月ぶりのバージョンアップということもあり、変更点が非常に多かった印象です。0.12.0-rc1 が出た当初から本記事の準備をしていたのですが、目を引く機能追加・不具合修正が非常に多く、作業をまとめるのも大変でした。今回は大規模な再実装があったためリリースが遅くなったとのことなので、次回のバージョンはもう少し早めに来るかもしれません。

本記事で誤りを見つけた方は、コメントにてご指摘ください。

参考資料

Discussion