citeproc 1.0.0.pre5 → 1.0.0.pre6

Sign up to get free protection for your applications and to get access to all the features.
data/citeproc.gemspec CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |s|
22
22
  s.license = 'AGPL'
23
23
  s.date = Time.now.strftime('%Y-%m-%d')
24
24
 
25
- s.add_runtime_dependency('multi_json', '~>1.3.5')
25
+ s.add_runtime_dependency('multi_json', '~>1.5')
26
26
  s.add_runtime_dependency('namae', '~>0.3')
27
27
 
28
28
  s.add_development_dependency 'cucumber', '~>1.2'
@@ -47,7 +47,7 @@ module CiteProc
47
47
  # @!attribute suffix
48
48
  # @return [String] a string to print after cites produced for this item
49
49
 
50
- attr_predicates :id, :locator, :label, :'suppress-author',
50
+ attr_predicates :id, :locator, :page, :label, :'suppress-author',
51
51
  :'author-only', :prefix, :suffix
52
52
 
53
53
  # Attributes added by processor
data/lib/citeproc/date.rb CHANGED
@@ -74,7 +74,7 @@ module CiteProc
74
74
  # be used in an external context.
75
75
  class DateParts < Struct.new(:year, :month, :day)
76
76
  include Comparable
77
-
77
+
78
78
  def initialize(*arguments)
79
79
  if arguments.length == 1 && arguments[0].is_a?(::Date)
80
80
  d = arguments[0]
@@ -83,11 +83,11 @@ module CiteProc
83
83
  super(*arguments.map(&:to_i))
84
84
  end
85
85
  end
86
-
86
+
87
87
  def initialize_copy(other)
88
88
  update(other)
89
89
  end
90
-
90
+
91
91
  # Update the date parts with the passed-in values.
92
92
  # @param parts [Array, #each_pair] an ordered list of date parts (year,
93
93
  # month, day) or a Hash containing the mapping
@@ -96,14 +96,14 @@ module CiteProc
96
96
  unless parts.respond_to?(:each_pair)
97
97
  parts = Hash[DateParts.members.zip(parts)]
98
98
  end
99
-
99
+
100
100
  parts.each_pair do |part, value|
101
101
  self[part] = value.nil? ? nil : value.to_i
102
102
  end
103
-
103
+
104
104
  self
105
105
  end
106
-
106
+
107
107
  # @return [Boolean] whether or not the date parts are unset
108
108
  def empty?
109
109
  to_citeproc.empty?
@@ -135,7 +135,7 @@ module CiteProc
135
135
  # parts are not a valid date.
136
136
  def strftime(format = '%F')
137
137
  d = to_date
138
-
138
+
139
139
  if d.nil?
140
140
  nil
141
141
  else
@@ -156,14 +156,14 @@ module CiteProc
156
156
  nil
157
157
  end
158
158
  end
159
-
159
+
160
160
  # Convert the date parts into a proper Ruby date object; if the date
161
161
  # parts are empty, contain zero or are otherwise invalid, nil will
162
162
  # be returned instead.
163
163
  # @return [::Date,nil] the date parts as a Ruby date object
164
164
  def to_date
165
165
  parts = to_citeproc
166
-
166
+
167
167
  if parts.empty? || parts.include?(0)
168
168
  nil
169
169
  else
@@ -175,14 +175,14 @@ module CiteProc
175
175
  end
176
176
  end
177
177
  end
178
-
178
+
179
179
  alias to_ruby to_date
180
-
180
+
181
181
  # @return [Array<Fixnum>] the list of date parts
182
182
  def to_citeproc
183
183
  take_while { |p| !p.nil? }
184
184
  end
185
-
185
+
186
186
  # @return [String] the date parts as a string
187
187
  def to_s
188
188
  to_citeproc.inspect
@@ -193,19 +193,19 @@ module CiteProc
193
193
  "#<DateParts #{to_s}>"
194
194
  end
195
195
  end
196
-
196
+
197
197
 
198
198
  include Attributes
199
199
 
200
200
  alias attributes value
201
201
  protected :value, :attributes
202
-
202
+
203
203
  undef_method :value=
204
-
204
+
205
205
 
206
206
  # List of date parsers (must respond to #parse)
207
207
  @parsers = []
208
-
208
+
209
209
  [%w{ edtf EDTF }, %w{ chronic Chronic }].each do |date_parser, module_id|
210
210
  begin
211
211
  require date_parser
@@ -216,8 +216,8 @@ module CiteProc
216
216
  end
217
217
 
218
218
  @parsers << ::Date
