めっちゃ簡単だった…
前回の記事、
ではlua filterでやるのアレかも…とか書いてましたが、アレではなかった。すごい簡単なことでした…。
私、めっちゃ勘違いしていて、io.read()
でファイル読むもんだと思ってました…。これの引数は文字列でしたね。
ファイルを開くのはio.open()
を使う。…なので、対象のcsvファイルを開いて読み取った文字列をio.read()
に渡してあげればよい、ということになります。
この辺りを参考にしました。
あと、本家のマニュアルも。
さて、本題。
ひとまず、ドキュメントPandoc
に対して、内容を全部置換する形でやってみましょう。
ダミーの入力ファイル、test.md
として、以下のようなファイルを作っておきます。
# Test
This is a test document for including csv as a table format by using Div and lua filter.
::: {.csv file=iris.csv}
This is dummy text
:::
そして、以下のようなコードをtest.lua
に書き、
function Pandoc (e) local f = assert(io.open("iris.csv", "r")) local t = f:read("*all") f:close() local document = pandoc.read(t, "csv") return(document) end
以下のコマンドで変換します。
pandoc -f markdown -t html -L test.lua test.md -o test.html
生成されたhtmlファイルを開くと、こんな感じになっていると思います。元の文字列は消え、csvファイルの内容の表が取り込まれていますね。
さて、前回の記事で見ましたが、csv形式でファイルを読んだ場合、出力形式をnativeにして表示するとTableだけになっていたと思います。つまり、読み取られたファイルはMeta
を無視するとBlocks
直下にTable
があることになりますね。
この構造を仮定して、csvファイルを読み込んだときに余計に作られるPandocのガワの部分を削除してTable
だけを取り出して埋め込めばよさそうです。
んで、そういう制御を入れられるのはAttr
持ちの構造が良いですね。また、Table
はBlock
要素になるので、Span
などのInline
要素よりはDiv
、Image
、Link
、CodeBlock
などが良いでしょう。
今回はDiv
を使用して、Div要素がcsv
classを一番最初に持ち、attributes
としてfile
をキーとし、ファイル名をその値として持つことを想定してLua filterを作ります。
具体的には、test.md
の
::: {.csv file=iris.csv} This is dummy text :::
の記述に相当します。ここで、ダミーテキストはどのみち消えてしまうので不要ですが、正しく変換がされているかを確認するためのマーカとして入れておくと実使用上は良いと思います。何かわかりやすい文字を入れておきましょう(おせっかい)
さて、先ほどとは別にtest2.lua
という名前でファイルを作ります。もちろん同じファイルに書いても良いですが、先のPandoc
関数は消すか、Pandoc__
みたいな適当な名前に変えておきましょう。どちらも呼ばれると正しく動作しなくなります。
あとはもうやることを書くだけ…。
function Div(e) if e.attr.classes[1] == "csv" then filename = e.attr.attributes.file --"iris.csv" local f = assert(io.open(filename, "r")) local t = f:read("*all") f:close() local document = pandoc.read(t, "csv") table = document.blocks[1] return(table) end end
で、
pandoc -f markdown -t html -L test2.lua test.md -o test.html
と実行すれば、
のようにDiv
記法で書かれていた箇所が正しく表に置き換わっていますね。