1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
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
|