citeproc 1.0.0.pre12 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.simplecov +4 -0
  3. data/AGPL +1 -1
  4. data/BSDL +2 -2
  5. data/Gemfile +39 -19
  6. data/README.md +123 -14
  7. data/Rakefile +22 -8
  8. data/cucumber.yml +1 -1
  9. data/features/step_definitions/processor.rb +59 -0
  10. data/features/support/env.rb +45 -2
  11. data/lib/citeproc.rb +8 -8
  12. data/lib/citeproc/abbreviate.rb +5 -4
  13. data/lib/citeproc/assets.rb +109 -109
  14. data/lib/citeproc/attributes.rb +11 -11
  15. data/lib/citeproc/bibliography.rb +107 -71
  16. data/lib/citeproc/citation_data.rb +175 -150
  17. data/lib/citeproc/compatibility.rb +5 -108
  18. data/lib/citeproc/date.rb +23 -12
  19. data/lib/citeproc/engine.rb +9 -4
  20. data/lib/citeproc/errors.rb +6 -6
  21. data/lib/citeproc/extensions.rb +66 -66
  22. data/lib/citeproc/item.rb +60 -2
  23. data/lib/citeproc/names.rb +103 -24
  24. data/lib/citeproc/number.rb +27 -8
  25. data/lib/citeproc/processor.rb +31 -41
  26. data/lib/citeproc/selector.rb +132 -126
  27. data/lib/citeproc/utilities.rb +6 -6
  28. data/lib/citeproc/variable.rb +5 -4
  29. data/lib/citeproc/version.rb +1 -1
  30. data/spec/citeproc/assets_spec.rb +17 -15
  31. data/spec/citeproc/bibliography_spec.rb +17 -17
  32. data/spec/citeproc/citation_data_spec.rb +90 -90
  33. data/spec/citeproc/engine_spec.rb +3 -4
  34. data/spec/citeproc/item_spec.rb +76 -68
  35. data/spec/citeproc/names_spec.rb +187 -148
  36. data/spec/citeproc/processor_spec.rb +119 -115
  37. data/spec/citeproc/selector_spec.rb +87 -78
  38. data/spec/citeproc/variable_spec.rb +30 -30
  39. data/spec/fixtures/locales/locales-en-US.xml +304 -0
  40. data/spec/spec_helper.rb +32 -1
  41. data/tasks/testsuite.rb +209 -0
  42. metadata +19 -87
  43. data/.gitignore +0 -6
  44. data/.travis.yml +0 -21
  45. data/citeproc.gemspec +0 -40
@@ -44,12 +44,8 @@ module CiteProc
44
44
 
45
45
  # Class instance variables
46
46
 
47
- @romanesque = CiteProc.oniguruma {
48
- '^[\p{Latin}\p{Greek}\p{Cyrillic}\p{Hebrew}\p{Armenian}\p{Georgian}\p{Common}]*$'
49
- } || CiteProc.ruby_18 {
50
- # @todo improve fallback range
51
- /^[a-zA-Zäöüéè\s[:punct:]]*$/u
52
- }
47
+ @romanesque =
48
+ /^[\p{Latin}\p{Greek}\p{Cyrillic}\p{Hebrew}\p{Armenian}\p{Georgian}\p{Common}]*$/
53
49
 
54
50
  # Default formatting options
55
51
  @defaults = {
@@ -57,6 +53,8 @@ module CiteProc
57
53
  :'name-as-sort-order' => false,
58
54
  :'demote-non-dropping-particle' => :never,
59
55
  :'sort-separator' => ', ',
56
+ :initialize => true,
57
+ :'initialize-with-hyphen' => true,
60
58
  :'initialize-with' => nil
61
59
  }.freeze
62
60
 
@@ -75,6 +73,8 @@ module CiteProc
75
73
  # @return the name's formatting options
76
74
  attr_reader :options
77
75
 
76
+ attr_reader :sort_prefix
77
+
78
78
  attr_predicates :'comma-suffix', :'static-ordering', :multi, *@parts
79
79
 
80
80
  # Aliases
@@ -92,8 +92,9 @@ module CiteProc
92
92
  end
93
93
 
94
94
  # Names quack sorta like a String
