This isn't entirely trivial, but possible. The following uses pandoc Lua filters and a function available in pandoc 2.1.1 and later. You'll have to upgrade to a recent version to make it work.
Using the filter works by adding this to your document's YAML section:
---
output:
bookdown::html_document2:
pandoc_args: --lua-filter=multiple-bibliographies.lua
bibliography_normal: normal-bibliography.bib
bibliography_software: software.bib
---
Then add divs to mark where the bibliographies are supposed to be included in the document.
# Bibliography
::: {#refs_normal}
:::
::: {#refs_software}
:::
Each refsX
div should have a matching bibliographyX
entry in the header.
The Lua Filter
Lua filters allow to modify the document programmatically. We use this to generate the reference section separately. For each div that looks like it is supposed to contain references (i.e., whose ID is refsX
, with X
being empty or the name of your topic), we create temporary dummy documents which contain all citations and the reference div, but where bibliography is set to the value of bibliographyX. This allows us to create the bibliography for each topic while ignoring all other topics (as well as the main bibliography).
The aforementioned step doesn't resolve the citations in the actual document, so we need to do this separately. It is enough to fold all bibliographyX into the bibliography meta value and the run pandoc-citeproc on the full document.
-- file: multiple-bibliographies.lua
--- collection of all cites in the document
local all_cites = {}
--- document meta value
local doc_meta = pandoc.Meta{}
--- Create a bibliography for a given topic. This acts on all divs whose ID
-- starts with "refs", followed by nothings but underscores and alphanumeric
-- characters.
local function create_topic_bibliography (div)
local name = div.identifier:match('^refs([_%w]*)$')
if not name then
return nil
end
local tmp_blocks = {
pandoc.Para(all_cites),
pandoc.Div({}, pandoc.Attr('refs')),
}
local tmp_meta = pandoc.Meta{bibliography = doc_meta['bibliography' .. name]}
local tmp_doc = pandoc.Pandoc(tmp_blocks, tmp_meta)
local res = pandoc.utils.run_json_filter(tmp_doc, 'pandoc-citeproc')
-- first block of the result contains the dummy para, second is the refs Div
div.content = res.blocks[2].content
return div
end
local function resolve_doc_citations (doc)
-- combine all bibliographies
local meta = doc.meta
local orig_bib = meta.bibliography
meta.bibliography = pandoc.MetaList{orig_bib}
for name, value in pairs(meta) do
if name:match('^bibliography_') then
table.insert(meta.bibliography, value)
end
end
doc = pandoc.utils.run_json_filter(doc, 'pandoc-citeproc')
doc.meta.bibliography = orig_bib -- restore to original value
return doc
end
return {
{
Cite = function (c) all_cites[#all_cites + 1] = c end,
Meta = function (m) doc_meta = m end,
},
{Pandoc = resolve_doc_citations,},
{Div = create_topic_bibliography,}
}
I published the filter as part of the officially supported Lua filters collection. See there for a more complete, up-to-date version which also respects csl
and nocite
settings.
For more info and details on Lua filters, see the R Markdown docs.