[Pandoc] markdownで論文として通用するレベルのwordへの変換を頑張る

この記事ではPandocを用いて,markdownで書いた内容をwordに変換して論文として投稿出来るレベルまで整えようという記事.そういった野望をもって取り組んだものの,まだ物凄い便利という状態には遠いが,そこそこの進展があったので記事にする.

今回の目標は,PLOS ONEのテンプレを再現する,だ.PLOS ONEのSubmission Guidelinesの真ん中あたりに”Download sample title, author list, and affiliations page (PDF)”とそのmanuscript body版があるのでそのページをmarkdownから作成する.

そう,これがやりたいだけなのに,出来ないことがたくさんあって困った.情報もないし,パッケージ自体のバグもまぁまぁある.なので現段階で出来たこと,出来なかったことをまずまとめる.

この記事で紹介していく出来たこと.
・pandocでmarkdownからwordに変換.
・pandocでwordのtemplateを用いてstyleの調整を行う.(ただし表の見た目の調整方法は不明)
・markdown中での,wordのtemplateの指定方法.
・default.ymlを用いた設定の保存.
・pandoc-mustacheで変数をmarkdownに埋め込む(template variableを用いる).
・pandoc-docx-pagebreak-pyでnew pageを作る.
・Pantableで表の整頓,csvデータの読み込み.(綺麗な表の指定方法は不明)
・pandas-crossrefで図表の番号の自動設定.
・数式の番号付.

この記事でカバーしない内容としては,

・Title, author部分の調整方法.
・文献の引用フロー.
・pandoc-scholarの使い方(分からんかった).
・個人でのpythonでのfilterの作成方法.

以上の内容はカバーはしないが上1つに関しては,試行錯誤の形跡は残す.また相互参照部分に関して,pandoc-xnonシリーズに手を出してしまったので後悔している.pandoc-crossrefを使おう.
文献の引用に関しては,以下の記事を作成した.
[Pandoc] markdownからdocxでpandoc-crossrefを用いたときの参考文献の入れ方

そもそもの前提としてPandocだけではかなり機能が貧弱,そのために3rd partyのパッケージの探索と使用をオススメする.

完成品はgithubに挙げている.
https://github.com/toshiakiasakura/pandoc_plosone_sample_reproduction
result.docxを見ていただければ,見た目に関してはかなり近づけたと思う.図表の相互参照機能も入れたことでmarkdownの利点が活かせているのではないだろうか.

何か新しいことや助言があればください! このブログの一番下にコメント欄があるのと,githubのissuesに質問でも問題ないです.

前置きから長いが,効率性のためには一時的な非効率が生じる.この記事がpandocへの入り口になって実践的な記事が増えるれば幸いである.

環境設定

まずは環境設定から.僕の環境はUbuntu.

インストールの説明はpandocのofficialが詳しい.
Pandoc installing page

Linunxの場合は,amd64の出来合いのものを手に入れて,
tar xvzf <installed_file> --strip-components 1 -C ~/.local
でインストール出来た.

その他に3つ,pantable, pandoc-mustach, pandoc-docx-pagebreakpy をインストールする.
それぞれのドキュメントページはそれぞれ以下.
Pantable—A Python library for writing pandoc filters for tables with batteries included.
pandoc-mustache: Variable Substitution in Pandoc
pandoc-docx-pagebreak-py
pandoc-crossref

インストールコマンドは,

pip install pantable
pip install -U pandoc-mustache
pip3 install git+https://github.com/pandocker/pandoc-docx-pagebreak-py

また相互参照用のpandas-crossrefもインストールする.出来合いのものをインストールするのが楽.pandocの対応するversionと合うバイナリファイルを持ってきて,僕の場合なら.

tar -xf ./package_name
mv pandoc-crossref ~/.local/bin

でインストール可能.参照は以下.バイナリファイルをインストールする方法が楽.
Using pandoc-crossref on Ubuntu 20.04

ここまでインストールすれば,先ほど紹介した僕のgithubのrepositoryをcloneして,pandoc -d default.yaml を叩けば result.docxが生成される.

