Pandoc 3.0以降ではLuaフィルタで使えるモジュールにpandoc.templateが追加されました。これを使うとLuaフィルタ内でPandoc Templateを展開できます。
うまく使うと定型句を任意のタイミングで、少しずつ文言を変えながら展開する、といったことが可能です。
たとえば、後述するLuaフィルタとテンプレートファイルを書いておいてあげれば、以下の<div>からテンプレートを展開して、Pandocはいいぞと出力されます。
<div template=assets/template.md x="Pandoc"></div>属性xの値を"Pandoc"から"Luaフィルタ"に書き換えれば出力はLuaフィルタはいいぞになります。
<div template=assets/template.md x="Luaフィルタ"></div>この程度のシンプルな例であれば、Luaフィルタ上で直接文字列操作をしてやれば済むでしょうが、定型句が長くなる、条件分岐するなど複雑さを増すごとに威力を発揮するでしょう。
<div>を使って好きなタイミングで読んでいるだけなので、入力がHTMLやMarkdownであれば、定型句(<div>)の前後に任意の文章を挿入できる柔軟性も魅力です。
肝心のLuaフィルタは以下のように記述します。簡略して書いているため、いくつか注意点があります。
- テンプレートファイルは
markdown形式決め打ち - テンプレートファイルに相対パスを指定する場合は作業ディレクトリを基準
- 同じテンプレートを何度もコンパイルしている点など最適化の余地あり
--[[ assets/filter.lua ]]
---テキストファイルを読む
---@param filepath string テンプレートのファイルパス。相対パスの基準はPandoc実行時の作業ディレクトリ。
---@return string テンプレートの中身
local function read_lines(filepath)
local lines = {}
for i in io.lines(filepath) do
table.insert(lines, i)
end
return table.concat(lines, "\n")
end
---テンプレートファイルを指定したコンテキスト化で展開し、Markdownとして処理する
---@param filepath string テンプレートのファイルパス。相対パスの基準はPandoc実行時の作業ディレクトリ。
---@param context table<any, any>
---@return any blocks PandocのBlock要素のリスト
local function apply_template(filepath, context)
local content = read_lines(filepath)
local compiled = pandoc.template.compile(content)
local rendered = pandoc.template.apply(compiled, context):render()
return pandoc.read(rendered, "markdown", PANDOC_READER_OPTIONS).blocks
end
---divのtemplate属性にファイルが指定されていれば、divの属性をコンテキストとしてテンプレートを展開するフィルタ
function Div(el)
if el.attributes.template then
local ctx = {}
for k, v in pairs(el.attributes) do
ctx[k] = v
end
return apply_template(el.attributes.template, ctx)
end
return el
endassets/template.mdの中身は以下の通りです。
<!-- assets/template.md -->
${x}はいいぞでは、このフィルタとテンプレートを利用するMarkdownファイルを用意しましょう。
<!-- assets/example.md -->
# 好きなもの紹介するぞ
<div template=assets/template.md x="Pandoc"></div>
<div template=assets/template.md x="Luaフィルタ"></div>
<div template=assets/template.md x="R"></div>あとはMarkdownファイルをPandocで良い感じに処理すれば、無事にテンプレートが展開されます。
<div>のx属性に指定していた値が、テンプレートの${x}に展開されていることがわかりますね。
> cat assets/example.md | pandoc -t markdown -L assets/filter.lua --strip-comments
# 好きなもの紹介するぞ
Pandocはいいぞ
Luaフィルタはいいぞ
RはいいぞENJOY!
Atusy's blog