Typstで遊ぼう

heroimage

この記事は Typst で書いていたものの写しであり書きかけであり更新中です。

Typstで作成したPDF: https://discord.ubanis.com/typst-manual.pdf

kawaiiロゴ: https://gist.github.com/fenjalien/1463a19ba2b91d061ed35e295494e0b3

Typst で作る表紙の例

front

色々できないことも多い(縦書きなど)

以下はTypstで作成したドキュメントをMarkdownにしたものです。


はじめに

Typst とは

Typstは、科学技術文書の作成に特化した、現代的な組版システムです。Markdownのようにシンプルな構文と、LaTeXのようにパワフルで柔軟な表現力を兼ね備えています。リアルタイムでの高速なコンパイルが特徴です。

Typst の利点

  • 学習の容易さ: 直感的で覚えやすい構文を採用しており、初心者でもすぐに使い始めることができます。
  • 高速なコンパイル: 変更を即座にプレビューに反映するため、トライ&エラーが容易です。
  • 強力なスクリプティング: 変数、関数、ループ、条件分岐といったプログラミング機能が組み込まれており、動的で再利用性の高いコンテンツを作成できます。
  • 統一されたエコシステム: パッケージ管理機能が内蔵されており、外部のライブラリやテンプレートを簡単に導入できます。

インストール

Typstは、Webアプリケーションとしてブラウザ上で利用する方法と、ローカル環境にインストールして利用する方法があります。詳細は公式サイトを参照してください。

以下は代表的なパッケージ管理ソフトでのインストール方法です。

winget(Windows)

Terminal window
winget install --id Typst.Typst

scoop(Windows)

Terminal window
scoop install typst

Cargo

Terminal window
cargo install --locked typst-cli

Snap(Linux)

Terminal window
sudo snap install typst

mise

Terminal window
mise use -g typst

はじめての Typst

まずシンプルな以下のような内容のファイルをexample.typという名前で保存します。

example.typ
= 見出しです
段落です。
- リスト1
- リスト2
- リスト3

以下のコマンドで対象のTypstファイルからpdfを出力します。

Terminal window
typst compile example.typ

出力されたpdfファイルを開いてみると以下のようになっているはずです。

example.pdf

以下のコマンドは対象のTypstファイルを監視して変更があるたびにコンパイルをしてpdfを更新し続けます。

Terminal window
typst watch example.typ

この状態でexample.typを編集するたびにpdfファイルが更新されることになります。

vscode 拡張 Tinymist Typst の導入

tinymist

vscode上でTypstを快適に編集するための拡張機能Tinymist Typstを導入すると、構文ハイライトや補完機能が利用可能になります。 リアルタイムプレビュー機能もあり、Typstのドキュメントを編集しながら即座に結果を確認できます。

vscode

このようにとても編集しやすいのでぜひ導入しましょう

プレビュー画面の表示

このアイコンをクリックする

vscode上の右上にある虫眼鏡のついたプレビューアイコンをクリックすると現在のファイルのリアルタイムプレビュー画面が右側に表示されます。 プレビュー画面の文などの要素をクリックすると該当箇所のファイルの行へ移動でき、 ファイル内の要素をクリックするとプレビュー画面がその位置へスクロールします。

外部ブラウザで開く

プレビュー画面の右上にある四角に右上矢印のアイコンをクリックするとプレビュー画面は外部ブラウザに表示されるようになります。 クリックでジャンプする機能はブラウザ上でもそのまま利用できます。


基本なマークアップ

見出し

= の数で見出しのレベルを表現します。

= 章 (レベル1)
== 節 (レベル2)
=== 項 (レベル3)

テキストの装飾

Typstでは、簡単な記号でテキストを装飾できます。

強調

*強調*

斜体

_イタリック_

下線

#underline[下線]

打ち消し線

#strike[打ち消し線]

URL

URL https://example.com

改行・エスケープ文字

\を使います。

このように改行できます。\ 文中では\ スペースを一つ空けます。\
\$←のようなTypstで利用されている文字を書きたい場合のエスケープ文字としても利用されます。

コードブロック

`(バッククォート1つ)で囲んだ文字はインラインコードになります。

`これはインライン`です。

```(バッククォート3つ)で囲んだ行はコードブロックを形成します。言語を指定するとシンタックスハイライトが適用されます。