Dockerでの環境構築も考えたが,pandocと他の解析環境の衝突がおきなさそうなことと,設定の煩雑さから今回は用いていない.Haskellのパッケージインストールは失敗して出来なかったので,もしかしたらこの記事よりもいい方法がDocker用いて構築出来る可能性は十分にある.

Pandocでのword template

まずはこれから紹介.
・pandocでmarkdownからwordに変換.

pandocでのmarkdownからwordへの変換は簡単.何らかのmarkdownがあったときに,

pandoc ./sample.md -o result.docx

で出力出来る.
ただ,この出力で用いられるtemplateは本当にダサい.のでこれを変更する必要がある.基本的に文字の大きさや書体,位置,数字の振り付け,ページの余白サイズの調整など,ワードの設定っぽいなぁって思う部分は全て,このtemplate fileによって管理する.

pandoc --print-default-data-file reference.docx > reference.docx

上のコマンドを実行するとpandocのtemplateのファイルが出力される.pandocで用いられるstyleの大体が既に載ってくれているのでこれをベースに編集する.

ただ,この編集はそこそこめんどくさいので,githubに上がっている,plosone_template.docxからスタートすることをオススメする.

References:
Pandocを使ったWord組版のはじめ方

Pandocのdefault.yaml

この章では以下の内容を解決する.
・default.ymlを用いた設定の保存.

pandoc -d default.yaml でコードが動くのは,default.yaml内に様々な設定が書かれているから.wordへの出力のために設定の多くがtemplateファイルで行われていること,また,参考文献の処理をしていないため僕のdefault.yamlは比較的単純だ.

to: docx  # output format type.
output-file: result.docx  # output file name.
input-files:
- plosone_sample.md  # input file name(s).

from: markdown  # input file format.
reference-doc: plosone_template.docx  # style template word file.
filters:
- pantable  # For table import from .csv files.
- pandoc-mustache  # For variable substition purpose.
- pandoc-docx-pagebreakpy # For pagebreak
- pandoc-crossref

metadata:
    tableEqns: true
    titleDelim: "."
    tableTitle: "Table"
    tblPrefix: "Table"
    figureTitle: "Fig"
    figPrefix: 
        - "Fig"
        - "Figs"

3rd partyのパッケージは大体filtersを通してpandocに組み込まれる.また,metadataの設定はpandoc-crossref用なので後で説明する.

default.yamlでのオプションの書き方に関してはこの記事がよくまとめてくれている.
Pandoc 2.8 新機能 長いオプションをファイルにまとめるDefault file

Pandocのmarkdown記法に関して

この章は分割して以下の内容をカバーしていく.
・pandocでwordのtemplateを用いてstyleの調整を行う.
・pandoc-docx-pagebreak-pyでnew pageを作る.
・pandoc-mustacheで変数をmarkdownに埋め込む(template variableを用いる).
・Pantableで表の整頓,csvデータの読み込み.(綺麗な表の指定方法は不明)
・pandas-crossrefで図表の番号の自動設定.
・数式の番号付.

基本的なmarkdown記法に関して

普通のmakrdownと似ているけど若干違うのでまずはチートシートの確認.
dsanson/Pandoc.tmbundle

あとはケースバイケースで.
Pandoc Markdown のあまり知られていない書法 : 上付き文字下付き文字.cssクラスの当て方.
まだまだ Word で消耗してるの? 大学のレポートを Markdown で書こう (Docker 編) : Dockerも使っててカバー範囲広め.
correctly sizing PNG images in markdown with pandoc for html/pdf/docx : 図のサイズの調整.

markdownでwordのstyleを指定する

ここで再度注意ですが,wordのtemplateで制御出来るものはwordのtemplate内のstyleで調整する.ではwordの任意のstyleをどうやって当てるの?という話に鳴りますが,それに関しては以下のサイト.
Custom Styles, pandoc manual

要するに,

[Get out]{custom-style="Emphatically"}, he said. 
::: {custom-style="Poetry"}
A Bird came down the Walk---
He did not know I saw---
:::

のうち,[]はinlineで用いる, :::{} ~ ::: まではブロックで当てたいとき.段落の最初の空白を消したいときは後者を用いる.

