PandocのLuaフィルタ内で引用文献を処理するpandoc.utils.citeprocを試す

by
カテゴリ:

Pandoc 2.19.1から、Luaフィルタ向けにpandoc.utils.citeproc関数が追加されました。

これは、Pandocで引用文献を生成する--citeproc引数相当の処理をASTレベルで実現します。ライターの後(?)に処理される--citeprocと異なり、生成された引用文献に更にフィルタをかけられます。

たとえば書籍をPandocで書く場合に、章ごとに引用文献を用意したい、といった需要を叶えてくれそうですね。

Luaフィルタ向けと書きましたが、カスタムライタを用意する場合も、pandoc.utils.citeprocで引用文献リストをAST内に追加してから出力フォーマットに合わせて整形すると便利かもしれません。

こう、夢が広がりますが、実際の挙動を確認してから使わないと怖いので、試してみました。

結論は、--citeprocした場合と--lua-filterpandoc.utils.citeprocした場合は同じ結果になるが、併用すると、引用文献のリストを2回繰り返します。基本的には排他利用した方がいいです。

--citeproc--lua-filterによる引用文献の処理結果比較

Pandocに与える引数を変えつつ、Pandoc’s Markdownを、GFMに変換して、--citeproc--lua-filterの挙動を理解します。

実験結果

citeproc lua filter 結果
なし なし 未処理
あり なし 通常の処理方法により引用文献のリストを生成
なし あり 上と同じ
あり あり 引用文献のリストが2回繰り返す

実験条件

以下のMarkdownを入力し、gfm-raw_html形式に出力します。 gfm-raw_htmlをつけて出力からHTMLを除去することで、ノイズを抑えます。

@john2022

# refs

引用文献には以下の内容のassets/example.bibを使います。

@Manual{john2022,
  title = {title},
  author = {john},
  year = {2022},
}

--lua-filterを指定する場合は、以下の内容のassets/citeproc.luaを使います。

function Pandoc(doc)
  return pandoc.utils.citeproc(doc)
end

この条件で、--citeproc引数と--lua-filter引数のありなしの組み合わせを比較します。

実験

--citeprocなし、--lua-filterなし

--bibliographyを指定しただけでは引用文献は生成されません

echo -e "@john2022\n\n# refs" | pandoc -t gfm-raw_html --bibliography="assets/example.bib"
@john2022

# refs

--citeprocあり、--lua-filterなし

通常通り引用文献が生成されます

echo -e "@john2022\n\n# refs" | pandoc -t gfm-raw_html --bibliography="assets/example.bib" \
  --citeproc
john (2022)

# refs

john. 2022. *Title*.

--citeprocなし、--lua-fiterあり

--citeprocのみの場合と同じ結果

echo -e "@john2022\n\n# refs" | pandoc -t gfm-raw_html --bibliography="assets/example.bib" \
  --lua-filter="assets/citeproc.lua"
john (2022)

# refs

john. 2022. *Title*.

--citeprocあり、--lua-filterあり

引用文献を2回繰り返してしまいます。

echo -e "@john2022\n\n# refs" | pandoc -t gfm-raw_html --bibliography="assets/example.bib" \
  --citeproc --lua-filter="assets/citeproc.lua"
john (2022)

# refs

john. 2022. *Title*.

john. 2022. *Title*.

おまけ

--citeprocがASTレベルで作用していないことを確認する

以下のJSONフィルタを使い、Pandocが処理するASTのレベルでは引用文献が生成されていないことを確認します。

#!/bin/bash
content="$(cat - | jq -r .)"

echo -e "\`\`\`\`\`\`\n${content}\n\`\`\`\`\`\`" | pandoc -f markdown -t json

JSON表現なので結果が長大ですが、引用文献が生成されていないのは確かなようです。

echo -e "@john2022\n\n# refs" | pandoc -t gfm-raw_html --bibliography="assets/example.bib" \
  --citeproc --filter="assets/ast.sh"
    {
      "pandoc-api-version": [
        1,
        23
      ],
      "meta": {
        "bibliography": {
          "t": "MetaString",
          "c": "assets/example.bib"
        }
      },
      "blocks": [
        {
          "t": "Para",
          "c": [
            {
              "t": "Cite",
              "c": [
                [
                  {
                    "citationId": "john2022",
                    "citationPrefix": [],
                    "citationSuffix": [],
                    "citationMode": {
                      "t": "AuthorInText"
                    },
                    "citationNoteNum": 1,
                    "citationHash": 0
                  }
                ],
                [
                  {
                    "t": "Str",
                    "c": "john"
                  },
                  {
                    "t": "Space"
                  },
                  {
                    "t": "Str",
                    "c": "(2022)"
                  }
                ]
              ]
            }
          ]
        },
        {
          "t": "Header",
          "c": [
            1,
            [
              "refs",
              [
                "unnumbered"
              ],
              []
            ],
            [
              {
                "t": "Str",
                "c": "refs"
              }
            ]
          ]
        },
        {
          "t": "Div",
          "c": [
            [
              "refs",
              [
                "references",
                "csl-bib-body",
                "hanging-indent"
              ],
              []
            ],
            [
              {
                "t": "Div",
                "c": [
                  [
                    "ref-john2022",
                    [
                      "csl-entry"
                    ],
                    []
                  ],
                  [
                    {
                      "t": "Para",
                      "c": [
                        {
                          "t": "Str",
                          "c": "john."
                        },
                        {
                          "t": "Space"
                        },
                        {
                          "t": "Str",
                          "c": "2022."
                        },
                        {
                          "t": "Space"
                        },
                        {
                          "t": "Emph",
                          "c": [
                            {
                              "t": "Str",
                              "c": "Title"
                            }
                          ]
                        },
                        {
                          "t": "Str",
                          "c": "."
                        }
                      ]
                    }
                  ]
                ]
              }
            ]
          ]
        }
      ]
    }