//これはブロックです。
//シンタックスハイライトが適用されています。
#include <stdio.h>
void main(int argc, char *argv[])
{
char *str = "hello world!";
puts(str);
}

リスト

-(ハイフン)や+(プラス)でリストを作成します。インデントすることでネストも可能です。

- 順序なしリスト
- ネストされたリスト
- 順序付きリスト
+ 番号は自動で振られます
+ 2番目の項目

用語リスト

/ Typst : 今注目されている新しい組版システム。2019年に開発が開始され、2023年3月にベータ版が一般公開された。Rustで書かれており、シンプルな文法やコンパイルの速さが利点。
/ Rust : メモリ安全性を保証しつつ、低レベルのシステムプログラミングが可能な言語。所有権システムを採用しており、ガベージコレクタ#footnote("コンピュータプログラムが動的に確保したメモリ領域のうち、不要になった領域を自動的に解放する機能です。")がなくてもメモリリークやデータ競合を防ぐ。
/ ねこ : @nyan-image

terms

数式

$ で数式を囲みます。1行でインライン数式、複数行でブロック数式になります。

/ インライン数式 : $E = m c^2$ はインライン数式です。
/ ブロック数式 :
これはブロック数式です。
$
sum_(i=1)^n i = (n(n+1)) / 2
$

formula

参照

<ラベル名> で要素にラベルを付け、@ラベル名 で参照します。数式や図、セクションなど、あらゆる要素にラベルを付けられます。

#figure(
image("../img/nyan4.jpg", width: 3cm),
caption: [参照されるねこ],
) <nyan-image>
#align(center)[@nyan-image をこのように参照できます。]

ref


関数

Typst における関数

#で始まる文は関数を表します。 内蔵の関数や以下のように#letを使って自作の関数を定義し利用することができます。

#let test(body) = { [渡された文字列は#body] }
- #test("テスト")
- #test[#text(fill: red, weight: "bold", [test])]

func01

引数の渡し方は複数あります。以下はbodyに引数が割り当てられます。

#test("テスト")

このようにマークアップ文全体をを渡すこともできます。これも自動的にbodyに割り当てられます。

#test[#text(fill: red, weight: "bold", [test])]

以下のように複数の引数がある場合も自動的にbodyに割り当てられます。引数の初期値も設定でき省略時にこれが参照されます。

#let test2( var: false, body) = {
if var {
[varはTrueです。]
} else {
[varはFalseです。]
}
body
}
- #test2[引数]
- #test2(var: true)[引数]

func02

{ }で区切られたブロック内はコードブロックなので関数に#をつけずに呼び出します。マークアップ文を使う場合は[ ]で囲みます。

  • コンテントブロック(Content block)[...] : 関数は#をつけて使う。#text(fill: red)[*Hey* there!]
  • コードブロック(Code block){...} : 関数は#をつけずに使う。text(fill: red)[*Hey* there!]

マークアップ関数の一覧

目次

// target で作りたい目次の要素を指定する。`depth`は目次を作るレベルの深さを数値で指定する。
#outline(target: heading, depth: 2)

outline

水平方向のスペース

#h(1fr)

垂直方向のスペース

#v(0.2em)

中央揃え

#align[center](テキスト)

取り消し線

#strike[文字列]

下線

#underline[文字列]

大文字化

#upper[apple]

小文字化

#lower[APPLE]

スモールキャピタル

#smallcaps[Smallcaps]

上付き文字

2#super[2]

下付き文字

2#sub[2]

ハイライト

#highlight[文字列]

引用

#quote[block: true, attribution: [名前]](引用文字列)

囲み

#box[stroke: 0.5pt + black, outset: 0.3em](文字列)

ダミーテキストを 10 単語生成

#lorem(10)

今日の日付を取得

#datetime.today()

水平線

#line(stroke: 1pt + black, start: (5%,0%), end: (95%,0%))

改ページ

#pagebreak()

この関数から下は次のページになります。

スクリプト

Typstはスクリプト言語としての機能も持っています。変数、ループ、条件分岐などを利用して、コンテンツを動的に生成できます。

for 関数

#let users = ("Alice", "Bob", "Charlie")
#for user in users {
[こんにちは、#text(fill: red)[#user] さん!]
}

func03

if 関数

#let a=32
#let b=64
#align(center)[#if a < b { [aはbより小さいです。] }]

単純な画像表示関数を定義