markdownで改ページ,段落,改行指定

pandocのdefaultにはないので,pandoc-docx-pagebreak-py 入れて該当箇所に \newpage を入れればok.

ちなみに改行に関しては,行の終わりに空白2文字か,\ を入れると改行を意味する.段落として認識されるためには1行空白を行と行の間に入れる.

UTF文字について

特殊な文字,例えば,¶ (Pilcrow), † (Dagger) などは論文を書くならばちょくちょく出てくる記号だろう.これは変換などを考えずに,直接どこからか持ってきて貼ってあげればok.wordは基本的に取り扱えるはずなので,問題なし.

template variableについて

template variables,すなわち,markdown中に別な場所で定義した変数を用いる方法は以下の記事でpandocでは対応してないと指摘されている.
Pandocでメタデータはテンプレート変数になるかならないか

が,さすがにそれは不便すぎるし3rd party(pandoc-mustache)のやつがあるので,それを用いると,別ファイルで定義したvariablesを使えるようになる.使うファイルに関しては,markdownのヘッダー部分に置いておく.

僕の場合は,variables.yamlに変数の定義を書き,plosone_sample.mdでそれを指定し,内部でその変数名を{{ }}で括って上げれば変数が展開する.

Title, authors, affiliationsに関して

これに関してはかなり罪深いと思う.どのサイトでもTitle, authors, affiliationsなどに関して入れて記述してある.また,officialのvariablesのところでも,authorなどをmeta-blockで細かく定義することが出来るなど書いてある.
Pandoc official, Metadata blocks
Issuesもあり.
Allow complex metadata fields to be defined on the command line (e.g. using JSON) #3732

ただ,もしcomplexなstyleにした場合は,取り出すためのコードをmarkdown部分に書く必要があるし,そのフォーマットの指定もする必要があるし,とmarkdown to wordの際にはあまりメリットを感じ無かった.なんならauthor部分のstyleの調整の方法は全然分からなった.結論,僕としてはword templateを駆使して,pandocデフォルトのmetadata部分の機能を使わない方針になった.

Supplementaryもmarkdown to word/pdfを行うことを考えると,pandoc-mustacheを用いてvariables.yamlに著者の名前や機関名を集めて置き,そのファイルをいじれば,どちらも変更されるといった状態が好ましいだろう.

Pantableで表の整頓,csvの読み取り

Pantableを用いれば,csvファイルの読み取りをしてmarkdownにファイル名だけ書き,あとは表の設定をして直接wordにデータを出力出来る.
Pantable—A Python library for writing pandoc filters for tables with batteries included.

Pantabelの例を見てもらうのが早いんじゃないかと思う.
Example

csv読み取りの際はこんな感じ.

```table
---
include: Table1.csv
markdown: true
table-width: 5/5
alignment: LLLLL
---
```

includeにファイル名を指定するだけでok.

