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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
|
--
-- Copyright (c) 2021-2023 Zeping Lee
-- Released under the MIT license.
-- Repository: https://github.com/zepinglee/citeproc-lua
--
local choose = {}
local element
local ir_node
local util
if kpse then
element = require("citeproc-element")
ir_node = require("citeproc-ir-node")
util = require("citeproc-util")
else
element = require("citeproc.element")
ir_node = require("citeproc.ir-node")
util = require("citeproc.util")
end
local Element = element.Element
local SeqIr = ir_node.SeqIr
-- [Choose](https://docs.citationstyles.org/en/stable/specification.html#choose)
local Choose = Element:derive("choose")
function Choose:from_node(node)
local o = Choose:new()
o.children = {}
o:process_children_nodes(node)
if #o.children == 0 then
return nil
end
return o
end
function Choose:build_ir(engine, state, context)
local active_branch
local branch_ir
local ir = SeqIr:new({}, self)
ir.should_inherit_delim = true
ir.group_var = "UnresolvedPlain"
for _, child in ipairs(self.children) do
if child:evaluate_conditions(engine, state, context) then
active_branch = child
branch_ir = child:build_ir(engine, state, context)
if branch_ir and branch_ir.group_var ~= "missing" then
table.insert(ir.children, branch_ir)
ir.group_var = branch_ir.group_var
ir.name_count = branch_ir.name_count
ir.sort_key = branch_ir.sort_key
else
ir.group_var = "missing"
end
break
end
end
-- util.debug(ir)
if not context.disambiguate then
context.disambiguate = true
for _, child in ipairs(self.children) do
if child:evaluate_conditions(engine, state, context) then
if child ~= active_branch then
ir.disambiguate_branch_ir = child:build_ir(engine, state, context)
end
break
end
end
context.disambiguate = false
end
return ir
end
local Condition = {
condition = nil,
value = nil,
match_type = "all",
}
function Condition:new(condition, value, match_type)
local o = {
condition = condition,
value = value,
match_type = match_type or "all"
}
setmetatable(o, self)
self.__index = self
return o
end
local If = Element:derive("if", {
conditions = nil,
match = "all"
})
function If:new()
local o = Element.new(self)
o.conditions = {}
o.match = "all"
return o
end
function If:from_node(node)
local o = If:new()
-- TODO: disambiguate
-- o:set_bool_attribute(node, "disambiguate")
o:add_conditions(node, "disambiguate")
o:add_conditions(node, "is-numeric")
o:add_conditions(node, "is-uncertain-date")
o:add_conditions(node, "locator")
o:add_conditions(node, "position")
o:add_conditions(node, "type")
o:add_conditions(node, "variable")
o.match = node:get_attribute("match")
o:process_children_nodes(node)
return o
end
function If:add_conditions(node, attribute)
local values = node:get_attribute(attribute)
if not values then
return
end
for _, value in ipairs(util.split(values)) do
local condition = Condition:new(attribute, value, self.match)
table.insert(self.conditions, condition)
end
end
function If:build_children_ir(engine, state, context)
if not self.children then
return nil
end
local irs = {}
local name_count
local ir_sort_key
local group_var = "plain"
for _, child_element in ipairs(self.children) do
local child_ir = child_element:build_ir(engine, state, context)
if child_ir then
local child_group_var = child_ir.group_var
if child_group_var == "important" then
group_var = "important"
elseif child_group_var == "missing" and child_ir._type ~= "YearSuffix" then
if group_var == "plain" then
group_var = "missing"
end
end
if child_ir.name_count then
if not name_count then
name_count = 0
end
name_count = name_count + child_ir.name_count
end
if child_ir.sort_key ~= nil then
ir_sort_key = child_ir.sort_key
end
-- The condition can be simplified
table.insert(irs, child_ir)
end
end
if #irs == 0 then
group_var = "missing"
end
local ir = SeqIr:new(irs, self)
ir.name_count = name_count
ir.sort_key = ir_sort_key
ir.group_var = group_var
return ir
end
function If:build_ir(engine, state, context)
if not self:evaluate_conditions(engine, state, context) then
return nil
end
local ir = self:build_children_ir(engine, state, context)
if not ir then
return nil
end
ir.should_inherit_delim = true
return ir
end
function If:evaluate_conditions(engine, state, context)
local res = false
-- util.debug(self.conditions)
for _, condition in ipairs(self.conditions) do
if self:evaluate_condition(condition, state, context) then
if self.match == "any" then
return true
elseif self.match == "none" then
return false
end
else
if self.match == "all" then
return false
end
end
end
if self.match == "any" then
return false
else
return true
end
end
function If:evaluate_condition(condition, state, context)
-- util.debug(context.cite)
-- util.debug(condition)
if condition.condition == "disambiguate" then
return context.disambiguate or (context.in_bibliography and context.reference.disambiguate)
elseif condition.condition == "is-numeric" then
local variable = context:get_variable(condition.value)
return util.is_numeric(variable)
elseif condition.condition == "is-uncertain-date" then
local variable = context:get_variable(condition.value)
-- TODO
return self:is_uncertain_date(variable)
elseif condition.condition == "locator" then
local locator_label = context:get_variable("label")
if locator_label == "sub verbo" then
locator_label = "sub-verbo"
end
return locator_label == condition.value
elseif condition.condition == "position" then
return self:check_position(condition.value, context)
elseif condition.condition == "type" then
local item_type = context:get_variable("type")
return item_type == condition.value
elseif condition.condition == "variable" then
local var = condition.value
if var == "locator" or var == "label" then
if context.in_bibliography then
return false
else
return context.cite[var] ~= nil
end
else
local res = context.reference[var] ~= nil
return res
end
end
end
function If:is_uncertain_date(variable)
if variable == nil then
return false
end
local circa = variable["circa"]
return circa and circa ~= ""
end
function If:check_position(position, context)
-- util.debug(context.cite)
if context.in_bibliography then
return false
end
local position_level = context.cite.position or context.cite.position_level or 0
-- context.cite.position is for hacking in debugging
-- bugreports_DemoPageFullCiteCruftOnSubsequent.txt
if position == "first" then
return (position_level == util.position_map["first"])
elseif position == "near-note" then
return context.cite["near-note"] or context.cite.near_note
else
return (position_level >= util.position_map[position])
end
end
local ElseIf = If:derive("else-if")
local Else = Element:derive("else")
function Else:from_node(node)
local o = Else:new()
o:process_children_nodes(node)
return o
end
function Else:evaluate_conditions(engine, state, context)
return true
end
Else.build_children_ir = If.build_children_ir
Else.build_ir = If.build_ir
choose.Choose = Choose
choose.If = If
choose.ElseIf = ElseIf
choose.Else = Else
return choose
|