#let nyan(size: 5cm) = {image("../img/nyan4.jpg", width:size)}
#align(center)[#nyan(size: 2.5cm)]

image 関数

#image() 関数で画像を挿入します。#figure() と組み合わせることで、キャプションや図番号を付与できます。

#figure(
image("../img/nyan4.jpg", width: 3cm),
caption: [ねこです]
)

func04

図形関数

#rect()#circle() などの関数で、基本的な図形を簡単に描画できます。

#align(center)[
#grid(columns: 3,
[#square(size: 1cm, fill: blue)],
[#circle(radius: 0.5cm, fill: red)],
[#polygon(
(0cm, 1cm), (0.5cm, 0cm), (1cm, 1cm),
fill: green,
)]
)]

func05

色の指定方法

関数の引数にcolorがある場合、色を指定できます。fillは塗りつぶしです。strokeは枠線です。3pt + blackのように+で属性を追加できます。

#rect(fill: red, stroke: 3pt + black, radius: 1em)
#line(stroke: 3pt + green, start: (0%,0%), end: (50%, -4em))

func06

rgb("#000000")のようにRGB値で指定することもできます。透明度を含めたrgb("#000000aa")のような指定方法もあります。

#grid(columns: 2,
polygon(
(0cm, 1cm), (0.5cm, 0cm), (1cm, 1cm),
fill: rgb("#0000cc"),
),
circle(radius: 0.5cm , fill: rgb("#0000cc55"))
)

func07

グラデーションを指定するにはgradientを利用します。グラデーションの種類をgradient.linearのように指定します。 グラデーションの方向はangle: 90degのように角度で指定します。

#rect(fill: gradient.linear(red, blue,angle: 90deg), radius: 1em,)

func08

table 関数

#table() 関数で柔軟な表を作成できます。

#table(
columns: (auto, 1fr, 1fr),
stroke: 0.5pt,
align: (left),
[*No.*],[*項目*],[*説明*],
[1], [Typst], [組版システム],
[2], [Markdown], [軽量マークアップ言語],
[3], [LaTeX], [組版システム],
)

func09

段組

#columns() 関数で多段組を実現できます。#colbreak() で段を区切ります。

#import "@preview/roremu:0.1.0": roremu
#columns(2)[
#roremu(100)
#colbreak()
#roremu(100)
]

columns

このように長い文章は折り返され、指定した段数で区切られます。 #lorem()(ここで使っているのは外部パッケージの#roremu)は指定された文字数の例文を表示する関数です。

grid 関数

#columns()関数よりも柔軟なレイアウトをしたい場合利用できます。

#set rect(
inset: 8pt,
fill: rgb("e4e5ea"),
width: 100%,
)
#grid(
columns: (60pt, 1fr, 2fr),
rows: (auto, 60pt),
gutter: 3pt,
rect[Fixed width, auto height],
rect[1/3 of the remains],
rect[2/3 of the remains],
rect(height: 100%)[Fixed height],
grid.cell(
colspan: 2,
image("../img/nyan4.jpg", width: 100%),
),
)

func10

footnote 関数

脚注をつけることができます。

Astro#footnote("SSGだけでなくSSRもできる静的サイトジェネレーター")もありますがTypstは使えません。

要素の移動や回転

ある要素を移動させたい場合以下のような関数が利用できます。他の要素の位置に注意して使用してください。

特定位置への要素の表示

#place関数を使用することでページ上の特定位置に要素を表示することができます。要素の中ならばその要素の相対位置になります。

#block関数でブロック領域を作りその中で#place関数を使ってみます。灰色の部分がブロック領域です。

#let mybox(body, color: white)={
box(stroke: 1pt, fill: color, inset: 0.5em, body)
}
#block(height: 3cm, width: 100%, fill: gray)[
#place(top+right)[#mybox([右上です], color: aqua)]
#place(top+center, dy: 2em)[#mybox([中央上から2文字下です], color: yellow)]
#place(bottom+right, dx: -0.5cm, dy: -0.5cm)[#mybox([右下から左に0.5cm上に0.5cmの位置です], color: green)]
]

place

現在位置から指定位置への要素の移動

#move関数を使用すると要素の現在位置から指定された位置に要素を移動できます。