95
- def_delegators :to_s, :=~, :===,
96
- *String.instance_methods(false).reject { |m| m =~ /^\W|!$|to_s|replace|first|last/ }
95
+ def_delegators :to_s, :=~, :===, *String.instance_methods(false).reject { |m|
96
+ m.to_s =~ /^[\W_]|[!=_]$|^(to_s|inspect|replace|first|last|dup|clone)$/
97
+ }
97
98
 
98
99
  # Delegate bang! methods to each field's value
99
100
  String.instance_methods(false).each do |m|
@@ -126,12 +127,24 @@ module CiteProc
126
127
  end
127
128
 
128
129
 
130
+ # Resets the object's options to the default settings.
131
+ # @return [self]
132
+ def reset!
133
+ @options = Name.defaults.dup
134
+ end
135
+
136
+ # Returns a copy of the name object with all options
137
+ # reset to their default settings.
138
+ # @return [Name] a copy of the name with default options
139
+ def reset
140
+ dup.reset!
141
+ end
142
+
129
143
  # @return [Boolean] whether or not the Name looks like it belongs to a person
130
144
  def personal?
131
145
  !empty? && !literal?
132
146
  end
133
147
 
134
-
135
148
  # A name is `romanesque' if it contains only romanesque characters. This
136
149
  # should be the case for the majority of names written in latin- or
137
150
  # greek-based script. It will be false, for example, for names written
@@ -173,15 +186,15 @@ module CiteProc
173
186
 
174
187
  # Sets the name to use sort-order. The reverse of {#display_order!}.
175
188
  # @return [self]
176
- def sort_order!
177
- options[:'name-as-sort-order'] = true
189
+ def sort_order!(toggle = true)
190
+ options[:'name-as-sort-order'] = !!toggle
178
191
  self
179
192
  end
180
193
 
181
194
  # Sets the name to use display-order. The reverse of {#sort_order!}.
182
195
  # @return [self]
183
- def display_order!
184
- options[:'name-as-sort-order'] = false
196
+ def display_order!(toggle = true)
197
+ options[:'name-as-sort-order'] = !toggle
185
198
  self
186
199
  end
187
200
 
@@ -200,7 +213,7 @@ module CiteProc
200
213
  # Use short form for printing the name
201
214
  # @return [self]
202
215
  def short_form!
203
- options[:form] = :short
216
+ options[:form] = 'short'
204
217
  self
205
218
  end
206
219
 
@@ -212,7 +225,7 @@ module CiteProc
212
225
  # Use long form for printing the name
213
226
  # @return [self]
214
227
  def long_form!
215
- options[:form] = :long
228
+ options[:form] = 'long'
216
229
  self
217
230
  end
218
231
 
@@ -221,6 +234,33 @@ module CiteProc
221
234
  !!options[:'initialize-with'] && personal? && romanesque?
222
235
  end
223
236
 
237
+ def initialize_with
238
+ options[:'initialize-with'].to_s
239
+ end
240
+
241
+ def initialize_existing_only?
242
+ options[:initialize].to_s == 'false'
243
+ end
244
+
245
+ def initialize_without_hyphen?
246
+ !options[:'initialize-with-hyphen']
247
+ end
248
+
249
+ def initialize_without_hyphen!
250
+ options[:'initialize-with-hyphen'] = false
251
+ end
252
+
253
+ def initials
254
+ case
255
+ when !initials?
256
+ given
257
+ when initialize_existing_only?
258
+ existing_initials_of given
259
+ else
260
+ initials_of given
261
+ end
262
+ end
263
+
224
264
  def demote_non_dropping_particle?
225
265
  always_demote_non_dropping_particle? ||
226
266
  !!(sort_order? && options[:'demote-non-dropping-particle'] =~ /^sort(-only)?$/i)
@@ -266,31 +306,36 @@ module CiteProc
266
306
  sort_order_downcase <=> other.sort_order_downcase
267
307
  end
268
308
 
269
- # @return [String] the name formatted according to the current options
270
309
  def to_s
310
+ [given, family].compact_join(' ')
311
+ end
312
+
313
+ # @return [String] the name formatted according to the current options
314
+ def format
271
315
  case
272
316
  when literal?
273
317
  literal.to_s
274
318
  when static_order?
275
- [family, given].compact.join(' ')
319
+ [family, initials].compact.join(' ')
276
320
  when !short_form?
277
321
  case
278
322
  when !sort_order?