219
-
220
-
219
+
220
+
221
221
  class << self
222
222
 
223
223
  # @!attribute [r] parsers
@@ -246,19 +246,19 @@ module CiteProc
246
246
  rescue ParseError
247
247
  nil
248
248
  end
249
-
249
+
250
250
  # Like #parse but raises a ParseError if the input failed to be parsed.
251
251
  #
252
252
  # @param date_string [String] the date to be parsed
253
253
  # @return [CiteProc::Date] the parsed date
254
254
  #
255
- # @raise [ParseError] when the string cannot be parsed
255
+ # @raise [ParseError] when the string cannot be parsed
256
256
  def parse!(date_string)
257
257
  @parsers.each do |p|
258
258
  date = p.parse(date_string) rescue nil
259
259
  return new(date) unless date.nil?
260
260
  end
261
-
261
+
262
262
  # Subtle: if we get here it means all parsers failed to create a date
263
263
  raise ParseError, "failed to parse #{date_string.inspect}"
264
264
  end
@@ -269,7 +269,7 @@ module CiteProc
269
269
  end
270
270
 
271
271
  alias now today
272
-
272
+
273
273
  end
274
274
 
275
275
 
@@ -293,7 +293,7 @@ module CiteProc
293
293
  super
294
294
  convert_parts!
295
295
  end
296
-
296
+
297
297
  # Replaces the date's value. Typically called by the constructor, this
298
298
  # method intelligently converts various input values.
299
299
  def replace(value)
@@ -317,7 +317,7 @@ module CiteProc
317
317
  @value = attributes.deep_copy
318
318
  end
319
319
  convert_parts!
320
-
320
+
321
321
  when value.is_a?(Array)
322
322
  @value = { :'date-parts' => value[0].is_a?(Array) ? value : [value] }
323
323
  convert_parts!
@@ -336,7 +336,7 @@ module CiteProc
336
336
 
337
337
  self
338
338
  end
339
-
339
+
340
340
  # @return [Array<DateParts>]
341
341
  def date_parts
342
342
  @value[:'date-parts'] ||= []
@@ -361,24 +361,24 @@ module CiteProc
361
361
  # @return [Fixnum] the day (of the start date for ranges)
362
362
  [:year, :month, :day].each do |reader|
363
363
  writer = "#{reader}="
364
-
364
+
365
365
  define_method(reader) do
366
366
  d = parts[0] and d.send(reader)
367
367
  end
368
-
368
+
369
369
  define_method(writer) do |v|
370
370
  parts[0] ||= DateParts.new
371
371
  parts[0].send(writer, v.to_i)
372
372
  end
373
373
  end
374
-
374
+
375
375
  # @return [Date] a copy of the date with an inverted year
376
376
  def -@
377
377
  d = dup
378
378
  d.year = -1 * year
379
379
  d
380
380
  end
381
-
381
+
382
382
  # @return [::Date,nil] the date (start date if this instance is a range); or nil
383
383
  def start_date
384
384
  d = parts[0] and d.to_date
@@ -412,8 +412,8 @@ module CiteProc
412
412
  parts[1] && !parts[1].empty?
413
413
  end
414
414
 
415
- # Returns true if this date is a range
416
415
  alias range? has_end_date?
416
+ alias plural? has_end_date?
417
417
 
418
418
  # @return [Boolean] whether or not this date is an open range
419
419
  def open_range?
@@ -460,7 +460,7 @@ module CiteProc
460
460
  def bc?
461
461
  date = parts[0] and date.bc?
462
462
  end
463
-
463
+
464
464
  # A date is said to be AD when it is in the first millennium, i.e.,
465
465
  # between 1 and 1000 AD
466
466
  # @return [Boolean, nil] whether or not the date is AD; nil if there is
@@ -472,17 +472,17 @@ module CiteProc
472
472
  # @return [Hash] a hash representation of the date.
473
473
  def to_citeproc
474
474
  cp = @value.stringify_keys
475
-
475
+
476
476
  # Convert (or suppress empty) date-parts
477
477
  if parts.all?(&:empty?)
478
478
  cp.delete('date-parts')
479
479
  else
480
480
  cp['date-parts'] = cp['date-parts'].map(&:to_citeproc)
481
481
  end
482
-
482
+
483
483
  cp
484
484
  end
485
-
485
+
486
486
  # @return [String] the date as a string
487
487
  def to_s
488
488
  case
data/lib/citeproc/item.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module CiteProc
2
-
2
+
3
3
  # Items are similar to a Ruby Hash but pose a number of constraints on their
