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
|
--
-- Copyright (c) 2021-2022 Zeping Lee
-- Released under the MIT license.
-- Repository: https://github.com/zepinglee/citeproc-lua
--
local number_module = {}
local element = require("citeproc-element")
local util = require("citeproc-util")
local Number = element.Element:new()
function Number:render (item, context)
self:debug_info(context)
context = self:process_context(context)
local variable = context.options["variable"]
local content = self:get_variable(item, variable, context)
table.insert(context.variable_attempt, content ~= nil)
if not content then
return nil
end
local numbers = {}
local punct_list = {}
local last_position = 1
for number, punct, pos in string.gmatch(content, "(.-)%s*([-,&])%s*()") do
table.insert(numbers, number)
table.insert(punct_list, punct)
last_position = pos
end
table.insert(numbers, string.sub(content, last_position))
local res = ""
for i, number in ipairs(numbers) do
local punct = punct_list[i]
number = self:_format_single_number(number, context)
res = res .. number
if punct == "-" then
res = res .. punct
elseif punct == "," then
res = res .. punct .. " "
elseif punct == "&" then
res = res .. " " .. punct .. " "
end
end
res = self:case(res, context)
res = self:wrap(res, context)
res = self:display(res, context)
return res
end
function Number:_format_single_number(number, context)
local form = context.options["form"] or "numeric"
if form == "numeric" or not string.match(number, "^%d+$") then
return number
end
number = tonumber(number)
if form == "ordinal" or form == "long-ordinal" then
return self:_format_oridinal(number, form, context)
elseif form == "roman" then
return util.convert_roman(number)
end
end
function Number:_format_oridinal(number, form, context)
assert(type(number) == "number")
local variable = context.options["variable"]
if form == "long-ordinal" then
if number < 1 or number > 10 then
form = "ordinal"
end
end
local gender = nil
local term = self:get_term(variable)
if term then
gender = term:get_attribute("gender")
end
term = self:get_term(form, nil, number, gender)
local res = term:render(context)
if form == "ordinal" then
if res then
return tostring(number) .. res
else
res = tostring(number)
end
else
return res
end
return res
end
number_module.Number = Number
return number_module
|