279
- [[given, dropping_particle, particle, family].compact_join(' '),
323
+ [[initials, dropping_particle, particle, family].compact_join(' '),
280
324
  suffix].compact_join(comma_suffix? ? comma : ' ')
281
325
 
282
326
  when !demote_particle?
283
- [[particle, family].compact_join(' '), [given,
327
+ [[particle, family].compact_join(' '), [initials,
284
328
  dropping_particle].compact_join(' '), suffix].compact_join(comma)
285
329
 
286
330
  else
287
- [family, [given, dropping_particle, particle].compact_join(' '),
331
+ [family, [initials, dropping_particle, particle].compact_join(' '),
288
332
  suffix].compact_join(comma)
289
333
  end
290
334
  else
291
335
  [particle, family].compact_join(' ')
292
336
  end
293
337
  end
338
+ alias print format
294
339
 
295
340
  # @return [Array<String>] an ordered array of formatted name parts to be used for sorting
296
341
  def sort_order
@@ -326,8 +371,42 @@ module CiteProc
326
371
 
327
372
  private
328
373
 
329
- attr_reader :sort_prefix
374
+ def filter_key(key)
375
+ key = key.to_s.tr('_', '-')
376
+ key = 'non-dropping-particle' if key == 'particle'
377
+ super key
378
+ end
379
+
380
+ def initials_of(string)
381
+ string = string.dup
382
+
383
+ string.gsub!(/([[:upper:]])[^[:upper:]\s-]*\s*/, "\\1#{initialize_with}")
384
+
385
+ initialize_hyphen!(string)
330
386
 
387
+ string.strip!
388
+ string
389
+ end
390
+
391
+ def initialize_hyphen!(string)
392
+ if initialize_without_hyphen?
393
+ string.tr!('-', '')
394
+ else
395
+ string.gsub!(/\s*-/, '-')
396
+ end
397
+ end
398
+
399
+ def existing_initials_of(string)
400
+ string = string.dup
401
+
402
+ string.gsub!(/([[:upper:]])([[:upper:]])/, '\1 \2')
403
+ string.gsub!(/\b([[:upper:]])\b[^[:alpha:]-]*/, "\\1#{initialize_with}")
404
+
405
+ initialize_hyphen!(string)
406
+
407
+ string.strip!
408
+ string
409
+ end
331
410
  end
332
411
 
333
412
 
@@ -483,7 +562,7 @@ module CiteProc
483
562
  @value << Name.new(value)
484
563
  when value.respond_to?(:to_s)
485
564
  begin
486
- @value.concat Namae.parse!(value.to_s)
565
+ @value.concat Namae.parse!(value.to_s).map { |n| Name.new n }
487
566
  rescue
488
567
  raise TypeError, $!.message
489
568
  end
@@ -635,7 +714,7 @@ module CiteProc
635
714
  case
636
715
  when truncate?
637
716
  [names[0...max_names].join(delimiter), options[:'et-al']].join(truncated_delimiter)
638
- when length < 2
717
+ when length < 3
639
718
  names.join(last_delimiter)
640
719
  else
641
720
  [names[0...-1].join(delimiter), names[-1]].join(last_delimiter)
@@ -644,7 +723,7 @@ module CiteProc
644
723
 
645
724
  # @return [String] the names in a BibTeX-compatible format
646
725
  def to_bibtex
647
- map { |n| n.dup.sort_order! }.join(' and ')
726
+ map { |n| n.dup.sort_order!.format }.join(' and ')
648
727
  end
649
728
 
650
729
  # @return [Array<Hash>] the list of names converted to hash objects
@@ -1,8 +1,10 @@
1
+ # -*- encoding: utf-8 -*-
2
+
1
3
  module CiteProc
2
4
  # A CiteProc Variable used for numeric values.
3
5
  class Number < Variable
4
6
 
5
- MAX_ROMAN = 5000
7
+ MAX_ROMAN = 5000
6
8
 
7
9
  FACTORS = [
8
10
  ['m', 1000], ['cm', 900], ['d', 500], ['cd', 400],
@@ -11,12 +13,12 @@ module CiteProc
11
13
  ['i', 1]
12
14
  ].freeze
13
15
 
14
- class << self
15
- def pluralize?(string)
16
- /\S\s*[,&-]\s*\S|\df/ === string
17
- end
18
-
19
- # @param number [#to_i] the number to convert
16
+ class << self
17
+ def pluralize?(string)
18
+ /\S[\s,&–-]\S|\df/ === string
19
+ end
20
+
21
+ # @param number [#to_i] the number to convert
20
22
  # @return [String] roman equivalent of the passed-in number
21
23
  def romanize(number)
22
24
  number, roman = number.to_i, ''
@@ -30,7 +32,24 @@ module CiteProc
30
32
 
31
33
  roman
32
34
  end
33
- end
35
+ end
36
+
37
+ def <=>(other)
38
+ case
39
+ when other.nil?
40
+ 1
41
+ when numeric?
42
+ if other.respond_to?(:to_i)
43
+ to_i <=> other.to_i
44
+ else
45
+ nil
46
+ end
47
+ when other.is_a?(Variable) || other.is_a?(String)
48
+ to_s <=> other.to_s
49
+ else
50
+ nil
51
+ end
52
+ end
34
53
  end
35
54
 
36
55
  end
@@ -1,33 +1,32 @@
1
-
2
1
  module CiteProc
3
-
2
+
4
3
  class Processor
5
4
  extend Forwardable
6
5
 
7
6
  include Abbreviate
8
7
  include Converters
9
-
8
+
10
9
  @defaults = {
11
10
  :locale => 'en-US',
12
11
  :style => 'chicago-author-date',
13
- :engine => 'citeproc-js',
14
- :format => 'html'
12
+ :engine => 'citeproc-ruby',
13
+ :format => 'html',
14
+ :sort_case_sensitivity => false,
15
+ :allow_locale_overrides => false
15
16
  }.freeze
16
17
 
17
18
  class << self
18
19
  attr_reader :defaults
19
20
  end
20
21
 
21
- attr_reader :options, :items
22
+ attr_reader :options, :items, :data
22
23
  attr_writer :engine
23
24
 
24
- def_delegators :@locale, :language, :region
25
-
26
25
  def_delegators :@items, :key?, :value?, :has_key?, :has_value?,
27
26
  :include?, :member?, :length, :empty?
28
-
27
+
29
28
  def initialize(options = {})
30
- @options, @items = Processor.defaults.merge(options), {}
29
+ @options, @items, @data = Processor.defaults.merge(options), {}, []
31
30
  yield self if block_given?
32
31
  end
33
32
 
@@ -35,46 +34,34 @@ module CiteProc
35
34
  @engine ||= Engine.autodetect(options).new(self)
36
35
  end
37
36
 
38
- def style
39
- @style || load_style
40
- end
41
-
42
- def locale
43
- @locale || load_locale
44
- end
45
-
46
- def load_style(new_style = nil)
47
- options[:style] = new_style unless new_style.nil?
48
- @style = Style.open(options[:style])
49
- end
50
-
51
- def load_locale(new_locale = nil)
52
- options[:locale] = new_locale unless new_locale.nil?
53
- @locale = Locale.open(options[:locale])
54
- end
55
-
56
37
  def [](id)
57
- items[id.to_sym]
38
+ items[id.to_s]
58
39
  end
59
40
 
60
41
  def []=(id, item)
61
- items[id.to_sym] = Item(item)
42
+ item = Item(item)
43
+ item.id = id.to_s
44
+
45
+ register(items)
62
46
  end
63
-
47
+
64
48
  def register(item)
65
49
  item = Item(item)
66
- items[item.to_sym] = item
50
+
51
+ data << item
52
+ items[item.id.to_s] = item
53
+
67
54
  rescue => e
68
55
  raise "failed to register item #{item.inspect}: #{e.message}"
69
56
  end
70
-
57
+
71
58
  def <<(item)
72
59
  register(item)
73
60
  self
74
61
  end
75
-
62
+
76
63
  def update(*arguments)
77
- arguments.flatten(1).each do |argument|
64
+ arguments.each do |argument|
78
65
  case argument
79
66
  when Item
80
67
  register(argument)
@@ -82,8 +69,8 @@ module CiteProc
82
69
  argument.each { |item| register(item) }
83
70
  when Hash
84
71
  argument.each do |id, item|
85
- id, item = id.to_sym, Item(item)
86
-
72
+ id, item = id.to_s, Item(item)
73
+
87
74
  if items.key?(id) && block_given?
88
75
  items[id] = yield items[id], item
89
76
  else
@@ -94,12 +81,12 @@ module CiteProc
94
81
  raise "failed to register items #{argument.inspect}"
95
82
  end
96
83
  end
97
-
84
+
98
85
  self
99
86
  ensure
100
87
  # notify engine
101
88
  end
102
-
89
+ alias import update
103
90
 
104
91
 
105
92
  def process(*arguments)
@@ -114,9 +101,12 @@ module CiteProc
114
101
  engine.bibliography(Selector.new(*arguments, &block))
115
102
  end
116
103
 
104
+ def render(mode, *arguments)
105
+ engine.render(mode, CitationData.new(arguments.flatten(1)))
106
+ end
107
+
117
108
  def inspect
118
- "#<CiteProc::Processor style=#{style.name.inspect} locale=#{locale.name.inspect} items=[#{items.length}]>"
109
+ "#<CiteProc::Processor style=#{options[:style].inspect} locale=#{options[:locale].inspect} items=[#{items.length}]>"
119
110
  end
120
-
121
111
  end
122
112
  end
@@ -1,128 +1,134 @@
1
1
 
2
2
  module CiteProc
3
-
4
- class Selector
5
-
6
- @types = [:all, :any, :none].freeze
7
- @matcher = Hash[*@types.zip([:all?, :any?, :none?]).flatten].freeze
8
-
9
- @rb2cp = Hash[*(@types + [:skip]).zip(%w{
10
- select include exclude quash
11
- }).flatten]
12
-
13
- @cp2rb = @rb2cp.invert.freeze
14
- @rb2cp.freeze
15
-
16
- class << self
17
- attr_reader :types, :matcher, :rb2cp, :cp2rb
18
- end
19
-
20
- attr_reader :type, :conditions, :skip_conditions, :custom_matcher
21
-
22
- def initialize(attributes = nil)
23
- @conditions, @skip_conditions = {}, {}
24
-
25
- if block_given?
26
- @type = :ruby
27
-
28
- else
29
- unless attributes.nil? || attributes.empty?
30
- attributes.symbolize_keys.each_pair do |key, conditions|
31
- case key
32
- when :all, :any, :none
33
- @type = key
34
- @conditions.merge!(conditions)
35
-
36
- when :select, :include, :exclude
37
- @type = Selector.cp2rb[key.to_s]
38
- @conditions.merge!(conditions)
39
-
40
- when :skip, :quash
41
- @skip_conditions.merge!(conditions)
42
-
43
- else
44
- raise TypeError, "failed to create selector from #{key.inspect}"
45
- end
46
- end
47
- end
48
- end
49
-
50
- end
51
-
52
- def initialize_copy(other)
53
- @type = other.type
54
- @conditions = other.conditions.deep_copy
55
- @skip_conditions = other.skip_conditions.deep_copy
56
- @custom_matcher = other
57
- end
58
-
59
- def type=(type)
60
- raise TypeError, "failed to set selector type to #{type.inspect}" unless
61
- type.respond_to(:to_sym) && Selector.types.include?(type.to_sym)
62
-
63
- @type = type.to_sym
64
- end
65
-
66
- def empty?
67
- type.nil? && skip_conditions.empty?
68
- end
69
-
70
- def custom_matcher?
71
- defined?(@custom_matcher)
72
- end
73
-
74
- alias ruby? custom_matcher?
75
-
76
- def matches?(item)
77
- if custom_matcher?
78
- custom_matcher.call(item)
79
- else
80
- conditions.each_pair.send(matcher) do |field, value|
81
- item[field].to_s == value.to_s
82
- end
83
- end
84
- end
85
-
86
- def skip?(item)
87
- if custom_matcher?
88
- false # skips are ignored for custom matchers
89
- else
90
- skip_conditions.each_pair.all? do |field, value|
91
- item[field].to_s == value.to_s
92
- end
93
- end
94
- end
95
-
96
- def to_proc
97
- Proc.new { |item| matches?(item) && !skip?(item) }
98
- end
99
-
100
- def to_citeproc
101
- return nil if empty? || custom_matcher?
102
-
103
- cp = {}
104
- cp[Selector.rb2cp[type]] = conditions.map do |field, value|
105
- { 'field' => field.to_s, 'value' => value.to_s }
106
- end unless conditions.empty?
107
-
108
- cp['quash'] = skip_conditions.map do |field, value|
109
- { 'field' => field.to_s, 'value' => value.to_s }
110
- end unless skip_conditions.empty?
111
-
112
- cp
113
- end
114
-
115
- def to_json
116
- MultiJson.encode(to_citeproc)
117
- end
118
-
119
- private
120
-
121
- def matcher
122
- Selector.matcher[type] || :all?
123
- end
124
-
125
-
126
- end
127
-
128
- end
3
+
4
+ class Selector
5
+
6
+ @types = [:all, :any, :none].freeze
7
+ @matcher = Hash[*@types.zip([:all?, :any?, :none?]).flatten].freeze
8
+
9
+ @rb2cp = Hash[*(@types + [:skip]).zip(%w{
10
+ select include exclude quash
11
+ }).flatten]
12
+
13
+ @cp2rb = @rb2cp.invert.freeze
14
+ @rb2cp.freeze
15
+
16
+ class << self
17
+ attr_reader :types, :matcher, :rb2cp, :cp2rb
18
+ end
19
+
20
+ attr_reader :type, :conditions, :skip_conditions, :custom_matcher
21
+
22
+ def initialize(attributes = nil)
23
+ @conditions, @skip_conditions = {}, {}
24
+
25
+ if block_given?
26
+ @type = :ruby
27
+
28
+ else
29
+ unless attributes.nil? || attributes.empty?
30
+ attributes.symbolize_keys.each_pair do |key, conditions|
31
+ conditions = convert_conditions(conditions) if conditions.is_a?(Array)
32
+
33
+ case key
34
+ when :all, :any, :none
35
+ @type = key
36
+ @conditions.merge!(conditions)
37
+
38
+ when :select, :include, :exclude
39
+ @type = Selector.cp2rb[key.to_s]
40
+ @conditions.merge!(conditions)
41
+
42
+ when :skip, :quash
43
+ @skip_conditions.merge!(conditions)
44
+
45
+ else
46
+ raise TypeError, "failed to create selector from #{key.inspect}"
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ def initialize_copy(other)
54
+ @type = other.type
55
+ @conditions = other.conditions.deep_copy
56
+ @skip_conditions = other.skip_conditions.deep_copy
57
+ @custom_matcher = other
58
+ end
59
+
60
+ def type=(type)
61
+ raise TypeError, "failed to set selector type to #{type.inspect}" unless
62
+ type.respond_to(:to_sym) && Selector.types.include?(type.to_sym)
63
+
64
+ @type = type.to_sym
65
+ end
66
+
67
+ def empty?
68
+ type.nil? && skip_conditions.empty?
69
+ end
70
+
71
+ def custom_matcher?
72
+ defined?(@custom_matcher)
73
+ end
74
+
75
+ alias ruby? custom_matcher?
76
+
77
+ def matches?(item)
78
+ if custom_matcher?
79
+ custom_matcher.call(item)
80
+ else
81
+ conditions.each_pair.send(matcher) do |field, value|
82
+ item[field].to_s == value.to_s
83
+ end
84
+ end
85
+ end
86
+
87
+ def skip?(item)
88
+ if custom_matcher? || skip_conditions.empty?
89
+ false # skips are ignored for custom matchers
90
+ else
91
+ skip_conditions.each_pair.all? do |field, value|
92
+ item[field].to_s == value.to_s
93
+ end
94
+ end
95
+ end
96
+
97
+ def to_proc
98
+ Proc.new { |item| matches?(item) && !skip?(item) }
99
+ end
100
+
101
+ def to_citeproc
102
+ return nil if empty? || custom_matcher?
103
+
104
+ cp = {}
105
+ cp[Selector.rb2cp[type]] = conditions.map do |field, value|
106
+ { 'field' => field.to_s, 'value' => value.to_s }
107
+ end unless conditions.empty?
108
+
109
+ cp['quash'] = skip_conditions.map do |field, value|
110
+ { 'field' => field.to_s, 'value' => value.to_s }
111
+ end unless skip_conditions.empty?
112
+
113
+ cp
114
+ end
115
+
116
+ def to_json
117
+ ::JSON.dump(to_citeproc)
118
+ end
119
+
120
+ private
121
+
122
+ def matcher
123
+ Selector.matcher[type] || :all?
124
+ end
125
+
126
+ # Converts a CiteProc-JS style conditions list into
127
+ # a conditions Hash.
128
+ def convert_conditions(conditions)
129
+ Hash[conditions.map { |c| [c['field'], c['value']] }]
130
+ end
131
+
132
+ end
133
+
134
+ end