Skip to content

Commit

Permalink
refactor(packages): Support name particles in (CSL) bibliographies
Browse files Browse the repository at this point in the history
  • Loading branch information
Omikhleia authored and Didier Willis committed Sep 14, 2024
1 parent 8be54bb commit c407336
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 15 deletions.
103 changes: 90 additions & 13 deletions csl/core/engine.lua
Original file line number Diff line number Diff line change
Expand Up @@ -748,28 +748,101 @@ function CslEngine:_name_et_al (options)
end

function CslEngine:_a_name (options, content, entry)
local form = options.form
local nameAsSortOrder = options["name-as-sort-order"]
if not entry.family then
-- There's one element in a name we can't do without.
SU.error("Name without family: what do you expect me to do with it?")
end
local demoteNonDroppingParticle = options["demote-non-dropping-particle"] or "never"

if self.sorting then
-- Ovveride form and name-as-sort-order in sorting mode
form = "long"
nameAsSortOrder = "all"
-- Implicitely we are in long form, name-as-sort-order all, and no formatting.
if demoteNonDroppingParticle == "never" then
-- Order is: [NDP] Family [Given] [Suffix] e.g. van Gogh Vincent III
local name = {}
if entry["non-dropping-particle"] then table.insert(name, entry["non-dropping-particle"]) end
table.insert(name, entry.family)
if entry.given then table.insert(name, entry.given) end
if entry.suffix then table.insert(name, entry.suffix) end
return table.concat(name, " ")
end
-- Order is: Family [Given] [DP] [Suffix] e.g. Gogh Vincent van III
local name = { entry.family }
if entry.given then table.insert(name, entry.given) end
if entry["dropping-particle"] then table.insert(name, entry["dropping-particle"]) end
if entry["non-dropping-particle"] then table.insert(name, entry["non-dropping-particle"]) end
if entry.suffix then table.insert(name, entry.suffix) end
return table.concat(name, " ")
end

local form = options.form
local nameAsSortOrder = options["name-as-sort-order"] or "first"

-- TODO FIXME: content can consists in name-part elements for formatting, text-case, affixes
-- Chigaco style does not seem to use them, so we keep it simple for now.
-- TODO FIXME: demote-non-dropping-particle option not implemented, and name particle not implemented at all!
-- Chigaco style does not seem to use them, so we keep it "simple" for now.

if form == "short" then
-- Order is: [NDP] Family, e.g. van Gogh
if entry["non-dropping-particle"] then
return table.concat({
entry["non-dropping-particle"],
entry.family
}, " ")
end
return entry.family
end

if nameAsSortOrder ~= "all" and not self.firstName then
-- Order is: Given Family
return entry.given and (entry.given .. " " .. entry.family) or entry.family
-- Order is: [Given] [DP] [NDP] Family [Suffix] e.g. Vincent van Gogh III
local t = {}
if entry.given then table.insert(t, entry.given) end
if entry["dropping-particle"] then table.insert(t, entry["dropping-particle"]) end
if entry["non-dropping-particle"] then table.insert(t, entry["non-dropping-particle"]) end
table.insert(t, entry.family)
if entry.suffix then table.insert(t, entry.suffix) end
return table.concat(t, " ")
end
-- Order is: Family, Given

local sep = options["sort-separator"] or (self.punctuation[","] .. " ")
return entry.given and (entry.family .. sep .. entry.given) or entry.family
if demoteNonDroppingParticle == "display-and-sort" then
-- Order is: Family, [Given] [DP] [NDP], [Suffix] e.g. Gogh, Vincent van, III
local mid = {}
if entry.given then table.insert(mid, entry.given) end
if entry["dropping-particle"] then table.insert(mid, entry["dropping-particle"]) end
if entry["non-dropping-particle"] then table.insert(mid, entry["non-dropping-particle"]) end
local midname = table.concat(mid, " ")
if #midname > 0 then
return table.concat({
entry.family,
midname,
entry.suffix -- may be nil
}, sep)
end
return table.concat({
entry.family,
entry.suffix -- may be nil
}, sep)
end

