diff options
Diffstat (limited to 'biblio/citation-style-language/citeproc-node-layout.lua')
-rw-r--r-- | biblio/citation-style-language/citeproc-node-layout.lua | 243 |
1 files changed, 35 insertions, 208 deletions
diff --git a/biblio/citation-style-language/citeproc-node-layout.lua b/biblio/citation-style-language/citeproc-node-layout.lua index 944ed883a3..168f923b08 100644 --- a/biblio/citation-style-language/citeproc-node-layout.lua +++ b/biblio/citation-style-language/citeproc-node-layout.lua @@ -6,229 +6,56 @@ local layout = {} -local richtext = require("citeproc-richtext") -local element = require("citeproc-element") +local Element = require("citeproc-element").Element +local SeqIr = require("citeproc-ir-node").SeqIr local util = require("citeproc-util") -local Layout = element.Element:new() +local Layout = Element:derive("layout") -function Layout:render (items, context) - self:debug_info(context) +function Layout:from_node(node) + local o = Layout:new() + o:set_affixes_attributes(node) + o:set_formatting_attributes(node) + o:get_delimiter_attribute(node) - context.items = items + o:process_children_nodes(node) - -- When used within cs:citation, the delimiter attribute may be used to specify a delimiter for cites within a citation. - -- Thus the processing of context is put after render_children(). - if context.mode == "citation" then - if context.options["collapse"] == "citation-number" then - context.build.item_citation_numbers = {} - context.build.item_citation_number_text = {} - end - elseif context.mode == "bibliography" then - context.build.longest_label = "" - context.build.preceding_first_rendered_names = nil - context = self:process_context(context) - end - - local output = {} - local previous_cite = nil - for _, item in ipairs(items) do - - context.item = item - context.variable_attempt = {} - context.suppressed_variables = {} - context.suppress_subsequent_variables = false - if context.mode == "bibliography" then - context.build.first_rendered_names = {} - end - - if not item.position then - item.position = self:_get_position(item, previous_cite, context) - end - - local first = nil - local second = {} - local element_index = 0 - for _, child in ipairs(self:get_children()) do - if child:is_element() then - element_index = element_index + 1 - local text = child:render(item, context) - if element_index == 1 then - first = text - else - table.insert(second, text) - end - end - end - second = self:concat(second, context) - - if context.mode == "bibliography" then - if first and context.options["prefix"] then - first = richtext.new(context.options["prefix"]) .. first - end - if second and context.options["suffix"] then - second = second .. richtext.new(context.options["suffix"]) - end - end - - local res = nil - if context.options["second-field-align"] == "flush" then - if first then - first:add_format("display", "left-margin") - res = first - end - if second then - second:add_format("display", "right-inline") - if res then - res = richtext.concat(res, second) - else - res = second - end - end - else - res = self:concat({first, second}, context) - end - - if context.mode == "citation" then - if res and item["prefix"] then - res = richtext.new(item["prefix"]) .. res - end - if res and item["suffix"] then - res = res .. richtext.new(item["suffix"]) - end - elseif context.mode == "bibliography" then - if not res then - res = richtext.new("[CSL STYLE ERROR: reference with no printed form.]") - end - res = self:wrap(res, context) - -- util.debug(text) - res = res:render(context.engine.formatter, context) - res = context.engine.formatter["@bibliography/entry"](res, context) - end - table.insert(output, res) - previous_cite = item - end - - if context.mode == "citation" then - if next(output) == nil then - return "[CSL STYLE ERROR: reference with no printed form.]" - end - - context = self:process_context(context) - local res - if context.options["collapse"] then - res = self:_collapse_citations(output, context) - else - res = self:concat(output, context) - end - res = self:wrap(res, context) - res = self:format(res, context) - if res then - -- util.debug(res) - res = res:render(context.engine.formatter, context) - end - return res - - else - local params = { - maxoffset = #context.build.longest_label, - } - - return {params, output} - end + return o end -function Layout:_get_position (item, previous_cite, context) - local engine = context.engine - if not engine.registry.registry[item.id] then - return util.position_map["first"] +function Layout:build_ir(engine, state, context) + local ir = self:build_children_ir(engine, state, context) + if not ir then + return nil end - - local position = util.position_map["subsequent"] - -- Find the preceding cite referencing the same item - local preceding_cite = nil - if previous_cite then - -- a. the current cite immediately follows on another cite - if item.id == previous_cite.id then - preceding_cite = previous_cite - end - elseif engine.registry.previous_citation then - -- b. first cite in the citation and previous citation exists - for _, cite in ipairs(engine.registry.previous_citation.citationItems) do - if item.id == cite.id then - preceding_cite = cite - break - end - end - end - - if preceding_cite then - if preceding_cite.locator then - -- Preceding cite does have a locator - if item.locator then - if item.locator == preceding_cite.locator then - position = util.position_map["ibid"] - else - position = util.position_map["ibid-with-locator"] + if context.in_bibliography then + ir.delimiter = self.delimiter + + -- Move affixes of `bibliography > layout` into the right-inline element + -- bugreports_SmallCapsEscape.txt + local has_right_inline = false + if self.affixes or self.formatting then + for i, child_ir in ipairs(ir.children) do + if child_ir.display == "right-inline" then + has_right_inline = true + local right_inline_with_affixes = SeqIr:new({child_ir}, self) + right_inline_with_affixes.affixes = util.clone(self.affixes) + right_inline_with_affixes.formatting = util.clone(self.formatting) + child_ir.display = nil + right_inline_with_affixes.display = "right-inline" + ir.children[i] = right_inline_with_affixes + break end - else - -- the current cite lacks a locator - position = util.position_map["subsequent"] - end - else - -- Preceding cite does not have a locator - if item.locator then - position = util.position_map["ibid-with-locator"] - else - position = util.position_map["ibid"] end end - end - return position -end - -function Layout:_collapse_citations(output, context) - if context.options["collapse"] == "citation-number" then - assert(#output == #context.items) - local citation_numbers = {} - for i, item in ipairs(context.items) do - citation_numbers[i] = context.build.item_citation_numbers[item.id] or 0 + if not has_right_inline then + ir.affixes = util.clone(self.affixes) + ir.formatting = util.clone(self.formatting) end - - local collapsed_output = {} - local citation_number_range_delimiter = util.unicode["en dash"] - local index = 1 - while index <= #citation_numbers do - local stop_index = index + 1 - if output[index] == context.build.item_citation_number_text[index] then - while stop_index <= #citation_numbers do - if output[stop_index] ~= context.build.item_citation_number_text[stop_index] then - break - end - if citation_numbers[stop_index - 1] + 1 ~= citation_numbers[stop_index] then - break - end - stop_index = stop_index + 1 - end - end - - if stop_index >= index + 3 then - local range_text = output[index] .. citation_number_range_delimiter .. output[stop_index - 1] - table.insert(collapsed_output, range_text) - else - for i = index, stop_index - 1 do - table.insert(collapsed_output, output[i]) - end - end - - index = stop_index - end - - return self:concat(collapsed_output, context) end - return self:concat(output, context) + return ir end |