@@ -58,6 +58,34 @@ local parseBibtex = function (fn)
5858 return entries
5959end
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+
6189function 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