4
4
  # contents: keys are always (implicitly converted to) symbols and values
5
5
  # are strictly {Variable Variables}. When Items are constructed
@@ -24,7 +24,7 @@ module CiteProc
24
24
  # Items can be converted to the CiteProc JSON format via {#to_citeproc}
25
25
  # and {#to_json}.
26
26
  class Item
27
-
27
+
28
28
  @types = [
29
29
  :article, :'article-journal', :'article-magazine', :'article-newspaper',
30
30
  :bill, :book, :broadcast, :chapter, :entry, :'entry-dictionary',
@@ -33,7 +33,7 @@ module CiteProc
33
33
  :pamphlet, :'paper-conference', :patent, :personal_communication, :post,
34
34
  :'post-weblog', :report, :review, :'review-book', :song, :speech,
35
35
  :thesis, :treaty, :webpage].freeze
36
-
36
+
37
37
  @bibtex_types = Hash.new { |h,k| :misc }.merge(Hash[*%w{
38
38
  pamphlet booklet
39
39
  paper-conference conference
@@ -49,13 +49,13 @@ module CiteProc
49
49
  article-journal article
50
50
  article-magazine article
51
51
  }.map(&:intern)]).freeze
52
-
52
+
53
53
  class << self
54
54
  attr_reader :types, :bibtex_types
55
55
  end
56
-
56
+
57
57
  extend Forwardable
58
-
58
+
59
59
  include Attributes
60
60
  include Enumerable
61
61
  include Comparable
@@ -66,38 +66,51 @@ module CiteProc
66
66
  *Variable.fields[:all]
67
67
 
68
68
  def_delegators :attributes, :values_at, :keys, :values
69
-
69
+
70
70
  alias fields keys
71
-
72
- # Hide attributes reader
71
+
72
+ # Hide attributes reader:
73
+ # All access should go through (read|write)_attribute
73
74
  protected :attributes
74
-
75
-
75
+
76
+
76
77
  def initialize(attributes = nil)
77
78
  merge(attributes)
78
79
  yield self if block_given?
79
80
  end
80
-
81
+
81
82
  def initialize_copy(other)
82
83
  @attributes = other.attributes.deep_copy
83
84
  end
84
-
85
- # @param name [Symbol] the name of the variable
86
- #
87
- # @param options [Hash]
88
- # @option options [:short] :form (nil) when given, the variable's
89
- # short form will be returned if available.
90
- #
91
- # @return [Variable, nil] the matching variable
92
- def variable(name, options = {})
93
- if options.key?(:form) && options[:form].to_sym == :short
94
- var = read_attribute "#{name}-short"
95
- return var unless var.nil?
96
- end
97
-
98
- read_attribute name
99
- end
100
-
85
+
86
+
87
+ def observable_read_attribute(key)
88
+ value = original_read_attribute(key)
89
+ ensure
90
+ changed
91
+ notify_observers :read, key, value
92
+ end
93
+
94
+ alias original_read_attribute read_attribute
95
+ alias read_attribute observable_read_attribute
96
+
97
+
98
+ # @param name [Symbol] the name of the variable
99
+ #
100
+ # @param options [Hash]
101
+ # @option options [:short] :form (nil) when given, the variable's
102
+ # short form will be returned if available.
103
+ #
104
+ # @return [Variable, nil] the matching variable
105
+ def variable(name, options = {})
106
+ if options.key?(:form) && options[:form].to_sym == :short
107
+ var = read_attribute "#{name}-short"
108
+ return var unless var.nil?
109
+ end
110
+
111
+ read_attribute name
112
+ end
113
+
101
114
  # Calls a block once for each field in the item, passing the field's
102
115
  # name-value pair as parameters.
103
116
  #
@@ -120,7 +133,7 @@ module CiteProc
120
133
  to_enum
121
134
  end
122
135
  end
123
-
136
+
124
137
  alias each_pair each
125
138
 
126
139
  # Calls a block once for each field in the item, passing the field's
@@ -144,7 +157,7 @@ module CiteProc
144
157
  enum_for :each_value
145
158
  end
146
159
  end
147
-
160
+
148
161
  def <=>(other)
149
162
  return nil unless other.is_a?(Attributes)
150
163
  eql?(other) ? 0 : length <=> other.length
@@ -154,26 +167,26 @@ module CiteProc
154
167
  # installed; otherwise returns a BibTeX string.
155
168
  def to_bibtex
156
169
  # hash = to_hash
157
- #
170
+ #
158
171
  # hash[:type] = Item.bibtex_types[hash[:type]]
