This filter modifies the bibliography, adding backlinks to the locations in the text where an item is cited.
This filter should be invoked after citeproc
, e.g.
pandoc --citeproc --lua-filter citation-backlinks.lua ...
The filter doesn’t work yet as a Quarto extension.
This pandoc Lua filter is published under the MIT license, see file
LICENSE
for details.
---
title: Lorem ipsum
author: Nullus
nocite: '@*'
bibliography: test/example.bib
---
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec
hendrerit tempor tellus. Donec pretium posuere tellus. Proin quam
nisl @krewinkel2017, tincidunt et, mattis eget, convallis nec, purus.
---
author: Nullus
bibliography: test/example.bib
nocite: "[@\\*]{#cite_1}"
title: Lorem ipsum
---
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec
hendrerit tempor tellus. Donec pretium posuere tellus. Proin quam nisl[Krewinkel and Winkler (2017)]{#cite_2}, tincidunt et, mattis eget,
convallis nec, purus.
::: {#refs .references .csl-bib-body .hanging-indent}
::: {#ref-krewinkel2017 .csl-entry}
Krewinkel, Albert, and Robert Winkler. 2017. "Formatting Open Science:
Agilely Creating Multiple Document Formats for Academic Manuscripts with
Pandoc Scholar." *PeerJ Computer Science* 3 (May): e112.<https://doi.org/10.7717/peerj-cs.112>. Cited: [1](#cite_2)
:::
::: {#ref-smith2018 .csl-entry}
Smith, Arfon M., Kyle E. Niemeyer, Daniel S. Katz, Lorena A. Barba,
George Githinji, Melissa Gymrek, Kathryn D. Huff, et al. 2018. "Journal
of Open Source Software (JOSS): Design and First-Year Review." *PeerJ
Computer Science* 4 (February): e147.<https://doi.org/10.7717/peerj-cs.147>.
::: :::
--- citation-backlinks.lua – adds citation backlinks to the bibliography
---
--- Copyright: © 2022 John MacFarlane and Albert Krewinkel
--- License: MIT – see LICENSE for details
-- Makes sure users know if their pandoc version is too old for this
-- filter.
PANDOC_VERSION:must_be_at_least '2.17'
-- cites is a table mapping citation item identifiers
-- to an array of cite identifiers
local cites = {}
-- counter for cite identifiers
local cite_number = 1
local function with_latex_label(s, el)
if FORMAT == "latex" then
return {pandoc.RawInline("latex", "\\label{" .. s .. "}"), el}
else
return {el}
end
end
function Cite(el)
local cite_id = "cite_" .. cite_number
= cite_number + 1
cite_number for _,citation in ipairs(el.citations) do
if cites[citation.id] then
table.insert(cites[citation.id], cite_id)
else
[citation.id] = {cite_id}
citesend
end
return pandoc.Span(with_latex_label(cite_id, el), pandoc.Attr(cite_id))
end
function append_inline(blocks, inlines)
local last = blocks[#blocks]
if last.t == 'Para' or last.t == 'Plain' then
-- append to last block
.content:extend(inlines)
lastelse
-- append as additional block
[#blocks + 1] = pandoc.Plain(inlines)
blocksend
return blocks
end
function Div(el)
local citation_id = el.identifier:match("ref%-(.+)")
if citation_id then
local backlinks = pandoc.Inlines{pandoc.Str("Cited:"),pandoc.Space()}
for i,cite_id in ipairs(cites[citation_id] or {}) do
local marker = pandoc.Str(i)
if FORMAT == "latex" then
= pandoc.RawInline("latex", "\\pageref{" .. cite_id .. "}")
marker end
if #backlinks > 2 then
table.insert(backlinks, pandoc.Str(","))
table.insert(backlinks, pandoc.Space())
end
table.insert(backlinks, pandoc.Link(marker, "#"..cite_id))
end
if #backlinks > 2 then
(el.content, {pandoc.Space()} .. backlinks)
append_inlineend
return el
end
end