Skip to content

Commit c4ae919

Browse files
Omikhleiaalerque
authored andcommitted
feat(packages): Support crossref field in bibTeX bibliography
Closes #2021
1 parent 47cb615 commit c4ae919

File tree

2 files changed

+40
-8
lines changed

2 files changed

+40
-8
lines changed

packages/bibtex/bibliography.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ Bibliography = {
286286
produceCitation = function (cite, bib, style)
287287
local item = bib[cite.key]
288288
if not item then
289+
-- Should have been already checked by the caller
289290
return Bibliography.Errors.UNKNOWN_REFERENCE
290291
end
291292
local t = Bibliography.buildEnv(cite, item.attributes, style)
@@ -296,6 +297,7 @@ Bibliography = {
296297
produceReference = function (cite, bib, style)
297298
local item = bib[cite.key]
298299
if not item then
300+
-- Should have been already checked by the caller
299301
return Bibliography.Errors.UNKNOWN_REFERENCE
300302
end
301303
item.type = item.type:gsub("^%l", string.upper)

packages/bibtex/init.lua

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,34 @@ local parseBibtex = function (fn)
5858
return entries
5959
end
6060

61+
--- Resolve the 'crossref' field on a bibliography entry.
62+
-- (Supplementing the entry with the attributes of the parent entry.)
63+
-- Once resolved recursively, the crossref field is removed from the entry.
64+
-- So this is intended to be called at first use of the entry, and have no
65+
-- effect on subsequent uses: BibTeX does seem to mandate crossref to be
66+
-- defined before the entry that uses it, or even in the same bibliography
67+
-- file.
68+
-- @tparam table bib Bibliography
69+
-- @tparam string key Valid entry key
70+
local function crossrefResolve (bib, key)
71+
local entry = bib[key]
72+
local crossref = entry.attributes.crossref
73+
if crossref then
74+
local parent = bib[crossref]
75+
entry.attributes.crossref = nil
76+
if parent then
77+
crossrefResolve(bib, crossref)
78+
for k, v in pairs(parent.attributes) do
79+
if not entry.attributes[k] then
80+
entry.attributes[k] = v
81+
end
82+
end
83+
else
84+
SU.warn("Unknown crossref " .. crossref .. " in bibliography entry " .. key)
85+
end
86+
end
87+
end
88+
6189
function package:_init ()
6290
base._init(self)
6391
SILE.scratch.bibtex = { bib = {} }
@@ -87,27 +115,29 @@ function package:registerCommands ()
87115
if not options.key then
88116
options.key = SU.ast.contentToString(content)
89117
end
90-
local style = SILE.settings:get("bibtex.style")
91-
local bibstyle = require("packages.bibtex.styles." .. style)
92-
local cite = Bibliography.produceCitation(options, SILE.scratch.bibtex.bib, bibstyle)
93-
if cite == Bibliography.Errors.UNKNOWN_REFERENCE then
118+
if not SILE.scratch.bibtex.bib[options.key] then
94119
SU.warn("Unknown reference in citation " .. options.key)
95120
return
96121
end
122+
crossrefResolve(SILE.scratch.bibtex.bib, options.key)
123+
local style = SILE.settings:get("bibtex.style")
124+
local bibstyle = require("packages.bibtex.styles." .. style)
125+
local cite = Bibliography.produceCitation(options, SILE.scratch.bibtex.bib, bibstyle)
97126
SILE.processString(("<sile>%s</sile>"):format(cite), "xml")
98127
end)
99128

100129
self:registerCommand("reference", function (options, content)
101130
if not options.key then
102131
options.key = SU.ast.contentToString(content)
103132
end
133+
if not SILE.scratch.bibtex.bib[options.key] then
134+
SU.warn("Unknown reference in citation " .. options.key)
135+
return
136+
end
137+
crossrefResolve(SILE.scratch.bibtex.bib, options.key)
104138
local style = SILE.settings:get("bibtex.style")
105139
local bibstyle = require("packages.bibtex.styles." .. style)
106140
local cite, err = Bibliography.produceReference(options, SILE.scratch.bibtex.bib, bibstyle)
107-
if cite == Bibliography.Errors.UNKNOWN_REFERENCE then
108-
SU.warn("Unknown reference in citation " .. tostring(options.key))
109-
return
110-
end
111141
if cite == Bibliography.Errors.UNKNOWN_TYPE then
112142
SU.warn("Unknown type @" .. err .. " in citation for reference " .. options.key)
113143
return

0 commit comments

Comments
 (0)