159
- #
172
+ #
160
173
  # if hash.has_key?(:issued)
161
174
  # date = hash.delete(:issued)
162
175
  # hash[:year] = date.year
163
176
  # hash[:month] = date.month
164
177
  # end
165
- #
178
+ #
166
179
  # Variable.fields[:date].each do |field|
167
180
  # hash[field] = hash[field].to_s if hash.has_key?(field)
168
181
  # end
169
- #
182
+ #
170
183
  # Variable.fields[:names].each do |field|
171
184
  # hash[field] = hash[field].to_bibtex
172
185
  # end
173
-
186
+
174
187
  raise 'not implemented yet'
175
188
  end
176
-
189
+
177
190
  # @return [Symbol,nil] the item's id
178
191
  def to_sym
179
192
  if id?
@@ -182,13 +195,13 @@ module CiteProc
182
195
  nil
183
196
  end
184
197
  end
185
-
198
+
186
199
  # @return [String] a string containing a human-readable
187
200
  # representation of the item
188
201
  def inspect
189
202
  "#<CiteProc::Item id=#{id.to_s.inspect} attributes={#{attributes.length}}>"
190
203
  end
191
-
204
+
192
205
  private
193
206
 
194
207
  # @private
@@ -196,5 +209,5 @@ module CiteProc
196
209
  Variable.create!(value, key)
197
210
  end
198
211
  end
199
-
212
+
200
213
  end
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  module CiteProc
3
-
3
+
4
4
  # Names consist of several dependent parts of strings. Simple personal names
5
5
  # are composed of family and given elements, containing respectively the
6
6
  # family and given name of the individual.
@@ -32,13 +32,13 @@ module CiteProc
32
32
  #
33
33
  # Name.new(:family => 'Murakami', :given => 'Haruki').to_s
34
34
  # #-> "Haruki Murakami"
35
- #
35
+ #
36
36
  # Name.new(:family => 'Murakami', :given => 'Haruki').static_order!.to_s
37
37
  # #-> "Murakami Haruki"
38
38
  class Name
39
-
39
+
40
40
  extend Forwardable
41
-
41
+
42
42
  include Attributes
43
43
  include Comparable
44
44
 
@@ -59,24 +59,24 @@ module CiteProc
59
59
  :'sort-separator' => ', ',
60
60
  :'initialize-with' => nil
61
61
  }.freeze
62
-
62
+
63
63
  @parts = [:family, :given,:literal, :suffix, :'dropping-particle',
64
64
  :'non-dropping-particle'].freeze
65
-
65
+
66
66
  class << self
67
67
  attr_reader :defaults, :parts, :romanesque
68
68
  end
69
69
 
70
-
70
+
71
71
 
72
72
  # Method generators
73
-
73
+
74
74
  # @!attribute [r] options
75
75
  # @return the name's formatting options
76
76
  attr_reader :options
77
-
77
+
78
78
  attr_predicates :'comma-suffix', :'static-ordering', :multi, *@parts
79
-
79
+
80
80
  # Aliases
81
81
  [[:particle, :'non_dropping_particle']].each do |a, m|
82
82
  alias_method(a, m) if method_defined?(m)
@@ -90,11 +90,11 @@ module CiteProc
90
90
  pa, pm = "has_#{a}?", "has_#{m}?"
91
91
  alias_method(pa, pm) if method_defined?(pm)
92
92
  end
93
-
93
+
94
94
  # Names quack sorta like a String
95
95
  def_delegators :to_s, :=~, :===,
96
96
  *String.instance_methods(false).reject { |m| m =~ /^\W|!$|to_s|replace|first|last/ }
97
-
97
+
98
98
  # Delegate bang! methods to each field's value
99
99
  String.instance_methods(false).each do |m|
100
100
  if m.to_s.end_with?('!')
@@ -107,30 +107,30 @@ module CiteProc
107
107
  end
108
108
  end
109
109
  end
110
-
111
-
110
+
111
+
112
112
  # Instance methods
113
-
113
+
114
114
  def initialize(attributes = {}, options = {})
115
115
  @options = Name.defaults.merge(options)
116
116
  @sort_prefix = (/^(the|an?|der|die|das|eine?|l[ae])\s+|^l\W/i).freeze
117
-
117
+
118
118
  merge(attributes)
119
-
119
+
120
120
  yield self if block_given?
121
121
  end
122
-
122
+
123
123
  def initialize_copy(other)
124
124
  @attributes = other.attributes.deep_copy
125
125
  @options = other.options.dup
126
126
  end
