summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/scripts/citation-style-language/citeproc-node-label.lua
blob: 828f5e91222059c2a162421421517aa03ee46746 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
--
-- Copyright (c) 2021-2022 Zeping Lee
-- Released under the MIT license.
-- Repository: https://github.com/zepinglee/citeproc-lua
--

local label = {}

local element = require("citeproc-element")
local util = require("citeproc-util")


local Label = element.Element:new()

function Label:render (item, context)
  self:debug_info(context)
  context = self:process_context(context)

  local variable_name
  if context.names_element then
    -- The `variable` attribute of names may hold multiple roles.
    -- Each of them may call `Label:render()` to render the term.
    -- When used in `names` element, the role name is the first argument
    -- and the item is accessed via `context.item`.
    -- Bad design
    -- TODO: Redesign the arguments of render()
    variable_name = item
  else
    variable_name = context.options["variable"]
  end

  local form = context.options["form"]
  local plural = context.options["plural"] or "contextual"

  if not context.names_element then
    local variable_type = util.variable_types[variable_name]
    -- variable must be or one of the number variables.
    if variable_type ~= "number" then
      return nil
    end
    -- The term is only rendered if the selected variable is non-empty
    local variable = item[variable_name]
    if not variable then
      return nil
    end
    if type(variable) == "string" then
      if not (string.match(variable, "^%d") or util.is_numeric(variable)) then
        return nil
      end
    end
  end

  local term
  if variable_name == "locator" then
    local locator_type = item.label or "page"
    term = self:get_term(locator_type, form)
  else
    term = self:get_term(variable_name, form)
  end

  local res = nil
  if term then
    if plural == "contextual" and self:_is_plural(variable_name, context) or plural == "always" then
      res = term:render(context, true)
    else
      res = term:render(context, false)
    end

    res = self:strip_periods(res, context)
    res = self:case(res, context)
    res = self:format(res, context)
    res = self:wrap(res, context)
  end
  return res
end

function Label:_is_plural (variable_name, context)
  local variable_type = util.variable_types[variable_name]
  -- Don't use self:get_variable here
  local variable = context.item[variable_name]
  local res = false
  if variable_type == "name" then
    -- Label inside `names`
    res = #variable > 1

  elseif variable_type == "number" then
    if util.startswith(variable_name, "number-of-") then
      res = tonumber(variable) > 1
    else
      variable = tostring(variable)
      variable = string.gsub(variable, "\\%-", "")
      if #util.split(variable, "%s*[,&-]%s*") > 1 then
        -- check if contains multiple numbers
        -- "i–ix": true
        -- res = string.match(tostring(variable), "%d+%D+%d+") ~= nil
        res = true
      elseif string.match(variable, "%Aand%A") or string.match(variable, "%Aet%A") then
        res = true
      else
        res = false
      end
    end
  else
    util.warning("Invalid attribute \"variable\".")
  end
  return res
end


label.Label = Label

return label