💯

Typstで試験の解答欄を作ってみた

2024/08/07に公開1

面白そうだったので、answerbox.styっぽいものをTypstで実装してみました。

https://github.com/1STEP621/typst-anshere

使い方

Exampleを見ると大体わかります。
https://github.com/1STEP621/typst-anshere/blob/main/example/example.typ

#anshere((
  q(),
  q(),
  q-blank,
  q-break,

  ..(q(),) * 3,
  q-break,

  q(content: [#h(1fr)m / s]),
  q(content: [#h(1fr)T#h(10pt)/#h(10pt)F#h(1fr)]),
  q(label: [$2x + 1$]),
  q-break,

  q(counter-reset: 1),
  q(),
  q-blank,
  q-break,

  q(numbering-width: 50pt),
  q(hide-numbering: true)
))

概ねanshere()の中にq()q-breakq-blankを連ねていくような感じです。
q-breakで改行、q-blankで空白を作れます
q()の引数に色々渡せるようになっています。

  • content
    解答欄に書き込みできる
    h(1fr)でいい感じに余白を開けられます
  • label
    問題番号欄に書き込みできる
  • counter-reset
    質問番号を強制的に巻き戻せます
  • numbering-width
    問題番号欄の幅を変えられます
  • hide-numbering
    問題番号を非表示にできます
#anshere((
  ..(q(numbering: "a"),) * 4,
  ..(q-blank,) * 2,
  q-break,

  q(counter-reset: 1),
  q(),
  q(counter-skip: 1),
  q(),
  q(counter-skip: 1),
  q(),
  q-break,

  q(counter-reset: 1),
  q(),
  q(counter-skip: -1),
  q(),
  q(counter-skip: -1),
  q(),
  q-break,
))
  • numbering
    番号の振り方を変えられます
  • counter-skip
    番号をn個スキップできます できればcounter-resetよりこっちを使ったほうがいいと思います
#anshere((
  q(children: (
    q(),
    q(),
    q(children: (
        q(),
        q(),
    )),
  )),
))

#anshere(
  (
    q(children: (
      q(),
      q(children: (
        q(),
        q(children: (
          q(),
          q(),
        )),
      )),
    )),
  ),
  numberings: ("1", "1", "(1)", "あ", "a"),
)
  • children
    問題をネストして小問の小問を作れます。なお、この中ではq-breakやq-blankを作ることはできません。(すべて改行される)

anshereの引数にnumberingsを渡すと問題番号の形式を一括指定できます。

感想

最初はtableでcolspanとrowspanを計算して頑張ろうかなと思ったのですが挫折したので、gridをネストする形で実装してみました。
gridだから起こった問題として、行の高さがずれてしまうというものがありました。とりあえずゼロ幅スペースsym.zwsを常に表示することで、少なくともNoto Serif CJK JPやNoto Sans CJK JPでは高さが維持されるようにしましたが、フォントの組み合わせによってはまだずれます。ここはいつかtableを使ってしっかり直したいです...。

Discussion

清水団清水団

私も数学のテストでtypstで問題と解答作りました。