#let mybox(body, color: white)={
box(stroke: 1pt, fill: color, inset: 0.5em, body)
}
#move(dx: 3cm)[#mybox([移動した要素], color: teal)]
#rect(inset: 0pt, move(
dx: 6pt, dy: 6pt,
rect(
inset: 8pt,
fill: white,
stroke: black,
[`#rect`の中で入れ子になって移動しています]
)
))

move

要素を回転させる

#rotate関数を利用して要素を指定した角度に回転させることができます。

#set text(fill: white)
#align(center,block(fill: black, width: 100%,
[
#place(left + horizon, dx: 6em)[
#rotate(-70deg)[*ローテート!*]]
#rotate(-10deg)[
#rotate(45deg)[#block(radius: 100%, clip: true)[
#image("../img/nyan4.jpg", width: 3cm)
]
]
このように要素が
#rotate(30deg)[すべて]
指定された角度`deg`に回転します
#rotate(25deg)[
#move(dx: 7em, dy: -8em)[入れ子になっていても大丈夫です。]
]
]
]
))

rotate

ファイルの分割

#for 関数と #include 関数を使って分割されたファイルを読み込みします。

複数のファイルに分割することで項目ごとに編集管理しやすくできます。

// ファイルのパスを配列にする
#let chapters = (
"content/text-format.typ",
"content/heading.typ",
"content/list.typ",
"content/codeblock.typ",
"content/formula.typ",
)
= ここからchaptersが配列順にそれぞれ並ぶ
#for chapter in (chapters) {
include(chapter)
}

リストのループ

別ファイルからリストを読み込み#forループを利用して用語リストとテーブルに表示してみます。#table関数では..#forと書くことで配列を渡します。

import される Typst ファイル

#let locales=(
( name:"日本",str:"首都は東京です。",),
( name:"アメリカ",str:"首都はワシントンD.C.です。",),
( name:"フランス",str:"首都はパリです。",),
( name:"イギリス",str:"首都はロンドンです。",),
( name:"ドイツ",str:"首都はベルリンです。",),
( name:"中国",str:"首都は北京です。",),
( name:"韓国",str:"首都はソウルです。",),
)

コード

#import "../import/locales.typ": locales
#for c in locales {
terms.item(text(c.name),text(c.str))
}
#table(
columns: (auto, 1fr),
stroke: 1pt+gray,
align: (left),
[*国名*],[*首都*],
..for (name,str) in locales {
(name,str)
}
)

func11 func12

外部データの読み込み

Typstは以下のデータを読み込むことができます。

  • cbor
  • csv
  • json
  • read
  • toml
  • xml
  • yaml

読み込むデータ

[
{
"name": "ねこ",
"path": "../img/e670ceab9f15d95ce92d718ba046aaac3142aac3.jpg",
"description": "クリスマスにゃんこだにゃん"
},
{
"name": "きつね",
"path": "../img/2022-0106-01.jpg",
"description": "見せつけてくるきつね"
},
{
"name": "ティファ",
"path": "../img/c2b7d960c6205cb3d973fe0b3c51b477ecf75202.jpg",
"description": "FF担当"
},
{
"name": "ブリジット",
"path": "../img/1e4697102be08c9174a60f109b4e6558e838bf81.jpg",
"description": "格ゲー"
}
]

コード

#let columnimage(data) = columns(
2,
for img in data{
block(
width: 100%,
clip: true,
square(
radius: 1em,
width: 100%,
height: auto,
inset: 0.5cm,
fill: if img.name == "ねこ" {
yellow
} else {
aqua
},
highlight(fill:rgb("#77ffff"), text(strong(underline(img.name))))
+"\n"+
text(img.description)
+align(center, rotate(8deg, image(img.path, fit:"cover", width: 80%))),
)
)
}
)
#columnimage(json("../json/animals.json"))

スタイリング

#set を利用したスタイリング

#setを利用して要素のスタイルを設定できます。

parは段落を設定します。textはテキストを設定します。

#import "@preview/roremu:0.1.0": roremu
#set par(spacing: 1em, leading: 1em)
#set text(weight: "bold", size: 0.8em)
#columns(2)[
#roremu(400)
]

set-01

#setの適用範囲はファイルの終端かブロックの終わりまでです。

#[
#set list(marker: [★], indent: 2em)
- ここは適用される
]
- こちらは適用されない

set-02

ページのスタイリング

#set page() ルールで、用紙サイズ、余白、ヘッダー、フッターなどを設定できます。

