niszetの日記

細かい情報を載せていくブログ

Lua filterでcsvの表の取り込みは難しいといったな。すまん、あれは嘘だ。

めっちゃ簡単だった…

前回の記事、

niszet.hatenablog.com

ではlua filterでやるのアレかも…とか書いてましたが、アレではなかった。すごい簡単なことでした…。

私、めっちゃ勘違いしていて、io.read()でファイル読むもんだと思ってました…。これの引数は文字列でしたね。 ファイルを開くのはio.open()を使う。…なので、対象のcsvファイルを開いて読み取った文字列をio.read()に渡してあげればよい、ということになります。

この辺りを参考にしました。

xn--pckzexbx21r8q9b.net

あと、本家のマニュアルも。

pandoc.org

さて、本題。

ひとまず、ドキュメント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ファイルの内容の表が取り込まれていますね。

f:id:niszet:20200222200754p:plain

さて、前回の記事で見ましたが、csv形式でファイルを読んだ場合、出力形式をnativeにして表示するとTableだけになっていたと思います。つまり、読み取られたファイルはMetaを無視するとBlocks直下にTableがあることになりますね。

この構造を仮定して、csvファイルを読み込んだときに余計に作られるPandocのガワの部分を削除してTableだけを取り出して埋め込めばよさそうです。

んで、そういう制御を入れられるのはAttr持ちの構造が良いですね。また、TableBlock要素になるので、SpanなどのInline要素よりはDivImageLinkCodeBlockなどが良いでしょう。

今回は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

と実行すれば、

f:id:niszet:20200222202322p:plain

のようにDiv記法で書かれていた箇所が正しく表に置き換わっていますね。

まとめ

  • Markdown中にcsvファイルから取り込んだ表を埋め込むのはLuaフィルタを使えば出来る。
  • Div記法はプレビュー対応していないエディタも多いので、記号が見えてうざったい場合はLinkが良さそうですね。
  • コードはエラー処理とか制約とか適当気味なので、ちゃんとしてあげてください。
  • Lua filterのリポジトリに加えたいので明日pandoc-discussに送る。