127
-
128
-
127
+
128
+
129
129
  # @return [Boolean] whether or not the Name looks like it belongs to a person
130
130
  def personal?
131
131
  !empty? && !literal?
132
132
  end
133
-
133
+
134
134
 
135
135
  # A name is `romanesque' if it contains only romanesque characters. This
136
136
  # should be the case for the majority of names written in latin- or
@@ -141,9 +141,9 @@ module CiteProc
141
141
  def romanesque?
142
142
  !!([given, family].join.gsub(Variable.markup, '') =~ Name.romanesque)
143
143
  end
144
-
144
+
145
145
  alias byzantine? romanesque?
146
-
146
+
147
147
  # @return [Boolean] whether or not the name should be printed in static order
148
148
  def static_order?
149
149
  static_ordering? || !romanesque?
@@ -166,32 +166,32 @@ module CiteProc
166
166
  def sort_order?
167
167
  !!(options[:'name-as-sort-order'].to_s =~ /^(y(es)?|always|t(rue)?)$/i)
168
168
  end
169
-
169
+
170
170
  def display_order?
171
171
  !sort_order?
172
172
  end
173
-
173
+
174
174
  # Sets the name to use sort-order. The reverse of {#display_order!}.
175
175
  # @return [self]
176
176
  def sort_order!
177
177
  options[:'name-as-sort-order'] = true
178
178
  self
179
179
  end
180
-
180
+
181
181
  # Sets the name to use display-order. The reverse of {#sort_order!}.
182
182
  # @return [self]
183
183
  def display_order!
184
184
  options[:'name-as-sort-order'] = false
185
185
  self
186
186
  end
187
-
187
+
188
188
  # @return [String] the current sort separator
189
189
  def sort_separator
190
190
  options[:'sort-separator']
191
191
  end
192
-
192
+
193
193
  alias comma sort_separator
194
-
194
+
195
195
  # @return [Boolean] whether or not the short form will be used for printing
196
196
  def short_form?
197
197
  options[:form].to_s =~ /short/i
@@ -215,19 +215,19 @@ module CiteProc
215
215
  options[:form] = :long
216
216
  self
217
217
  end
218
-
218
+
219
219
  # @return [Boolean] whether or not initials will be used for printing
220
220
  def initials?
221
221
  !!options[:'initialize-with'] && personal? && romanesque?
222
222
  end
223
-
223
+
224
224
  def demote_non_dropping_particle?
225
225
  always_demote_non_dropping_particle? ||
226
226
  !!(sort_order? && options[:'demote-non-dropping-particle'] =~ /^sort(-only)?$/i)
227
227
  end
228
228
 
229
229
  alias demote_particle? demote_non_dropping_particle?
230
-
230
+
231
231
  def never_demote_non_dropping_particle?
232
232
  !!(options[:'demote-non-dropping-particle'] =~ /^never$/i)
233
233
  end
@@ -265,7 +265,7 @@ module CiteProc
265
265
  return nil unless other.respond_to?(:sort_order_downcase)
266
266
  sort_order_downcase <=> other.sort_order_downcase
267
267
  end
268
-
268
+
269
269
  # @return [String] the name formatted according to the current options
270
270
  def to_s
271
271
  case
@@ -286,12 +286,12 @@ module CiteProc
286
286
  else
287
287
  [family, [given, dropping_particle, particle].compact_join(' '),
288
288
  suffix].compact_join(comma)
289
- end
289
+ end
290
290
  else
291
291
  [particle, family].compact_join(' ')
292
292
  end
293
293
  end
294
-
294
+
295
295
  # @return [Array<String>] an ordered array of formatted name parts to be used for sorting
296
296
  def sort_order
297
297
  case
@@ -303,41 +303,41 @@ module CiteProc
303
303
  [family, [particle, dropping_particle].compact_join(' '), given, suffix].map(&:to_s)
304
304
  end
305
305
  end
306
-
306
+
307
307
  # @return [String] the name as a string stripped off all markup
308
308
  def strip_markup
309
309
  gsub(Variable.markup, '')
310
310
  end
311
-
311
+
312
312
  # @return [self] the name with all parts stripped off markup
313
313
  def strip_markup!
314
314
  gsub!(Variable.markup, '')
315
315
  end
316
-
316
+
317
317
  # @return [Array<String>] the sort order array stripped off markup and downcased
318
318
  def sort_order_downcase
319
319
  sort_order.map { |s| s.downcase.gsub(Variable.markup, '') }
320
320
  end
321
-
321
+
322
322
  # @return [String] a human-readable representation of the name object
