summaryrefslogtreecommitdiff
path: root/paper/lua-filters/section-refs/section-refs.lua
diff options
context:
space:
mode:
Diffstat (limited to 'paper/lua-filters/section-refs/section-refs.lua')
-rw-r--r--paper/lua-filters/section-refs/section-refs.lua138
1 files changed, 138 insertions, 0 deletions
diff --git a/paper/lua-filters/section-refs/section-refs.lua b/paper/lua-filters/section-refs/section-refs.lua
new file mode 100644
index 0000000..68e61d0
--- /dev/null
+++ b/paper/lua-filters/section-refs/section-refs.lua
@@ -0,0 +1,138 @@
+function is_ref_div (blk)
+ return (blk.t == "Div" and blk.identifier == "refs")
+end
+
+function is_ref_header (blk)
+ return (blk.t == "Header" and blk.identifier == "bibliography")
+end
+
+function get_all_refs (blks)
+ for _, b in pairs(blks) do
+ if is_ref_div(b) then
+ return b.content
+ end
+ end
+end
+
+function remove_all_refs (blks)
+ local out = {}
+ for _, b in pairs(blks) do
+ if not (is_ref_div(b) or is_ref_header(b)) then
+ table.insert(out, b)
+ end
+ end
+ return out
+end
+
+-- We return a {number, ref} pair so we can sort in the individual
+-- bibliographies.
+function citation_to_numbered_ref (citation, all_refs)
+ local div_id = "ref-" .. citation.id
+ for i, d in ipairs(all_refs) do
+ if d.t == "Div" and d.identifier == div_id then
+ return {i, d}
+ end
+ end
+end
+
+
+function get_partial_refs (blocks, all_refs)
+ local cites = {}
+ local citegetter = {
+ Cite = function (el)
+ for _, c in pairs(el.citations) do
+ table.insert(cites, c)
+ end
+ end
+ }
+
+ for _, b in pairs(blocks) do
+ pandoc.walk_block(b, citegetter)
+ end
+
+
+ -- first we make a list of the {number, ref} pairs so we can sort
+ -- them. Then after sorting, we're going to make a new list with
+ -- only the second element.
+ local numbered_refs = {}
+ for _, c in pairs(cites) do
+ local r = citation_to_numbered_ref(c, all_refs)
+ if r then
+ table.insert(numbered_refs, r)
+ end
+ end
+
+ table.sort(numbered_refs, function(x, y) return x[1] < y[1] end)
+
+ local refs = {}
+ for _, nr in pairs(numbered_refs) do
+ table.insert(refs, nr[2])
+ end
+
+ return refs
+end
+
+function add_section_refs (blks, lvl, refs_title, all_refs)
+ local output_blks = {}
+ local section = {}
+ local refs_num = 0
+
+ local go = function ()
+ refs_num = refs_num + 1
+ local section_refs = get_partial_refs(section, all_refs)
+ if refs_title then
+ local hdr = pandoc.Header(lvl + 1,
+ refs_title,
+ pandoc.Attr("bibliography-" .. tostring(refs_num),
+ {"unnumbered"}))
+ table.insert(section_refs, 1, hdr)
+ end
+ local refs_div = pandoc.Div(section_refs,
+ pandoc.Attr("refs-" .. tostring(refs_num),
+ {"references"}))
+ table.insert(section, refs_div)
+ for _, x in pairs(section) do
+ table.insert(output_blks, x)
+ end
+ end
+
+ -- to avoid putting a bib after an intro paragraph.
+ local seen_hdr_before = false
+ for _, b in pairs(blks) do
+ if b.t == "Header" and b.level <= lvl then
+ if seen_hdr_before then
+ go()
+ section = {b}
+ else
+ seen_hdr_before = true
+ table.insert(section, b)
+ end
+ else
+ table.insert(section, b)
+ end
+ end
+ go()
+ return output_blks
+end
+
+function Pandoc(doc)
+ if PANDOC_VERSION == nil then -- if pandoc_version < 2.1
+ io.stderr:write("WARNING: pandoc >= 2.1 required for section-refs filter\n")
+ return doc
+ end
+ local refs_title = doc.meta["reference-section-title"]
+ -- if we get it from a command-line field, read it in as md.
+ if type(refs_title) == "string" then
+ refs_title = pandoc.read(refs_title, "markdown").blocks[1].content
+ end
+ local lvl = tonumber(doc.meta["section-refs-level"]) or 1
+ local all_refs = get_all_refs(doc.blocks)
+ -- we only want to do something if there are refs to work
+ -- with. This way, if this is run without pandoc-citeproc, it will
+ -- just return the same document.
+ if all_refs then
+ local unreffed = remove_all_refs(doc.blocks)
+ local output = add_section_refs(unreffed, lvl, refs_title, all_refs)
+ return pandoc.Pandoc(output, doc.meta)
+ end
+end