#set page(
paper: "a4",
margin: (x: 2.5cm, y: 3cm),
header: align(right)[Typst Manual],
footer: align(center)[#counter(page).display("1")]
)

#show を利用したスタイリング

#showを使用すると、要素のスタイルを細かくカスタマイズできます。 #[...]は無名のコンテントブロックです。

#[
#show heading: set text(fill: red)
= レベル1
== レベル2
=== レベル3
]
ブロックの外なので通常です
= レベル1
== レベル2
=== レベル3

show-01 show-02

コロン:の後に関数をつけてさらに細かくカスタマイズすることもできます。 itは要素の実体を表します。

#[
#show heading: it => [
#set text(fill: green)
#align(center)[#it]
]
= レベル1
== レベル2
=== レベル3
]

show-03

要素の中の特定要素をwhereで指定することもできます。

#[
#show heading.where(level: 2): it => [
#set text(fill: fuchsia)
#align(center)[#it]
]
= レベル1
== レベル2
=== レベル3
]

show-04

単純な文字列の置き換えは以下の方法が利用できます。

#block(stroke: 1pt + gray, inset: 5mm)[
#show "日本語": "nihongo"
日本語という文字列がこのように変化しています。
]

show-05

#showregexを利用して特定文字列を対象にすることもできます。

#block(stroke: 1pt + gray, inset: 5mm)[
#show regex("apple"): [ジョブズ]
apple computer
]

show-06

#block(stroke: 1pt + gray, inset: 5mm)[
#show regex("ジョブズ"): it => [
#rotate(30deg)[#strong(it)]
]
apple ジョブズ
]

show-07

#show:と with を利用して外部のテンプレートを利用する

#set#showで設定したスタイリングはそのファイル内かブロック内で有効になりますが、 これを外部ファイルに記述してそれを#importして利用することができます。

layout.typというファイルを作成し、#letを使って名前はなんでもよいのですがlayoutを定義します。

そして=に続くコードブロック内でスタイリングをします。

引数は自由に定義して問題ありません。コロン:の後に続く要素はデフォルト値になります。

layout.typ
#let layout(
body,
title: "Typstの使い方",
author: "ubanis",
pagesize: "a5",
column: 1,
fontname: "Noto Sans CJK JP",
fontsize: 8pt,
language: "ja",
) = {
// ドキュメントの設定
set document(
title: _title,
author: author,
)
// ページの設定
set page(
fill: none,
paper: pagesize,
flipped: false,
binding: left,
margin: (
top: 25mm,
bottom: 15mm,
inside: 15mm,
outside: 15mm,
),
columns: column,
numbering: "1",
)
// フォントの設定
set text(
font: fontname,
lang: language,
size: fontsize,
)
// 本文
{//このコードブロックはなくてもよい
body
}
}// layoutの終わり

必ず関数の最後の方にbodyを入れてください。

そしてこれを本体の文書から#importを使って読み込みます。

#import "layout.typ"の後に続く:はそのファイルから読み込む関数を指定します。*は全てを読み込むことを表しています。

特定の関数を読み込むならば#import "layout.typ": layoutのように指定します。

そしてその下で#show:を付けてlayout.with関数を呼び出します。

main.typ
#import "layout.typ": *
#show: layout.with(
title: "いろいろできそうなTypstで遊ぼう",
author: "ubanis",
pagesize: "a5",
column: 1,
fontsize: 9pt,
fontname: "BIZ UDPGothic",
)
= ここから本文です
`layout`で設定した要素がここに適用されます。
この部分全てがlayoutの引数`body`に入っています
- リスト1
- リスト2
- リスト3

コードにあるように#show: layout.with(...)以降のファイル内はlayout.typ#layout内で設定したスタイルが適用されます。

他に#include関数もあり、別ファイルの内容がそのまま同じファイル内に取り込まれるため以下のようにした場合も別ファイルにスタイルが適用されます。

#show: layout.with(...) // 省略
= ここから本文です
`layout`で設定した要素がここに適用されます。
この部分全てがlayoutの引数`body`に入っています
- リスト1
- リスト2
- リスト3
#include "next.typ" //このファイルの中身もlayoutのスタイルが適用される。

layout.typbodyの前にコンテンツを書けばそれはこの本文の前に置かれます。#outlineを使って目次を載せたり引数を活用して表紙を作成したりするのもよいでしょう。