323
323
  def inspect
324
324
  "#<CiteProc::Name #{to_s.inspect}>"
325
325
  end
326
-
326
+
327
327
  private
328
-
328
+
329
329
  attr_reader :sort_prefix
330
-
330
+
331
331
  end
332
-
333
-
334
-
332
+
333
+
334
+
335
335
 
336
336
  # Represents a {Variable} containing an ordered list of {Name}
337
337
  # objects. The names can be formatted using CSL formatting options (see
338
338
  # {Names.defaults} for details).
339
339
  class Names < Variable
340
-
340
+
341
341
  @defaults = {
342
342
  :and => ' & ',
343
343
  :delimiter => ', ',
@@ -348,7 +348,7 @@ module CiteProc
348
348
  :'et-al-subsequent-min' => 5,
349
349
  :'et-al-subsequent-use-first' => 3
350
350
  }.freeze
351
-
351
+
352
352
  class << self
353
353
 
354
354
  # @!attribute [r] defaults
@@ -388,9 +388,9 @@ module CiteProc
388
388
  # # referencing earlier cited items)
389
389
  # }
390
390
  #
391
- # @return [Hash] the Names' default formatting options
391
+ # @return [Hash] the Names' default formatting options
392
392
  attr_reader :defaults
393
-
393
+
394
394
  # Parses the passed-in string and returns a Names object. Behaves like
395
395
  # parse but returns nil for bad input without raising an error.
396
396
  #
@@ -403,7 +403,7 @@ module CiteProc
403
403
  rescue ParseError
404
404
  nil
405
405
  end
406
-
406
+
407
407
  # Parses the passed-in string and returns a Names object.
408
408
  #
409
409
  # @param names [String] the name or names to be parsed
@@ -417,19 +417,19 @@ module CiteProc
417
417
  end
418
418
 
419
419
  end
420
-
420
+
421
421
  include Enumerable
422
422
 
423
423
  # @!attribute [r] options
424
424
  # @return [Hash] the current formatting options
425
425
 
426
426
  attr_reader :options
427
-
427
+
428
428
  alias names value
429
-
429
+
430
430
  # Don't expose value/names writer
431
431
  undef_method :value=
432
-
432
+
433
433
  # Delegate bang! methods to each name
434
434
  Name.instance_methods(false).each do |m|
435
435
  if m.to_s.end_with?('!')
@@ -441,11 +441,11 @@ module CiteProc
441
441
  end
442
442
  end
443
443
  end
444
-
444
+
445
445
  # Names quack sorta like an Array
446
446
  def_delegators :names, :length, :empty?, :[], :join
447
447
 
448
-
448
+
449
449
  # Some delegators should return self
450
450
 
451
451
  # @!method push(name)
@@ -455,26 +455,26 @@ module CiteProc
455
455
  # @!method unshift(name)
456
456
  # Inserts the given name at the beginning of the list of names.
457
457
  # @param name [Name] a name
458
- # @return [self]
458
+ # @return [self]
459
459
  [:<<, :push, :unshift].each do |m|
460
460
  define_method(m) do |*arguments, &block|
461
461
  names.send(m, *arguments, &block)
462
462
  self
463
463
  end
464
464
  end
465
-
465
+
466
466
  def initialize(*arguments)
467
467
  @options = Names.defaults.dup
468
468
  super(arguments.flatten(1))
469
469
  end
470
-
470
+
471
471
  def initialize_copy(other)
472
472
  @options, @value = other.options.dup, other.value.map(&:dup)
473
473
  end
474
-
474
+
475
475
  def replace(values)
476
476
  @value = []
477
-
477
+
478
478
  [*values].each do |value|
479
479
  case
480
480
  when value.is_a?(Name)
@@ -488,34 +488,34 @@ module CiteProc
488
488
  raise TypeError, $!.message
489
489
  end
490
490
  else
491
- raise TypeError, "failed to create names from #{value.inspect}"
491
+ raise TypeError, "failed to create names from #{value.inspect}"
492
492
  end
493
493
  end
494
-
494
+
495
495
  self
496
496
  end
497
-
497
+
498
498
  # @return [Fixnum] the maximum number of names that should be printed
499
499
  def max_names
500
500
  [length, options[:'et-al-use-first'].to_i.abs].min
501
501
  end
502
-
502
+
503
503
  # @return [Boolean] whether or not the Names should be truncate
504
504
  def truncate?
505
505
  length >= options[:'et-al-min'].to_i.abs
506
506
  end
507
-
507
+
508
508
  # @return [Boolean] whether ot not the Names, if printed on subsequent
