Skip to content

Commit

Permalink
feat(packages): Support crossref field in bibTeX bibliography
Browse files Browse the repository at this point in the history
Closes #2021
  • Loading branch information
Omikhleia authored and alerque committed Jun 23, 2024
1 parent 47cb615 commit c4ae919
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 8 deletions.
2 changes: 2 additions & 0 deletions packages/bibtex/bibliography.lua
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ Bibliography = {
produceCitation = function (cite, bib, style)
local item = bib[cite.key]
if not item then
-- Should have been already checked by the caller
return Bibliography.Errors.UNKNOWN_REFERENCE
end
local t = Bibliography.buildEnv(cite, item.attributes, style)
Expand All @@ -296,6 +297,7 @@ Bibliography = {
produceReference = function (cite, bib, style)
local item = bib[cite.key]
if not item then
-- Should have been already checked by the caller
return Bibliography.Errors.UNKNOWN_REFERENCE
end
item.type = item.type:gsub("^%l", string.upper)
Expand Down
46 changes: 38 additions & 8 deletions packages/bibtex/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,34 @@ local parseBibtex = function (fn)
return entries
end

--- Resolve the 'crossref' field on a bibliography entry.
-- (Supplementing the entry with the attributes of the parent entry.)
-- Once resolved recursively, the crossref field is removed from the entry.
-- So this is intended to be called at first use of the entry, and have no
-- effect on subsequent uses: BibTeX does seem to mandate crossref to be
-- defined before the entry that uses it, or even in the same bibliography
-- file.
-- @tparam table bib Bibliography
-- @tparam string key Valid entry key
local function crossrefResolve (bib, key)
local entry = bib[key]
local crossref = entry.attributes.crossref
if crossref then
local parent = bib[crossref]
entry.attributes.crossref = nil
if parent then
crossrefResolve(bib, crossref)
for k, v in pairs(parent.attributes) do
if not entry.attributes[k] then
entry.attributes[k] = v
end
end
else
SU.warn("Unknown crossref " .. crossref .. " in bibliography entry " .. key)
end
end
end

function package:_init ()
base._init(self)
SILE.scratch.bibtex = { bib = {} }
Expand Down Expand Up @@ -87,27 +115,29 @@ function package:registerCommands ()
if not options.key then
options.key = SU.ast.contentToString(content)
end
local style = SILE.settings:get("bibtex.style")
local bibstyle = require("packages.bibtex.styles." .. style)
local cite = Bibliography.produceCitation(options, SILE.scratch.bibtex.bib, bibstyle)
if cite == Bibliography.Errors.UNKNOWN_REFERENCE then
if not SILE.scratch.bibtex.bib[options.key] then
SU.warn("Unknown reference in citation " .. options.key)
return
end
crossrefResolve(SILE.scratch.bibtex.bib, options.key)
local style = SILE.settings:get("bibtex.style")
local bibstyle = require("packages.bibtex.styles." .. style)
local cite = Bibliography.produceCitation(options, SILE.scratch.bibtex.bib, bibstyle)
SILE.processString(("<sile>%s</sile>"):format(cite), "xml")
end)

self:registerCommand("reference", function (options, content)
if not options.key then
options.key = SU.ast.contentToString(content)
end
if not SILE.scratch.bibtex.bib[options.key] then
SU.warn("Unknown reference in citation " .. options.key)
return
end
crossrefResolve(SILE.scratch.bibtex.bib, options.key)
local style = SILE.settings:get("bibtex.style")
local bibstyle = require("packages.bibtex.styles." .. style)
local cite, err = Bibliography.produceReference(options, SILE.scratch.bibtex.bib, bibstyle)
if cite == Bibliography.Errors.UNKNOWN_REFERENCE then
SU.warn("Unknown reference in citation " .. tostring(options.key))
return
end
if cite == Bibliography.Errors.UNKNOWN_TYPE then
SU.warn("Unknown type @" .. err .. " in citation for reference " .. options.key)
return
Expand Down

0 comments on commit c4ae919

Please sign in to comment.