注: Pantableの“`の領域はyml扱いになるので,pandoc-mustacheの変数を{{}}で入れ込むことが出来ない.まぁ,以下の相互参照の機能も考えるとメリットの方が大きいのでここはご愛嬌.

図表番号の相互参照: pandoc-crossref

ドキュメントはこちら.
pandoc-crossref

基本的に図や表の後に,{#fig:id} でタグ付けして,@fig:idで取り出す.テーブルや数式も同じ.

Pantableと組み合わせたいときは,captionの後に{#tbl:1}を加える.例えばこんな感じ.

```table
---
include: Table1.csv 
caption : This is the Table 1 Title. This is the Table 1 legend. {#tbl:1}
markdown: true
table-width: 5/5
alignment: LLLLL
---

```

自動生成される部分を太字にする方法はまだ探していない.そこは最後の最後に太字は手作業でも妥協かな.それよりも論文がrejectされたあとに,methodとresultを入れ替えたとしても細かい,FigureやResultの番号の振り方を全て入れ替える手間がなくなることを想像すると,なんと嬉しいことか!

FigureやTable, Equationの参照する際の細かい名前の調整は,default.ymlで定義したmetadata以下の変数で行う.以下が該当ページ.
Custom numbering

数式の番号挿入

これは上と同じであるが,数式の番号は右端に来てほしい.ということで,metadataでtableEqns: true とする.オシマイ.

pandocの3rd partyの色々

まだ手を出せていないが,面白そうで有用な3rd partyの資料が色々ある.公式に出ているExtraも注目.
Pandoc Extras

このなかだと,pandiff, pancritic, vim-pandoc, pandoc scholar, zotxt あたりが使うかもしれない.

あと,こんな記事も見つけた.
Quarto が完成すると Jupyter でも R Markdown のように簡単にスライドや文書を作れるかもしれない

もう少ししたら,anacondaのようなmarkdown用のall in one packgeが出てくるんだろうなと思ってる.

以下は,pandoc-xnosに苦しめられた備忘録.読まなくて良いです.

試行錯誤記録: pandoc-xnosシリーズ

前提として,pandoc-crossrefを用いるのがオススメ.pandoc-xnosはメインテナンスがされてないからバグが解消されない可能性がある.以下は途中まで書いた内容.読まなくて良いと思います.

数式への番号挿入

Pythonでの数式相互参照パッケージには,pandoc-eqnosがある.
pandoc-eqnos 2.5.0

関連パッケージにpandoc-xnos, pandoc-fignos, pandoc-tablenosがあるが,全部痒い所に手が届かない感が凄い.

今回のpandoc-eqnosの場合は単純に数式の後に番号が上手く入らない...関連するIssuesがこちら.しかも入れられても見た目がよろしくないらしい.
Convert markdown to word: “Word experienced an error trying to open the file” #62

そのため,数式の相互参照は良いから,テーブル機能を用いて上手く調整しようとするも,pandoc, pandoc-crossrefどちらもあまり芳しくない様相.
・Tables for equation numbers in docx and html #65
feature request: specify the widths for pipe tables #2486

でも,このTableを用いて数式をwrapする発想は良いなと思って,Pantableを用いて実装可能だった.以下のようにすると数式に番号を付けられる.

```table
---
alignment: CCC
table-width: 1/1
markdown: true
---
, $p^2+2pq+q^2$,\(1\) 
```

最初のcsvパートには &nbsp; が入っている.widthも調整出来るので,毎度この量を数式を埋め込むために用いなければ行けないのは,何だったら可読性随分落としている気がするが,可能ではある.数式の数が少ないauthorに取っては許容範囲内ではなかろうか?

試行錯誤の形跡 : 図表番号の相互参照

先ほど出てきたpandoc-eqnosは <w><;w>辺りに問題があるとので,pandoc-fignosでも出来れば便利だなと考えた.結論から言えば,PLOS ONEのFigの形式に合わせられなかった.

文字自体は合わせられた.以下の設定を行えば,自動で振られる図の最初の名前(fignos-caption-name, fignos-caption-separator)で合わせられるし文章中での文字の図表の参照もfignos-plus-nameで調整可能.cleverefを適切に落とせば,Figsも例えば, Figs !@fig:id1 and !@fig:id2 のようにして対応可能だった.

fignos-cleveref: True
fignos-plus-name: "Fig "
fignos-caption-name: Fig
fignos-caption-separator: period

何がダメだったかと言えば,自動で生成されるFig 1.やFig 2.の部分を太字に出来なかった.全部太字だったらwordのFigure Captionの部分を太字にすれば良いが,PLOS ONEや他のジャーナルは混在を推奨する.そのため,丁度,Fig 1. やFig 2.の部分だけが太字に出来なかった.

(上がっているファイルではpandoc-fignosを用いたver.にした.理由としては,最初の太字にする手間が最後にこの部分だけ太字にする利益を上回ると考えたからだ.例えばrejectされた後に,投稿するジャーナルを帰る際のFigureの名前の調整が消えると想像したらとても素晴らしい! )

これに関してはIssuesを立てたので解決を待たれたい,それか解決方法が分かったら教えて欲しい.
Auto-generated caption names want to be bold, when converting from markdown to word. #101

また,pandoc-tablenosに関しては,pantableとの互換性がない.
Support Para-typed captions
これが解決してくれれば使えそうだ.

コメント

タイトルとURLをコピーしました