citeproc 1.0.0.pre5 → 1.0.0.pre6

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.
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.