数学の文書をPandocで処理させる場合、定理等の記述をどうするか考える必要がある。LaTeXには定理環境があるが、 MarkdownやHTMLにはそういうマークアップは用意されていない。
目次
ソースとしてはMarkdownかLaTeX、ターゲットとしてはHTMLかLaTeXを考える。
LaTeX
標準で定理環境(を定義するコマンド)がある。amsthmパッケージを読むと機能が拡張されたりproof環境が使えるようになったりする。
例:
\newtheorem{theorem}{定理} \begin{theorem}[フェルマーの最終定理] 3以上の自然数 $n$ に対して、次を満たす整数 $x,y,z$ は存在しない: \[x^n+y^n=z^n, xyz\ne 0\] \end{theorem} \begin{proof} 読者の演習問題とする。 \end{proof}
例の中では定理環境の名前を “theorem” としたが、実際の環境の名前は人によって違うだろう。
HTMLでの表現
LaTeXでの環境に相当するものとしては、divを使うのが自然だろう。
<div class="theorem"> </div> <div class="proof"> </div>
「定理」や「証明」等の文字列を直接HTMLで書くか、CSSのcontent属性等を使って生成するかは、検討の余地がある。
Markdownでの表現
Markdown中でもHTMLタグを使えるので、HTMLと同様に書いても良い。
Pandocで処理させる場合は、Pandoc拡張でdivやspanをおしゃれに書ける。(他のMarkdownプロセッサーは知らない)
fenced_divs:
::: {.theorem} :::
bracketed_spans:
[foo]{.bar}
これらを駆使して自分だけの定理記法を作ろう!(そして自分だけのPandoc filterを書く羽目になる)
ちなみに、筆者の「週刊 代数的実数を作る」のソース(Markdown)では
<div class="theorem"> **定理**(フェルマーの最終定理). うんたらかんたら </div>
という形式で定理を書いていた(Pandoc filterなしでHTML出力してもそれなりの見た目になるようにするため)が、いざこれを解釈するPandoc filterを書こうとすると定理名の部分(例だと「フェルマーの最終定理」)の解釈が無駄に面倒になってしまった。せめて
<div class="theorem"> **定理**([フェルマーの最終定理]{.thmname}). うんたらかんたら </div>
という風に定理名の部分が要素となるようにしておくべきだった。
Pandoc filterを書く
Pandoc本体には定理環境を処理する機能はないので、定理環境の処理にはPandoc filterを使う必要がある。定理環境用の既存のfilterはいくつか公開されているが、既存の書き方では満足できない場合、Pandoc filterを自作する必要がある。
Pandocをガチで使うなら、Pandoc filterを書ける能力は必須である。
Pandoc本体はHaskellで書かれているが、Pandoc filterは外部コマンドとして起動されるので、好きな言語でPandoc filterを書くことができる。Pandoc filterを書くのにオススメな言語を3つ挙げる:
- Haskell: Pandoc自体にHaskellでPandoc filterを書くことを支援する関数が用意されている。
- Python: Pandoc filterを書くためのライブラリーがあるらしい。
- Lua: 最近のPandocではLuaで書かれたfilterを直接実行できるようになった。つまり、外部プロセス起動やJSON変換のコストが省ける。今後、簡単なフィルターはLuaで書くべきだろう。
筆者はこの記事に書いた定理環境以外にも、青空文庫形式のルビ(例:猫《ねこ》である)をHTMLや日本語LaTeXのルビに変換するフィルターをHaskellで書いて使っている。(この書き方ではルビの部分とその他の部分がPandocのAST上で区別されないので、パターンマッチや正規表現等で頑張って文字列処理をする必要がある。筆者はこのフィルターをLuaに移植しようと思ったが標準のstring.match等の文字列パターン機能が貧弱だったので断念した。)
Markdown→LaTeX
原稿をMarkdownで書いてLaTeX文書を得たい場合。
divタグを定理環境に変換することになる。
divタグをLaTeXの環境にするフィルターはすでにいくつか存在する:
出力に \begin{..} や \end{..} を挿入する際はPandoc ASTのRawBlockやRawInlineを使うことになる。
例に挙げたpandoc-latex-environment等は [RawBlock(“latex”, “\\begin{…}”] + content + [RawBlock(“latex”,”\\end{…}”)] という風に \begin{..} \end{..} を挿入しているが、proof環境でこれをやると出力されるLaTeXソース中で \end{proof} の前に1行空くため、「証明終わり」の記号の位置が変になる。
これを解決するには、 \end{proof} をブロックとして挿入するのではなく、証明の内容の最後の段落の末尾に RawInline(“latex”,”\\end{proof}”) を挿入するようにする。プログラムが複雑になるが、Haskellの強力なパターンマッチと高階関数を使えば割とさくっと書ける。Haskellを書こう。
LaTeX→HTML
原稿をLaTeXで書いて最終的にHTMLを出力したい場合。
この場合はLaTeXの定理環境をdivタグに変換することになる。
@mr_konn 氏が pandoc-japanese-filters でそういうfilterを書いているので、参考にすると良いだろう:https://github.com/konn/pandoc-japanese-filters/blob/master/env-to-div-filter.hs
関連スライド:(数式の入った)本をつくる, 2015年3月
筆者自身はLaTeXで書いた定理環境を含む文書をPandocで真面目に処理させた経験はないので、突っ込んだノウハウは持ち合わせていない。
ピンバック: 2018年振り返り | 雑記帳