// ここまで省略
// タイトルページ
{
v(3cm)
set text(size: 1.5em)
align(center, title)
align(bottom+center, author)
pagebreak()//改ページ
}
// 目次
{
set text(size:0.9em)
outline(
title: [目次],
depth: 2,
indent: 2em,
)
pagebreak()//改ページ
}
// 本文
{//このコードブロックはなくてもよい
body
}
}// layoutの終わり

外部パッケージ

codly コードブロック装飾

codly – Typst Universe
Codly is a beautiful code presentation template with many features like smart indentation, line numbering, highlighting, etc.
codly – Typst Universe favicon https://typst.app/universe/package/codly
codly – Typst Universe

以下のようにインポートと初期化を行うことでコードブロックのスタイルが変化します。

#import "@preview/codly:1.3.0": *
#import "@preview/codly-languages:0.1.1": *
#show: codly-init.with()

Rustの例

func13

一部分のハイライト

#codly(highlights: (
(line: 4, start: 2, end: none, fill: red),
(line: 5, start: 13, end: 19, fill: green, tag: "(a)"),
(line: 5, start: 26, fill: blue, tag: "(b)"),
))

func14

Rubby ルビをふる

rubby – Typst Universe
Add ruby (furigana) next to base text.
rubby – Typst Universe favicon https://typst.app/universe/package/rubby/
rubby – Typst Universe

初期化

#import "@preview/rubby:0.10.2": get-ruby
#let ruby = get-ruby(
size: 0.5em, // Ruby font size
dy: 0em, // Vertical offset of the ruby
pos: top, // Ruby position (top or bottom)
alignment: "center", // Ruby alignment ("center", "start", "between", "around")
delimiter: "|", // The delimiter between words
auto-spacing: true, // Automatically add necessary space around words
)

ルビのふりかた

ルビはRubbyを#ruby[り|よう][利|用]する。

func15

wrap-it 回り込み

wrap-it – Typst Universe
Wrap text around figures and content
wrap-it – Typst Universe favicon https://typst.app/universe/package/wrap-it/
wrap-it – Typst Universe

初期化

#import "@preview/wrap-it:0.1.1": wrap-content

使用例

#let wrap_fig = [
#figure(
image("../../img/nyan4.jpg",width:5cm),
caption: [画像],
)<fig:nyan4>
]
#let wrap_body = [#lorem(100)]
#wrap-content(wrap_fig, wrap_body,align: bottom + left, column-gutter: 1em)
* @fig:nyan4 *

func16

showybox 様々なボックス描画

showybox – Typst Universe
Colorful and customizable boxes for Typst
showybox – Typst Universe favicon https://typst.app/universe/package/showybox
showybox – Typst Universe

様々な枠線を作ることができるパッケージです。

初期化

#import "@preview/showybox:2.0.4": showybox

使用例

#showybox(
[Hello world!]
)

func17

#showybox(
frame: (
border-color: red.darken(50%),
title-color: red.lighten(60%),
body-color: red.lighten(80%)
),
title-style: (
color: black,
weight: "regular",
align: center
),
shadow: (
offset: 3pt,
),
title: "Red-ish showybox with separated sections!",
lorem(20),
lorem(12)
)

func18

#showybox(
frame: (
dash: "dashed",
border-color: red.darken(40%)
),
body-style: (
align: center
),
sep: (
dash: "dashed"
),
shadow: (
offset: (x: 2pt, y: 3pt),
color: yellow.lighten(70%)
),
[This is an important message!],
[Be careful outside. There are dangerous bananas!]
)

func19


付録

地震情報を掲載する

気象庁の地震情報を取得できるアドレス https://www.jma.go.jp/bosai/quake/data/list.jsonからjsonファイルを取得してテーブル表示します。

json ファイルの取得

Terminal window
wget https://www.jma.go.jp/bosai/quake/data/list.json

リストは1000件と長すぎるため表示する範囲はsliceで限定しました。

#let earthquake-list(num) = {
set text(
size: 0.8em,
)
let earthquakes = json("json/list.json")
[== 最近の地震 #num 件]
table(
stroke: 0.5pt,
align: left,
columns: (auto,auto,auto,auto),
[*地震発生時刻*], [*震源地*], [*マグニチュード*], [*最大震度*],
..for (at,anm,mag,maxi) in earthquakes.slice(0,num){
(at,anm,mag,maxi)
}
)
}
#earthquake-list(10)