csl 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.coveralls.yml +1 -0
- data/.gitignore +1 -0
- data/.simplecov +3 -1
- data/.travis.yml +4 -10
- data/AGPL +1 -1
- data/BSDL +2 -2
- data/Gemfile +22 -12
- data/README.md +20 -11
- data/Rakefile +6 -1
- data/csl.gemspec +4 -2
- data/features/parser/choose.feature +16 -0
- data/features/step_definitions/parser_steps.rb +10 -0
- data/features/support/env.rb +16 -2
- data/lib/csl.rb +7 -4
- data/lib/csl/compatibility.rb +10 -16
- data/lib/csl/info.rb +3 -2
- data/lib/csl/locale.rb +92 -19
- data/lib/csl/locale/term.rb +41 -2
- data/lib/csl/name_options.rb +44 -0
- data/lib/csl/node.rb +54 -6
- data/lib/csl/parser.rb +17 -17
- data/lib/csl/schema.rb +37 -32
- data/lib/csl/style.rb +32 -8
- data/lib/csl/style/bibliography.rb +46 -9
- data/lib/csl/style/choose.rb +4 -2
- data/lib/csl/style/citation.rb +10 -11
- data/lib/csl/style/group.rb +13 -6
- data/lib/csl/style/label.rb +1 -1
- data/lib/csl/style/layout.rb +4 -4
- data/lib/csl/style/names.rb +161 -22
- data/lib/csl/style/sort.rb +74 -18
- data/lib/csl/style/text.rb +6 -4
- data/lib/csl/treelike.rb +16 -5
- data/lib/csl/version.rb +2 -2
- data/spec/csl/locale/term_spec.rb +70 -70
- data/spec/csl/locale_spec.rb +140 -99
- data/spec/csl/parser_spec.rb +26 -26
- data/spec/csl/schema_spec.rb +15 -15
- data/spec/csl/style/layout_spec.rb +2 -2
- data/spec/csl/style/sort_spec.rb +11 -0
- data/spec/spec_helper.rb +13 -4
- metadata +20 -14
data/lib/csl/style.rb
CHANGED
|
@@ -3,6 +3,8 @@ module CSL
|
|
|
3
3
|
class Style < Node
|
|
4
4
|
types << CSL::Info << CSL::Locale
|
|
5
5
|
|
|
6
|
+
include InheritableNameOptions
|
|
7
|
+
|
|
6
8
|
@default = :apa
|
|
7
9
|
|
|
8
10
|
@root = '/usr/local/share/csl/styles'.freeze
|
|
@@ -14,9 +16,9 @@ module CSL
|
|
|
14
16
|
include Loader
|
|
15
17
|
|
|
16
18
|
attr_accessor :default
|
|
17
|
-
|
|
18
|
-
def load(input =
|
|
19
|
-
super
|
|
19
|
+
|
|
20
|
+
def load(input = nil)
|
|
21
|
+
super(input || Style.default)
|
|
20
22
|
end
|
|
21
23
|
end
|
|
22
24
|
|
|
@@ -45,8 +47,7 @@ module CSL
|
|
|
45
47
|
:independent_parent_link, :independent_parent_link=,
|
|
46
48
|
:has_independent_parent_link?, :title=, :id=, :has_title?, :has_id?,
|
|
47
49
|
:published_at, :updated_at, :citation_format, :citation_format=,
|
|
48
|
-
:
|
|
49
|
-
:default_license!
|
|
50
|
+
:update!, :license, :license=, :default_license?, :default_license!
|
|
50
51
|
|
|
51
52
|
def initialize(attributes = {})
|
|
52
53
|
super(attributes, &nil)
|
|
@@ -77,6 +78,7 @@ module CSL
|
|
|
77
78
|
validate.empty?
|
|
78
79
|
end
|
|
79
80
|
|
|
81
|
+
remove_method :info # generated by struct_children
|
|
80
82
|
def info
|
|
81
83
|
children[:info] ||= Info.new
|
|
82
84
|
end
|
|
@@ -114,6 +116,28 @@ module CSL
|
|
|
114
116
|
load_related_style_from independent_parent_link
|
|
115
117
|
end
|
|
116
118
|
|
|
119
|
+
def demote_non_dropping_particle
|
|
120
|
+
attributes[:'demote-non-dropping-particle']
|
|
121
|
+
end
|
|
122
|
+
alias demote_particle demote_non_dropping_particle
|
|
123
|
+
|
|
124
|
+
def demote_non_dropping_particle?
|
|
125
|
+
attribute?(:'demote-non-dropping-particle')
|
|
126
|
+
end
|
|
127
|
+
alias demote_particle? demote_non_dropping_particle?
|
|
128
|
+
|
|
129
|
+
def initialize_without_hyphen?
|
|
130
|
+
attribute?(:'initialize-with-hyphen') && !attributes[:'initialize-with-hyphen']
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def has_page_range_format?
|
|
134
|
+
attribute?(:'page-range-format')
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def page_range_format
|
|
138
|
+
attributes[:'page-range-format']
|
|
139
|
+
end
|
|
140
|
+
|
|
117
141
|
private
|
|
118
142
|
|
|
119
143
|
def preamble
|
|
@@ -124,7 +148,7 @@ module CSL
|
|
|
124
148
|
# TODO try local first
|
|
125
149
|
Style.load(uri)
|
|
126
150
|
end
|
|
127
|
-
|
|
151
|
+
|
|
128
152
|
def added_macro(node)
|
|
129
153
|
unless node.attribute?(:name)
|
|
130
154
|
raise ValidationError,
|
|
@@ -138,10 +162,10 @@ module CSL
|
|
|
138
162
|
|
|
139
163
|
macros[node[:name]] = node
|
|
140
164
|
end
|
|
141
|
-
|
|
165
|
+
|
|
142
166
|
def deleted_macro(node)
|
|
143
167
|
macros.delete node[:name]
|
|
144
168
|
end
|
|
145
169
|
end
|
|
146
170
|
|
|
147
|
-
end
|
|
171
|
+
end
|
|
@@ -1,15 +1,52 @@
|
|
|
1
1
|
module CSL
|
|
2
2
|
class Style
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
class Bibliography < Node
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
|
|
6
|
+
include InheritableNameOptions
|
|
7
|
+
|
|
8
|
+
attr_struct :'subsequent-author-substitute',
|
|
9
|
+
:'subsequent-author-substitute-rule',
|
|
10
|
+
*Schema.attr(:bibliography, :name, :names)
|
|
11
|
+
|
|
10
12
|
attr_children :sort, :layout
|
|
11
|
-
|
|
13
|
+
|
|
14
|
+
attr_defaults :'line-spacing' => 1, :'entry-spacing' => 1,
|
|
15
|
+
:'subsequent-author-substitute-rule' => 'complete-all'
|
|
16
|
+
|
|
17
|
+
alias sort? has_sort?
|
|
18
|
+
|
|
19
|
+
def bibliography_options
|
|
20
|
+
attributes_for(*Schema.attr(:bibliography))
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def sort_keys
|
|
24
|
+
return [] unless sort?
|
|
25
|
+
children[:sort].descendants
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def substitute_subsequent_authors?
|
|
29
|
+
attribute?(:'subsequent-author-substitute')
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def subsequent_author_substitute
|
|
33
|
+
attributes[:'subsequent-author-substitute'].to_s
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def subsequent_author_substitute_rule
|
|
37
|
+
attributes[:'subsequent-author-substitute-rule'].to_s
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def substitute_subsequent_authors_completely?
|
|
41
|
+
return false unless substitute_subsequent_authors?
|
|
42
|
+
subsequent_author_substitute_rule == 'complete-all'
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def substitute_subsequent_authors_individually?
|
|
46
|
+
return false unless substitute_subsequent_authors?
|
|
47
|
+
subsequent_author_substitute_rule != 'complete-all'
|
|
48
|
+
end
|
|
12
49
|
end
|
|
13
|
-
|
|
50
|
+
|
|
14
51
|
end
|
|
15
|
-
end
|
|
52
|
+
end
|
data/lib/csl/style/choose.rb
CHANGED
|
@@ -3,6 +3,8 @@ module CSL
|
|
|
3
3
|
|
|
4
4
|
class Choose < Node
|
|
5
5
|
|
|
6
|
+
alias blocks children
|
|
7
|
+
|
|
6
8
|
class Block < Node
|
|
7
9
|
attr_struct :match, *Schema.attr(:conditionals)
|
|
8
10
|
|
|
@@ -10,7 +12,7 @@ module CSL
|
|
|
10
12
|
|
|
11
13
|
class << self
|
|
12
14
|
def matches?(nodename)
|
|
13
|
-
nodename
|
|
15
|
+
nodename === ':if' || nodename === ':elseif' || nodename === ':else'
|
|
14
16
|
end
|
|
15
17
|
end
|
|
16
18
|
|
|
@@ -52,4 +54,4 @@ module CSL
|
|
|
52
54
|
end
|
|
53
55
|
|
|
54
56
|
end
|
|
55
|
-
end
|
|
57
|
+
end
|
data/lib/csl/style/citation.rb
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
module CSL
|
|
2
2
|
class Style
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
class Citation < Node
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
*Schema.attr(:names, :name)
|
|
11
|
-
|
|
5
|
+
|
|
6
|
+
include InheritableNameOptions
|
|
7
|
+
|
|
8
|
+
attr_struct(*Schema.attr(:citation, :names, :name))
|
|
9
|
+
|
|
12
10
|
attr_children :sort, :layout
|
|
13
|
-
|
|
11
|
+
|
|
12
|
+
alias sort? has_sort?
|
|
14
13
|
end
|
|
15
|
-
|
|
14
|
+
|
|
16
15
|
end
|
|
17
|
-
end
|
|
16
|
+
end
|
data/lib/csl/style/group.rb
CHANGED
|
@@ -13,18 +13,25 @@ module CSL
|
|
|
13
13
|
# the Group calls a variable (either directly or via a macro), and
|
|
14
14
|
# b) all variables that are called are empty.
|
|
15
15
|
class Group < Node
|
|
16
|
-
attr_struct(*Schema.attr(:formatting, :
|
|
16
|
+
attr_struct(*Schema.attr(:formatting, :delimiter))
|
|
17
17
|
|
|
18
18
|
def delimiter
|
|
19
19
|
attributes.fetch(:delimiter, '')
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
# Returns only those formatting options applicable to the Group
|
|
23
|
+
# node itself; not those which are transmitted to the enclosed
|
|
24
|
+
# elements.
|
|
25
|
+
#
|
|
26
|
+
# @return [Hash] the node's formatting options
|
|
27
|
+
def formatting_options
|
|
28
|
+
attributes_for :display, *Schema.attr(:affixes)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def inheritable_formatting_options
|
|
32
|
+
attributes_for :'text-case', *Schema.attr(:font)
|
|
26
33
|
end
|
|
27
34
|
end
|
|
28
35
|
|
|
29
36
|
end
|
|
30
|
-
end
|
|
37
|
+
end
|
data/lib/csl/style/label.rb
CHANGED
data/lib/csl/style/layout.rb
CHANGED
data/lib/csl/style/names.rb
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
1
3
|
module CSL
|
|
2
4
|
class Style
|
|
3
5
|
|
|
4
6
|
class Names < Node
|
|
7
|
+
extend InheritsNameOptions
|
|
5
8
|
|
|
6
|
-
attr_struct :variable, *Schema.attr(:
|
|
9
|
+
attr_struct :variable, *Schema.attr(:delimiter, :affixes, :font)
|
|
7
10
|
|
|
8
11
|
attr_children :name, :'et-al', :label, :substitute
|
|
9
12
|
|
|
13
|
+
inherits :names_options
|
|
14
|
+
|
|
10
15
|
alias labels label
|
|
11
16
|
|
|
12
17
|
def initialize(attributes = {})
|
|
@@ -16,8 +21,10 @@ module CSL
|
|
|
16
21
|
yield self if block_given?
|
|
17
22
|
end
|
|
18
23
|
|
|
19
|
-
def delimiter
|
|
20
|
-
attributes.fetch(:delimiter
|
|
24
|
+
def delimiter(node = nil, style = nil)
|
|
25
|
+
attributes.fetch(:delimiter) do
|
|
26
|
+
inherited_names_options(node, style)[:delimiter] || ''
|
|
27
|
+
end
|
|
21
28
|
end
|
|
22
29
|
|
|
23
30
|
def has_variable?
|
|
@@ -32,15 +39,20 @@ module CSL
|
|
|
32
39
|
|
|
33
40
|
|
|
34
41
|
class Name < Node
|
|
42
|
+
extend InheritsNameOptions
|
|
35
43
|
|
|
36
44
|
attr_struct :form, *Schema.attr(:name, :affixes, :font, :delimiter)
|
|
37
45
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
# Having default attributes makes inheritance really difficult.
|
|
47
|
+
#
|
|
48
|
+
# attr_defaults :form => 'long', :delimiter => ', ',
|
|
49
|
+
# :'delimiter-precedes-last' => 'contextual', :initialize => true,
|
|
50
|
+
# :'sort-separator' => ', '
|
|
41
51
|
|
|
42
52
|
attr_children :'name-part'
|
|
43
53
|
|
|
54
|
+
inherits :name_options
|
|
55
|
+
|
|
44
56
|
alias parts name_part
|
|
45
57
|
|
|
46
58
|
def initialize(attributes = {})
|
|
@@ -50,17 +62,29 @@ module CSL
|
|
|
50
62
|
yield self if block_given?
|
|
51
63
|
end
|
|
52
64
|
|
|
65
|
+
def count?
|
|
66
|
+
attribute?(:form) && attributes[:form] == 'count'
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def name_options
|
|
70
|
+
attributes_for :form, :initialize, :'initialize-with', :'sort-separator'
|
|
71
|
+
end
|
|
53
72
|
|
|
54
|
-
def
|
|
55
|
-
|
|
73
|
+
def initialize_without_hyphen?
|
|
74
|
+
!root? && root.respond_to?(:initialize_without_hyphen?) &&
|
|
75
|
+
root.initialize_without_hyphen?
|
|
56
76
|
end
|
|
57
77
|
|
|
58
78
|
def et_al
|
|
59
|
-
parent && parent.et_al
|
|
79
|
+
@et_al || parent && parent.et_al
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def et_al=(et_al)
|
|
83
|
+
@et_al = et_al
|
|
60
84
|
end
|
|
61
85
|
|
|
62
86
|
# @param names [#to_i, Enumerable] the list of names (or its length)
|
|
63
|
-
# @return [Boolean] whether or not the should be
|
|
87
|
+
# @return [Boolean] whether or not the list should be truncated
|
|
64
88
|
def truncate?(names, subsequent = false)
|
|
65
89
|
names = names.length if names.respond_to?(:length)
|
|
66
90
|
limit = truncate_when(subsequent)
|
|
@@ -79,35 +103,60 @@ module CSL
|
|
|
79
103
|
|
|
80
104
|
def truncate_when(subsequent = false)
|
|
81
105
|
if subsequent && attribute?(:'et-al-subsequent-min')
|
|
82
|
-
|
|
106
|
+
attributes[:'et-al-subsequent-min'].to_i
|
|
83
107
|
else
|
|
84
|
-
|
|
108
|
+
attributes[:'et-al-min'].to_i
|
|
85
109
|
end
|
|
86
110
|
end
|
|
87
111
|
|
|
88
112
|
def truncate_at(subsequent = false)
|
|
89
113
|
if subsequent && attribute?(:'et-al-subsequent-use-first')
|
|
90
|
-
|
|
114
|
+
attributes.fetch(:'et-al-subsequent-use-first', 1).to_i
|
|
91
115
|
else
|
|
92
|
-
|
|
116
|
+
attributes.fetch(:'et-al-use-first', 1).to_i
|
|
93
117
|
end
|
|
94
118
|
end
|
|
95
119
|
|
|
120
|
+
def truncate_at!(at)
|
|
121
|
+
attributes[:'et-al-use-first'] = at.to_i
|
|
122
|
+
self
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def truncate_when!(pos)
|
|
126
|
+
attributes[:'et-al-min'] = pos.to_i
|
|
127
|
+
self
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def truncate_subsequent_at!(at)
|
|
131
|
+
attributes[:'et-al-subsequent-use-first'] = at.to_i
|
|
132
|
+
self
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def truncate_subsequent_when!(pos)
|
|
136
|
+
attributes[:'et-al-subsequent-min'] = pos.to_i
|
|
137
|
+
self
|
|
138
|
+
end
|
|
139
|
+
|
|
96
140
|
# @return [String] the delimiter between family and given names
|
|
97
141
|
# in sort order
|
|
98
142
|
def sort_separator
|
|
99
|
-
attributes[:'sort-separator']
|
|
143
|
+
attributes[:'sort-separator'] || ', '
|
|
100
144
|
end
|
|
101
145
|
|
|
102
146
|
# @return [String] the delimiter between names
|
|
103
147
|
def delimiter
|
|
104
|
-
attributes[:delimiter]
|
|
148
|
+
attributes[:delimiter] || ', '
|
|
105
149
|
end
|
|
106
150
|
|
|
107
151
|
def name_as_sort_order?
|
|
108
152
|
attribute?(:'name-as-sort-order')
|
|
109
153
|
end
|
|
110
154
|
|
|
155
|
+
def name_as_sort_order_at?(position)
|
|
156
|
+
return false unless name_as_sort_order?
|
|
157
|
+
all_names_as_sort_order? || position == 1 && first_name_as_sort_order?
|
|
158
|
+
end
|
|
159
|
+
|
|
111
160
|
def name_as_sort_order
|
|
112
161
|
attributes[:'name-as-sort-order'].to_s
|
|
113
162
|
end
|
|
@@ -115,14 +164,91 @@ module CSL
|
|
|
115
164
|
alias sort_order name_as_sort_order
|
|
116
165
|
|
|
117
166
|
def first_name_as_sort_order?
|
|
118
|
-
attributes[:'name-as-sort-order'].to_s =~ /^first$/i
|
|
167
|
+
!!(attributes[:'name-as-sort-order'].to_s =~ /^first$/i)
|
|
119
168
|
end
|
|
120
169
|
|
|
121
170
|
def all_names_as_sort_order?
|
|
122
|
-
attributes[:'name-as-sort-order'].to_s =~ /^all$/i
|
|
171
|
+
!!(attributes[:'name-as-sort-order'].to_s =~ /^all$/i)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def first_name_as_sort_order!
|
|
175
|
+
attributes[:'name-as-sort-order'] = 'first'
|
|
176
|
+
self
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def all_names_as_sort_order!
|
|
180
|
+
attributes[:'name-as-sort-order'] = 'all'
|
|
181
|
+
self
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def delimiter_precedes_et_al?(names)
|
|
185
|
+
names = names.length if names.respond_to?(:length)
|
|
186
|
+
|
|
187
|
+
case
|
|
188
|
+
when delimiter_never_precedes_et_al?
|
|
189
|
+
false
|
|
190
|
+
when delimiter_always_precedes_et_al?
|
|
191
|
+
true
|
|
192
|
+
when delimiter_precedes_et_al_after_inverted_name?
|
|
193
|
+
name_as_sort_order_at?(names.to_i)
|
|
194
|
+
else
|
|
195
|
+
names.to_i > 1
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# @return [Boolean] whether or not the delimmiter should
|
|
200
|
+
# always be inserted before et-al
|
|
201
|
+
def delimiter_always_precedes_et_al?
|
|
202
|
+
!!(attributes[:'delimiter-precedes-et-al'].to_s =~ /^always$/i)
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# Set the :'delimiter-precedes-et-al' attribute to 'always'.
|
|
206
|
+
# @return [self] self
|
|
207
|
+
def delimiter_always_precedes_et_al!
|
|
208
|
+
attributes[:'delimiter-precedes-et-al'] = 'always'
|
|
209
|
+
self
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
alias delimiter_precedes_et_al! delimiter_always_precedes_et_al!
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
# @return [Boolean] whether or not the delimiter should
|
|
216
|
+
# never be inserted before et-al
|
|
217
|
+
def delimiter_never_precedes_et_al?
|
|
218
|
+
!!(attributes[:'delimiter-precedes-et-al'].to_s =~ /^never$/i)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# Set the :'delimiter-precedes-et-al' attribute to 'never'
|
|
222
|
+
# @return [self] self
|
|
223
|
+
def delimiter_never_precedes_et_al!
|
|
224
|
+
attributes[:'delimiter-precedes-et-al'] = 'never'
|
|
225
|
+
self
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# @return [Boolean] whether or not the delimtier should
|
|
229
|
+
# be inserted between before et-al depending on the
|
|
230
|
+
# number of names rendered
|
|
231
|
+
def delimiter_contextually_precedes_et_al?
|
|
232
|
+
return true unless attribute?[:'delimiter-precedes-et-al']
|
|
233
|
+
!!(attributes[:'delimiter-precedes-et-al'].to_s =~ /^contextual/i)
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# Set the :'delimiter-precedes-et-al' attribute to 'contextual'
|
|
237
|
+
# @return [self] self
|
|
238
|
+
def delimiter_contextually_precedes_et_al!
|
|
239
|
+
attributes[:'delimiter-precedes-et-al'] = 'contextual'
|
|
240
|
+
self
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def delimiter_precedes_et_al_after_inverted_name?
|
|
244
|
+
!!(attributes[:'delimiter-precedes-et-al'].to_s =~ /^after-inverted-name/i)
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def delimiter_precedes_et_al_after_inverted_name!
|
|
248
|
+
attributes[:'delimiter-precedes-et-al'] = 'after-inverted-name'
|
|
249
|
+
self
|
|
123
250
|
end
|
|
124
251
|
|
|
125
|
-
|
|
126
252
|
# @param names [#to_i, Enumerable] the list of names (or its length)
|
|
127
253
|
# @return [Boolean] whether or not the delimiter will be inserted between
|
|
128
254
|
# the penultimate and the last name
|
|
@@ -136,7 +262,7 @@ module CSL
|
|
|
136
262
|
false
|
|
137
263
|
when delimiter_always_precedes_last?
|
|
138
264
|
true
|
|
139
|
-
when
|
|
265
|
+
when delimiter_precedes_last_after_inverted_name?
|
|
140
266
|
if name_as_sort_order?
|
|
141
267
|
all_names_as_sort_order? || names.to_i == 2
|
|
142
268
|
else
|
|
@@ -180,6 +306,7 @@ module CSL
|
|
|
180
306
|
# @return [Boolean] whether or not the should be inserted between the
|
|
181
307
|
# penultimate and the last name depending on the number of names
|
|
182
308
|
def delimiter_contextually_precedes_last?
|
|
309
|
+
return true unless attribute?(:'delimiter-precedes-last')
|
|
183
310
|
!!(attributes[:'delimiter-precedes-last'].to_s =~ /^contextual/i)
|
|
184
311
|
end
|
|
185
312
|
|
|
@@ -203,20 +330,32 @@ module CSL
|
|
|
203
330
|
attributes[:'et-al-use-last'].to_s =~ /^true$/
|
|
204
331
|
end
|
|
205
332
|
|
|
333
|
+
def ellipsis
|
|
334
|
+
"#{delimiter}… "
|
|
335
|
+
end
|
|
336
|
+
|
|
206
337
|
def connector
|
|
207
338
|
c = attributes[:and]
|
|
208
339
|
c == 'symbol' ? '&' : c
|
|
209
340
|
end
|
|
341
|
+
|
|
342
|
+
def connector=(c)
|
|
343
|
+
attributes[:and] = c
|
|
344
|
+
end
|
|
210
345
|
end
|
|
211
346
|
|
|
212
347
|
class NamePart < Node
|
|
213
348
|
has_no_children
|
|
214
349
|
attr_struct :name, :'text-case', *Schema.attr(:affixes, :font)
|
|
350
|
+
|
|
351
|
+
def name
|
|
352
|
+
attributes[:name]
|
|
353
|
+
end
|
|
215
354
|
end
|
|
216
355
|
|
|
217
356
|
class EtAl < Node
|
|
218
357
|
has_no_children
|
|
219
|
-
attr_struct :term, *Schema.attr(:affixes, :font)
|
|
358
|
+
attr_struct :term, :'text-case', *Schema.attr(:affixes, :font)
|
|
220
359
|
|
|
221
360
|
attr_defaults :term => 'et-al'
|
|
222
361
|
end
|
|
@@ -226,4 +365,4 @@ module CSL
|
|
|
226
365
|
|
|
227
366
|
|
|
228
367
|
end
|
|
229
|
-
end
|
|
368
|
+
end
|