citeproc 1.0.0.pre12 → 1.0.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 +7 -0
- data/.simplecov +4 -0
- data/AGPL +1 -1
- data/BSDL +2 -2
- data/Gemfile +39 -19
- data/README.md +123 -14
- data/Rakefile +22 -8
- data/cucumber.yml +1 -1
- data/features/step_definitions/processor.rb +59 -0
- data/features/support/env.rb +45 -2
- data/lib/citeproc.rb +8 -8
- data/lib/citeproc/abbreviate.rb +5 -4
- data/lib/citeproc/assets.rb +109 -109
- data/lib/citeproc/attributes.rb +11 -11
- data/lib/citeproc/bibliography.rb +107 -71
- data/lib/citeproc/citation_data.rb +175 -150
- data/lib/citeproc/compatibility.rb +5 -108
- data/lib/citeproc/date.rb +23 -12
- data/lib/citeproc/engine.rb +9 -4
- data/lib/citeproc/errors.rb +6 -6
- data/lib/citeproc/extensions.rb +66 -66
- data/lib/citeproc/item.rb +60 -2
- data/lib/citeproc/names.rb +103 -24
- data/lib/citeproc/number.rb +27 -8
- data/lib/citeproc/processor.rb +31 -41
- data/lib/citeproc/selector.rb +132 -126
- data/lib/citeproc/utilities.rb +6 -6
- data/lib/citeproc/variable.rb +5 -4
- data/lib/citeproc/version.rb +1 -1
- data/spec/citeproc/assets_spec.rb +17 -15
- data/spec/citeproc/bibliography_spec.rb +17 -17
- data/spec/citeproc/citation_data_spec.rb +90 -90
- data/spec/citeproc/engine_spec.rb +3 -4
- data/spec/citeproc/item_spec.rb +76 -68
- data/spec/citeproc/names_spec.rb +187 -148
- data/spec/citeproc/processor_spec.rb +119 -115
- data/spec/citeproc/selector_spec.rb +87 -78
- data/spec/citeproc/variable_spec.rb +30 -30
- data/spec/fixtures/locales/locales-en-US.xml +304 -0
- data/spec/spec_helper.rb +32 -1
- data/tasks/testsuite.rb +209 -0
- metadata +19 -87
- data/.gitignore +0 -6
- data/.travis.yml +0 -21
- data/citeproc.gemspec +0 -40
data/lib/citeproc/abbreviate.rb
CHANGED
@@ -10,9 +10,9 @@ module CiteProc
|
|
10
10
|
def abbreviations=(abbreviations)
|
11
11
|
@abbreviations = case abbreviations
|
12
12
|
when ::String
|
13
|
-
|
13
|
+
::JSON.parse(abbreviations, :symbolize_names => true)
|
14
14
|
when ::Hash
|
15
|
-
abbreviations.deep_copy
|
15
|
+
abbreviations.deep_copy.symbolize_keys
|
16
16
|
else
|
17
17
|
raise ArgumentError, "failed to set abbreviations from #{abbreviations.inspect}"
|
18
18
|
end
|
@@ -20,11 +20,12 @@ module CiteProc
|
|
20
20
|
|
21
21
|
# @overload abbreviate(namespace = :default, context, word)
|
22
22
|
def abbreviate(*arguments)
|
23
|
-
raise ArgumentError, "wrong number of arguments (#{arguments.length} for 2..3)" unless
|
23
|
+
raise ArgumentError, "wrong number of arguments (#{arguments.length} for 2..3)" unless
|
24
|
+
(2..3).include?(arguments.length)
|
25
|
+
|
24
26
|
arguments.unshift(namespace || :default) if arguments.length < 3
|
25
27
|
@abbreviations.deep_fetch(*arguments)
|
26
28
|
end
|
27
|
-
|
28
29
|
alias abbrev abbreviate
|
29
30
|
|
30
31
|
end
|
data/lib/citeproc/assets.rb
CHANGED
@@ -1,113 +1,113 @@
|
|
1
1
|
module CiteProc
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
3
|
+
module Asset
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :asset, :location
|
10
|
+
|
11
|
+
def open?
|
12
|
+
!asset.nil?
|
13
|
+
end
|
14
|
+
|
15
|
+
def open(input)
|
16
|
+
case
|
17
|
+
when input.respond_to?(:read)
|
18
|
+
@location = nil
|
19
|
+
@asset = input.read
|
20
|
+
when input.to_s =~ /^\s*</
|
21
|
+
@location = nil
|
22
|
+
@asset = input.to_s.dup
|
23
|
+
else
|
24
|
+
case
|
25
|
+
when File.exists?(input)
|
26
|
+
@location = input
|
27
|
+
when File.exists?(self.class.extend_name(input))
|
28
|
+
@location = self.class.extend_name(input)
|
29
|
+
when File.exists?(self.class.extend_path(input))
|
30
|
+
@location = self.class.extend_path(input)
|
31
|
+
else
|
32
|
+
@location = input
|
33
|
+
end
|
34
|
+
|
35
|
+
Kernel.open(@location, 'r:UTF-8') do |io|
|
36
|
+
@asset = io.read
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
self
|
41
|
+
rescue => e
|
42
|
+
raise ArgumentError, "failed to open asset #@location (#{input.inspect}): #{e.message}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def name
|
46
|
+
File.basename(location, self.class.extension).sub(Regexp.new("^#{self.class.prefix}"), '')
|
47
|
+
end
|
48
|
+
|
49
|
+
alias to_s asset
|
50
|
+
|
51
|
+
def inspect
|
52
|
+
"#<CiteProc::#{self.class.name} #{name}>"
|
53
|
+
end
|
54
|
+
|
55
|
+
module ClassMethods
|
56
|
+
|
57
|
+
attr_accessor :root, :extension, :prefix
|
58
|
+
|
59
|
+
def open(path_or_name)
|
60
|
+
new.open(path_or_name)
|
61
|
+
end
|
62
|
+
|
63
|
+
def extend_path(input)
|
64
|
+
File.join(root.to_s, extend_name(input))
|
65
|
+
end
|
66
|
+
|
67
|
+
def extend_name(input)
|
68
|
+
if File.extname(input) != extension
|
69
|
+
name = [input, extension].compact.join
|
70
|
+
else
|
71
|
+
name = input.to_s.dup
|
72
|
+
end
|
73
|
+
|
74
|
+
unless name.start_with?(prefix.to_s)
|
75
|
+
name = [prefix, name].join
|
76
|
+
end
|
77
|
+
|
78
|
+
name
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
class Style
|
86
|
+
|
87
|
+
include Asset
|
88
|
+
|
89
|
+
@root = '/usr/local/share/citation-style-language/styles'.freeze
|
90
|
+
@extension = '.csl'.freeze
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
class Locale
|
95
|
+
|
96
|
+
include Asset
|
97
|
+
|
98
|
+
@root = '/usr/local/share/citation-style-language/locales'.freeze
|
99
|
+
@extension = '.xml'.freeze
|
100
|
+
@prefix = 'locales-'.freeze
|
101
|
+
|
102
|
+
|
103
|
+
def language
|
104
|
+
name.split('-')[0]
|
105
|
+
end
|
106
|
+
|
107
|
+
def region
|
108
|
+
name.split('-')[1]
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
112
|
|
113
113
|
end
|
data/lib/citeproc/attributes.rb
CHANGED
@@ -23,16 +23,16 @@ module CiteProc
|
|
23
23
|
def write_attribute(key, value)
|
24
24
|
attributes[filter_key(key)] = filter_value(value, key)
|
25
25
|
end
|
26
|
-
|
26
|
+
alias []= write_attribute
|
27
27
|
|
28
|
-
|
29
|
-
|
28
|
+
def attribute?(key)
|
29
|
+
value = read_attribute key
|
30
30
|
|
31
|
-
|
32
|
-
|
31
|
+
return false if value.nil?
|
32
|
+
return false if value.respond_to?(:empty?) && value.empty?
|
33
33
|
|
34
|
-
|
35
|
-
|
34
|
+
value.to_s !~ /^(false|no|never)$/i
|
35
|
+
end
|
36
36
|
|
37
37
|
def filter_key(key)
|
38
38
|
key.to_sym
|
@@ -49,7 +49,7 @@ module CiteProc
|
|
49
49
|
|
50
50
|
case
|
51
51
|
when other.is_a?(String) && /^\s*\{/ =~ other
|
52
|
-
other =
|
52
|
+
other = ::JSON.parse(other, :symbolize_names => true)
|
53
53
|
when other.respond_to?(:each_pair)
|
54
54
|
# do nothing
|
55
55
|
when other.respond_to?(:to_hash)
|
@@ -83,7 +83,7 @@ module CiteProc
|
|
83
83
|
|
84
84
|
# @return [String] a JSON string representation of the attributes
|
85
85
|
def to_json
|
86
|
-
|
86
|
+
::JSON.dump(to_citeproc)
|
87
87
|
end
|
88
88
|
|
89
89
|
# Don't expose internals to public API
|
@@ -173,7 +173,7 @@ module CiteProc
|
|
173
173
|
predicate_id = [method_id, '?'].join
|
174
174
|
if predicate && !instance_methods.include?(predicate_id)
|
175
175
|
define_method(predicate_id) do
|
176
|
-
|
176
|
+
attribute?(field)
|
177
177
|
end
|
178
178
|
|
179
179
|
has_predicate = ['has_', predicate_id].join
|
@@ -184,4 +184,4 @@ module CiteProc
|
|
184
184
|
end
|
185
185
|
|
186
186
|
end
|
187
|
-
end
|
187
|
+
end
|
@@ -13,30 +13,30 @@ module CiteProc
|
|
13
13
|
|
14
14
|
@defaults = {
|
15
15
|
:offset => 0,
|
16
|
-
:
|
17
|
-
:
|
18
|
-
:indent =>
|
19
|
-
:align => false
|
16
|
+
:'entry-spacing' => 1,
|
17
|
+
:'line-spacing' => 1,
|
18
|
+
:'hanging-indent' => false,
|
19
|
+
:'second-field-align' => false
|
20
20
|
}.freeze
|
21
|
-
|
22
|
-
|
21
|
+
|
22
|
+
|
23
23
|
# citeproc-js and csl attributes are often inconsistent or difficult
|
24
24
|
# to use as symbols/method names, so we're using different names at the
|
25
25
|
# cost of making conversion to and from the json format more difficult
|
26
|
-
|
26
|
+
|
27
27
|
@cp2rb = {
|
28
28
|
'maxoffset' => :offset,
|
29
|
-
'entryspacing' => :
|
30
|
-
'linespacing' => :
|
31
|
-
'hangingindent' => :indent,
|
32
|
-
'second-field-align' => :align
|
29
|
+
'entryspacing' => :'entry-spacing',
|
30
|
+
'linespacing' => :'line-spacing',
|
31
|
+
'hangingindent' => :'hanging-indent',
|
32
|
+
'second-field-align' => :'second-field-align'
|
33
33
|
}
|
34
|
-
|
34
|
+
|
35
35
|
@rb2cp = @cp2rb.invert.freeze
|
36
36
|
@cp2rb.freeze
|
37
|
-
|
37
|
+
|
38
38
|
class << self
|
39
|
-
|
39
|
+
|
40
40
|
# @!attribute [r] defaults
|
41
41
|
# @example Default Formatting Options
|
42
42
|
# {
|
@@ -54,19 +54,17 @@ module CiteProc
|
|
54
54
|
# # string should use this value to calculate and apply a suitable
|
55
55
|
# # indentation length.
|
56
56
|
#
|
57
|
-
# :
|
57
|
+
# :'entry-spacing' => 1,
|
58
58
|
# # An integer representing the spacing between entries in the
|
59
59
|
# # bibliography.
|
60
60
|
#
|
61
|
-
# :
|
61
|
+
# :'line-spacing' => 1,
|
62
62
|
# # An integer representing the spacing between the lines within
|
63
63
|
# # each bibliography entry.
|
64
64
|
#
|
65
|
-
# :indent =>
|
66
|
-
# # The number of em-spaces to apply in hanging indents within the
|
67
|
-
# # bibliography.
|
65
|
+
# :'hanging-indent' => false,
|
68
66
|
#
|
69
|
-
# :align => false
|
67
|
+
# :'second-field-align' => false
|
70
68
|
# # When the second-field-align CSL option is set, this returns
|
71
69
|
# # either "flush" or "margin". The calling application should
|
72
70
|
# # align text in the bibliography output as described by the CSL
|
@@ -77,105 +75,143 @@ module CiteProc
|
|
77
75
|
attr_reader :defaults
|
78
76
|
|
79
77
|
attr_reader :cp2rb, :rb2cp
|
80
|
-
|
78
|
+
|
81
79
|
# Create a new Bibliography from the passed-in string or array, or nil
|
82
80
|
# if the input cannot be parsed.
|
83
|
-
def create(input)
|
84
|
-
create!(input)
|
81
|
+
def create(input, &block)
|
82
|
+
create!(input, &block)
|
85
83
|
rescue
|
86
84
|
nil
|
87
85
|
end
|
88
|
-
|
86
|
+
|
89
87
|
# Create a new Bibliography from the passed-in string or array. Raises
|
90
88
|
# ParseError if the input cannot be parsed.
|
91
89
|
def create!(input)
|
92
90
|
case
|
93
91
|
when input.is_a?(String)
|
94
|
-
create!(
|
95
|
-
|
92
|
+
create!(::JSON.parse(input))
|
93
|
+
|
94
|
+
when input.is_a?(Hash)
|
95
|
+
create!([input])
|
96
|
+
|
96
97
|
when input.is_a?(Array) && input.length == 2
|
97
98
|
options, references = input
|
98
99
|
|
99
100
|
new do |b|
|
100
|
-
b.concat(references)
|
101
|
+
b.references.concat(references)
|
102
|
+
b.ids.concat(options.fetch('entry_ids', []))
|
101
103
|
b.errors.concat(options.fetch('bibliography_errors', []))
|
102
|
-
|
103
|
-
b.
|
104
|
-
|
104
|
+
|
105
|
+
b.header, b.footer = options['bibstart'], options['bibend']
|
106
|
+
|
105
107
|
(options.keys & cp2rb.keys).each do |k|
|
106
108
|
b.options[cp2rb[k]] = options[k]
|
107
109
|
end
|
110
|
+
|
111
|
+
yield b if block_given?
|
108
112
|
end
|
109
|
-
|
113
|
+
|
110
114
|
else
|
111
115
|
raise ParseError, "failed to create Bibliography from #{input.inspect}"
|
112
116
|
end
|
113
117
|
end
|
114
|
-
|
118
|
+
|
115
119
|
end
|
116
|
-
|
120
|
+
|
117
121
|
include Comparable
|
118
122
|
include Enumerable
|
119
|
-
|
123
|
+
|
120
124
|
extend Forwardable
|
121
125
|
|
122
126
|
# @!attribute [r] refrences
|
123
127
|
# @return [Array<String>] the list of references
|
124
128
|
attr_reader :references
|
125
|
-
|
129
|
+
|
130
|
+
attr_reader :ids
|
131
|
+
|
126
132
|
# @!attribute [r] options
|
127
133
|
# @see .defaults
|
128
134
|
# @return [Hash] the current formatting options
|
129
135
|
attr_reader :options
|
130
|
-
|
136
|
+
|
131
137
|
# @!attribute [r] errors
|
132
|
-
# @todo not implemented yet
|
133
138
|
# @return [Array<String>] a list of errors
|
134
139
|
attr_reader :errors
|
135
140
|
|
136
|
-
# @!attribute
|
141
|
+
# @!attribute header
|
137
142
|
# @return [String] content included before the reference list
|
138
|
-
attr_accessor :
|
143
|
+
attr_accessor :header
|
139
144
|
|
140
|
-
# @!attribute
|
145
|
+
# @!attribute footer
|
141
146
|
# @return [String] content included after the reference list
|
142
|
-
attr_accessor :
|
147
|
+
attr_accessor :footer
|
143
148
|
|
149
|
+
# @!attribute prefix
|
150
|
+
# @return [String] content included before each reference
|
151
|
+
attr_accessor :prefix
|
152
|
+
|
153
|
+
# @!attribute suffix
|
154
|
+
# @return [String] content included after each reference
|
155
|
+
attr_accessor :suffix
|
144
156
|
|
145
157
|
# Bibliographies quack sorta like an Array
|
146
|
-
def_delegators :@references, :length, :empty
|
158
|
+
def_delegators :@references, :length, :empty?
|
159
|
+
|
160
|
+
attr_accessor :connector
|
147
161
|
|
148
|
-
# Some delegators should return self
|
149
|
-
[:push, :<<, :unshift, :concat].each do |m|
|
150
|
-
define_method(m) do |*arguments, &block|
|
151
|
-
references.send(m, *arguments, &block)
|
152
|
-
self
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
|
157
162
|
def initialize(options = {})
|
158
163
|
@options = Bibliography.defaults.merge(options)
|
159
|
-
@errors, @references = [], []
|
160
|
-
|
164
|
+
@errors, @references, @ids, @connector = [], [], [], "\n"
|
165
|
+
|
161
166
|
yield self if block_given?
|
162
167
|
end
|
163
|
-
|
168
|
+
|
164
169
|
def initialize_copy(other)
|
165
|
-
@options = other.options.dup
|
166
|
-
@errors, @references = other.errors.dup, other.references.dup
|
170
|
+
@options, @connector = other.options.dup, other.connector.dup
|
171
|
+
@errors, @references, @ids = other.errors.dup, other.references.dup, other.ids.dup
|
172
|
+
end
|
173
|
+
|
174
|
+
def push(id, reference)
|
175
|
+
ids << id
|
176
|
+
references << reference
|
177
|
+
self
|
167
178
|
end
|
179
|
+
alias << push
|
168
180
|
|
169
181
|
def has_errors?
|
170
182
|
!errors.empty?
|
171
183
|
end
|
172
|
-
|
184
|
+
|
173
185
|
alias errors? has_errors?
|
174
|
-
|
175
|
-
def
|
176
|
-
[
|
186
|
+
|
187
|
+
def entry_spacing
|
188
|
+
options[:'entry-spacing'].to_f
|
189
|
+
end
|
190
|
+
|
191
|
+
def line_spacing
|
192
|
+
options[:'line-spacing'].to_f
|
177
193
|
end
|
178
|
-
|
194
|
+
|
195
|
+
def hanging_indent?
|
196
|
+
options[:'hanging_indent']
|
197
|
+
end
|
198
|
+
|
199
|
+
def join()
|
200
|
+
[
|
201
|
+
header,
|
202
|
+
|
203
|
+
references.map { |r|
|
204
|
+
[prefix, r, suffix].compact.join('')
|
205
|
+
}.join(connector),
|
206
|
+
|
207
|
+
footer
|
208
|
+
].compact.join(connector)
|
209
|
+
end
|
210
|
+
|
211
|
+
def to_s
|
212
|
+
join
|
213
|
+
end
|
214
|
+
|
179
215
|
def each
|
180
216
|
if block_given?
|
181
217
|
references.each(&Proc.new)
|
@@ -184,7 +220,7 @@ module CiteProc
|
|
184
220
|
to_enum
|
185
221
|
end
|
186
222
|
end
|
187
|
-
|
223
|
+
|
188
224
|
def <=>(other)
|
189
225
|
return nil unless other.respond_to?(:references)
|
190
226
|
references <=> other.references
|
@@ -195,29 +231,29 @@ module CiteProc
|
|
195
231
|
[Bibliography.rb2cp[k] || k.to_s, v]
|
196
232
|
}.flatten]
|
197
233
|
end
|
198
|
-
|
234
|
+
|
199
235
|
def to_citeproc
|
200
236
|
[
|
201
|
-
citeproc_options.merge({
|
237
|
+
citeproc_options.merge({
|
202
238
|
'bibstart' => prefix,
|
203
239
|
'bibend' => suffix,
|
204
240
|
'bibliography_errors' => errors
|
205
241
|
}),
|
206
|
-
|
242
|
+
|
207
243
|
references
|
208
|
-
|
244
|
+
|
209
245
|
]
|
210
246
|
end
|
211
|
-
|
247
|
+
|
212
248
|
def to_json
|
213
|
-
|
249
|
+
::JSON.dump(to_citeproc)
|
214
250
|
end
|
215
|
-
|
251
|
+
|
216
252
|
# @return [String] a human-readable representation of the bibliography
|
217
253
|
def inspect
|
218
254
|
"#<CiteProc::Bibliography @references=[#{references.length}], @errors=[#{errors.length}]>"
|
219
255
|
end
|
220
|
-
|
256
|
+
|
221
257
|
end
|
222
|
-
|
258
|
+
|
223
259
|
end
|