-- Order is: [NDP] Family, [Given] [DP], [Suffix] e.g. van Gogh, Vincent, III
local beg = {}
if entry["non-dropping-particle"] then table.insert(beg, entry["non-dropping-particle"]) end
table.insert(beg, entry.family)
local begname = table.concat(beg, " ")
local mid = {}
if entry.given then table.insert(mid, entry.given) end
if entry["dropping-particle"] then table.insert(mid, entry["dropping-particle"]) end
local midname = table.concat(mid, " ")
if #midname > 0 then
return table.concat({
begname,
midname,
entry.suffix -- may be nil
}, sep)
end
return table.concat({
begname,
entry.suffix -- may be nil
}, sep)
end

local function hasField (list, field)
Expand Down Expand Up @@ -840,8 +913,12 @@ function CslEngine:_names_with_resolved_opts (options, substitute_node, entry)
elseif #l == 1 then
joined = l[1]
else
-- TODO THINGS TO SUPPORT THAT MIGHT REQUIRE A REFACTOR
-- They are needed in Chicago style, but let's keep it simple for now.
-- delimiter-precedes-last ("contextual" by default)
-- Chicago has "always", let's hard-code it for now.
local last = table.remove(l)
joined = table.concat(l, name_delimiter) .. " " .. and_word .. " " .. last
joined = table.concat(l, name_delimiter) .. name_delimiter .. and_word .. " " .. last
end
if label then
joined = is_label_first and (label .. joined) or (joined .. label)
Expand Down Expand Up @@ -895,7 +972,7 @@ function CslEngine:_names (options, content, entry)
local et_al_use_first = tonumber(name_node.options["et-al-use-first"]) or 1
local and_opt = name_node.options["and"] or "text"
local and_word = and_opt == "symbol" and "&" or self:_render_term("and") -- text by default
local name_delimiter = name_node.options.delimiter or inherited_opts["names-delimiter"]
local name_delimiter = name_node.options.delimiter or inherited_opts["names-delimiter"] or ", "
-- local delimiter_precedes_et_al = name_node.options["delimiter-precedes-et-al"] -- TODO NOT IMPLEMENTED

if name_delimiter and not self.cache[name_delimiter] then
Expand Down
17 changes: 15 additions & 2 deletions packages/bibtex/support/nbibtex.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
-- The following functions borrowed from Norman Ramsey's nbibtex,
-- with permission.
-- Thanks, Norman, for these functions!
-- NOTE: Modified in 2024 for CSL compatibility:
-- - nbsp instead of "~" for non-breaking space
-- - added CSL compatibility fields (given, non-dropping-particle, family, suffix)

-- The initial implementation was using "~", but we now sanitized the
-- input earlier at parsing to replace those from the input with
Expand Down Expand Up @@ -266,11 +269,21 @@ do
end
end
set_name(first_start, first_lim, "ff", "f")
set_name(first_start, first_lim, "given", "f") -- HACK OMIKHLEIA FIXME
set_name(first_start, first_lim, "given", "given-short") -- CSL compatibility

set_name(von_start, von_lim, "vv", "v")
-- BibLaTex doesn't distinguish between dropping-particle and non-dropping-particle...
-- So we assume it is non-dropping-particle.
-- Note: citeproc-lua assumes a non-dropping-particle too, without comment (checking its code)
-- I'd like to be more convinced, or the BibLaTeX folks to evolve towards something more
-- explicit. We are in 2024, folks, there has been time to think about it...
set_name(von_start, von_lim, "non-dropping-particle", "non-dropping-particle-short") -- CSL compatibility

set_name(von_lim, last_lim, "ll", "l")
set_name(von_lim, last_lim, "family", "l") -- HACK OMIKHLEIA FIXME
set_name(von_lim, last_lim, "family", "family-short") -- CSL compatibility

set_name(last_lim, jr_lim, "jj", "j")
set_name(last_lim, jr_lim, "suffix", "suffix-short") -- CSL compatibility
return name
end
end
Expand Down

0 comments on commit c407336

Please sign in to comment.