509
509
  # cites, should be truncated
510
510
  def truncate_subsequent?
511
511
  length >= options[:'et-al-subsequent-min'].to_i
512
512
  end
513
-
513
+
514
514
  # @return [String] the delimiter between names
515
515
  def delimiter
516
516
  options[:delimiter]
517
517
  end
518
-
518
+
519
519
  # @return [String] the delimiter between the penultimate and last name
520
520
  # @see #connector
521
521
  # @see #delimiter_precedes_last?
@@ -526,26 +526,26 @@ module CiteProc
526
526
  connector
527
527
  end
528
528
  end
529
-
529
+
530
530
  # @return [String] the delimiter between the last name printed name and
531
531
  # the 'and others' term
532
532
  def truncated_delimiter
533
533
  max_names > 1 ? delimiter : ' '
534
534
  end
535
-
535
+
536
536
  # @return [Boolean] whether or not the delimiter will be inserted between
537
537
  # the penultimate and the last name
538
538
  def delimiter_precedes_last?
539
539
  case
540
540
  when delimiter_never_precedes_last?
541
- false
541
+ false
542
542
  when delimiter_always_precedes_last?
543
543
  true
544
544
  else
545
545
  length > 2
546
546
  end
547
547
  end
548
-
548
+
549
549
  # @return [Boolean] whether or not the should always be inserted between
550
550
  # the penultimate and the last name
551
551
  def delimiter_always_precedes_last?
@@ -561,7 +561,7 @@ module CiteProc
561
561
 
562
562
  alias delimiter_precedes_last! delimiter_always_precedes_last!
563
563
 
564
-
564
+
565
565
  # @return [Boolean] whether or not the should never be inserted between
566
566
  # the penultimate and the last name
567
567
  def delimiter_never_precedes_last?
@@ -587,22 +587,27 @@ module CiteProc
587
587
  options[:'delimiter-precedes-last'] = :contextual
588
588
  self
589
589
  end
590
-
590
+
591
591
  # @return [String] the connector between the penultimate and the last name
592
592
  def connector
593
593
  options[:and]
594
594
  end
595
-
595
+
596
596
  # @return [false] Names are non-numeric Variables
597
597
  def numeric?
598
598
  false
599
599
  end
600
600
 
601
+ # @return [Boolean] whether or not the variable holds more than one Name
602
+ def plural?
603
+ length > 1
604
+ end
605
+
601
606
  # Calls a block once for each name. If no block is given, an enumerator
602
607
  # is returned instead.
603
608
  #
604
609
  # @yieldparam name [Name] a name in the list
605
- # @return [self,Enumerator] self or an enumerator if no block is given
610
+ # @return [self,Enumerator] self or an enumerator if no block is given
606
611
  def each
607
612
  if block_given?
608
613
  names.each(&Proc.new)
@@ -611,7 +616,7 @@ module CiteProc
611
616
  to_enum
612
617
  end
613
618
  end
614
-
619
+
615
620
  # Compares two lists of Names.
616
621
  # @param other [(Name)] a list of names
617
622
  # @return [Fixnum,nil] -1, 0, or 1 depending on the result of the
@@ -620,13 +625,15 @@ module CiteProc
620
625
  return nil unless other.respond_to?(:to_a)
621
626
  to_a <=> other.to_a
622
627
  end
623
-
628
+
629
+ alias to_i length
630
+
624
631
  # Converts the list of names into a formatted string depending on the
625
632
  # current formatting options.
626
633
  # @return [String] the formatted list of names
627
634
  def to_s
628
635
  case
629
- when truncate?
636
+ when truncate?
630
637
  [names[0...max_names].join(delimiter), options[:'et-al']].join(truncated_delimiter)
631
638
  when length < 2
632
639
  names.join(last_delimiter)
@@ -634,22 +641,22 @@ module CiteProc
634
641
  [names[0...-1].join(delimiter), names[-1]].join(last_delimiter)
635
642
  end
636
643
  end
637
-
644
+
638
645
  # @return [String] the names in a BibTeX-compatible format
639
646
  def to_bibtex
640
647
  map { |n| n.dup.sort_order! }.join(' and ')
641
648
  end
642
-
649
+
643
650
  # @return [Array<Hash>] the list of names converted to hash objects
644
651
  def to_citeproc
645
652
  map(&:to_citeproc)
646
653
  end
647
-
654
+
648
655
  # @return [String] a human-readable representation of the Names object
649
656
  def inspect
650
657
  "#<CiteProc::Names #{to_s.inspect}>"
651
658
  end
652
-
659
+
653
660
  end
654
-
661
+
655
662
  end
@@ -34,8 +34,8 @@ module CiteProc
34
34
  first-reference-note-number genre ISBN ISSN jurisdiction keyword
35
35
  locator medium note original-publisher original-publisher-place
36
36
  original-title page page-first PMID PMCID publisher publisher-place
37
- references section source status title title-short URL version
38
- year-suffix
37
+ references reviewed-author reviewed-title scale section source status
38
+ title title-short URL version year-suffix
39
39
  }
40
40
  })
41
41
 
@@ -167,6 +167,15 @@ module CiteProc
167
167
  @type ||= self.class.name.split(/::/)[-1].downcase.to_sym
168
168
  end
169
169
 
170
+ # @return [Boolean] whether or not the variable holds a plural value
171
+ def plural?
172
+ if numeric?
173
+ !!match(/\S\s*[,&-]\s*\S|\df/)
174
+ else
175
+ false
176
+ end
177
+ end
178
+
170
179
  # Tests whether the variable contains numeric content. Content is
171
180
  # considered numeric if it solely consists of numbers. Numbers may have
172
181
  # prefixes and suffixes ("D2", "2b", "L2d"), and may be separated by a
@@ -176,9 +185,9 @@ module CiteProc
176
185
  #
177
186
  # @return [Boolean] whether or not the variable's value is numeric
178
187
  def numeric?
179
- !!match(/^\w*\d+\w*(\s*[,&-]\s*\w*\d+\w*)*$/i)
188
+ !!match(/^[\w\.:;]*\d+[\w\.:;]*(\s*[,&-]\s*[\w\.:;]*\d+[\w\.:;]*)*$/i)
180
189
  end
181
-
190
+
182
191
  # @return [Fixnum] the first (!) numeric data contained in the variable's
183
192
  # value; zero if no numeric data is present
184
193
  def to_i
@@ -1,3 +1,3 @@
1
1
  module CiteProc
2
- VERSION = '1.0.0.pre5'.freeze
2
+ VERSION = '1.0.0.pre6'.freeze
3
3
  end
@@ -459,7 +459,7 @@ module CiteProc
459
459
  end
460
460
 
461
461
  it '#parse! raises an error on bad input' do
462
- expect { Names.parse!('A,B,C,D,E') }.to raise_error(ParseError)
462
+ expect { Names.parse!('23') }.to raise_error(ParseError)
463
463
  end
464
464
 
465
465
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: citeproc
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre5
4
+ version: 1.0.0.pre6
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,22 +9,27 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-13 00:00:00.000000000 Z
12
+ date: 2013-01-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: multi_json
16
- requirement: &70321665463660 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 1.3.5
21
+ version: '1.5'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70321665463660
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.5'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: namae
27
- requirement: &70321665462900 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ~>
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: '0.3'
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *70321665462900
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '0.3'
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: cucumber
38
- requirement: &70321665462100 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ~>
@@ -43,10 +53,15 @@ dependencies:
43
53
  version: '1.2'
44
54
  type: :development
45
55
  prerelease: false
46
- version_requirements: *70321665462100
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.2'
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: rspec
49
- requirement: &70321665477800 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ~>
@@ -54,10 +69,15 @@ dependencies:
54
69
  version: '2.7'
55
70
  type: :development
56
71
  prerelease: false
57
- version_requirements: *70321665477800
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '2.7'
58
78
  - !ruby/object:Gem::Dependency
59
79
  name: rake
60
- requirement: &70321665477300 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
61
81
  none: false
62
82
  requirements:
63
83
  - - ~>
@@ -65,7 +85,12 @@ dependencies:
65
85
  version: '0.9'
66
86
  type: :development
67
87
  prerelease: false
68
- version_requirements: *70321665477300
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: '0.9'
69
94
  description: ! "\n A cite processor interface for Citation Style Language (CSL)
70
95
  styles.\n "
71
96
  email:
@@ -136,7 +161,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
136
161
  version: '0'
137
162
  segments:
138
163
  - 0
139
- hash: -3374209156135938924
164
+ hash: 91495025789271723
140
165
  required_rubygems_version: !ruby/object:Gem::Requirement
141
166
  none: false
142
167
  requirements:
@@ -145,7 +170,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
145
170
  version: 1.3.1
146
171
  requirements: []
147
172
  rubyforge_project:
148
- rubygems_version: 1.8.10
173
+ rubygems_version: 1.8.24
149
174
  signing_key:
150
175
  specification_version: 3
151
176
  summary: A cite processor interface.