bibtex-ruby 4.4.7 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of bibtex-ruby might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile +23 -24
- data/History.txt +4 -0
- data/Rakefile +23 -25
- data/bibtex-ruby.gemspec +1 -1
- data/examples/bib2html.rb +5 -6
- data/examples/bib2yaml.rb +2 -2
- data/features/step_definitions/bibtex_steps.rb +3 -6
- data/features/step_definitions/name_steps.rb +1 -2
- data/lib/bibtex.rb +11 -13
- data/lib/bibtex/bibliography.rb +45 -58
- data/lib/bibtex/compatibility.rb +3 -5
- data/lib/bibtex/elements.rb +49 -42
- data/lib/bibtex/entry.rb +80 -84
- data/lib/bibtex/entry/citeproc_converter.rb +47 -52
- data/lib/bibtex/entry/rdf_converter.rb +97 -63
- data/lib/bibtex/error.rb +10 -11
- data/lib/bibtex/extensions.rb +2 -5
- data/lib/bibtex/filters.rb +4 -9
- data/lib/bibtex/filters/latex.rb +0 -2
- data/lib/bibtex/filters/linebreaks.rb +0 -2
- data/lib/bibtex/lexer.rb +81 -81
- data/lib/bibtex/names.rb +24 -28
- data/lib/bibtex/replaceable.rb +15 -17
- data/lib/bibtex/utilities.rb +5 -10
- data/lib/bibtex/value.rb +28 -34
- data/lib/bibtex/version.rb +6 -6
- data/test/benchmark.rb +20 -22
- data/test/bibtex/entry/test_rdf_converter.rb +3 -5
- data/test/bibtex/test_bibliography.rb +22 -35
- data/test/bibtex/test_elements.rb +7 -15
- data/test/bibtex/test_entry.rb +78 -87
- data/test/bibtex/test_filters.rb +8 -7
- data/test/bibtex/test_lexer.rb +10 -13
- data/test/bibtex/test_name_parser.rb +6 -9
- data/test/bibtex/test_names.rb +50 -55
- data/test/bibtex/test_parser.rb +30 -34
- data/test/bibtex/test_string.rb +8 -9
- data/test/bibtex/test_utilities.rb +6 -9
- data/test/bibtex/test_value.rb +41 -43
- data/test/helper.rb +3 -6
- data/test/macruby.rb +12 -13
- data/test/profile.rb +16 -16
- data/test/test_bibtex.rb +10 -15
- data/test/test_export.rb +5 -13
- metadata +4 -4
data/lib/bibtex/error.rb
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
module BibTeX
|
2
|
+
class BibTeXError < StandardError
|
3
|
+
attr_reader :original
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
@original = original
|
9
|
-
end
|
10
|
-
end
|
5
|
+
def initialize(message = nil, original = $ERROR_INFO)
|
6
|
+
super(message)
|
7
|
+
@original = original
|
8
|
+
end
|
9
|
+
end
|
11
10
|
|
12
11
|
class ParseError < BibTeXError; end
|
13
12
|
class ArgumentError < BibTeXError; end
|
@@ -16,15 +15,15 @@ module BibTeX
|
|
16
15
|
# Represents a lexical or syntactical error.
|
17
16
|
#
|
18
17
|
class Error < Element
|
19
|
-
|
20
18
|
attr_reader :trace
|
21
19
|
|
22
|
-
def initialize(trace=[])
|
20
|
+
def initialize(trace = [])
|
23
21
|
@trace = trace
|
24
22
|
end
|
25
23
|
|
26
24
|
def trace=(trace)
|
27
|
-
raise(ArgumentError, "BibTeX::Error trace must be of type Array; was: #{trace.class.name}.") unless trace.
|
25
|
+
raise(ArgumentError, "BibTeX::Error trace must be of type Array; was: #{trace.class.name}.") unless trace.is_a?(Array)
|
26
|
+
|
28
27
|
@trace = trace
|
29
28
|
end
|
30
29
|
|
data/lib/bibtex/extensions.rb
CHANGED
data/lib/bibtex/filters.rb
CHANGED
@@ -23,11 +23,10 @@ module BibTeX
|
|
23
23
|
|
24
24
|
alias convert apply
|
25
25
|
alias << apply
|
26
|
-
|
27
26
|
end
|
28
27
|
|
29
28
|
module Filters
|
30
|
-
LOAD_PATH = [File.expand_path(
|
29
|
+
LOAD_PATH = [File.expand_path(__dir__), 'filters'].join('/').freeze
|
31
30
|
|
32
31
|
Dir.glob("#{LOAD_PATH}/*.rb").each do |filter|
|
33
32
|
require filter
|
@@ -38,18 +37,14 @@ module BibTeX
|
|
38
37
|
end
|
39
38
|
|
40
39
|
def self.resolve(filter)
|
41
|
-
|
42
|
-
when filter.respond_to?(:apply)
|
40
|
+
if filter.respond_to?(:apply)
|
43
41
|
filter
|
44
|
-
|
42
|
+
elsif filter.respond_to?(:to_s)
|
45
43
|
klass = Filter.subclasses.detect do |c|
|
46
44
|
c.name == filter.to_s || c.name.split(/::/)[-1] =~ /^#{filter}$/i
|
47
45
|
end
|
48
|
-
klass
|
49
|
-
else
|
50
|
-
nil
|
46
|
+
klass&.instance
|
51
47
|
end
|
52
48
|
end
|
53
49
|
end
|
54
50
|
end
|
55
|
-
|
data/lib/bibtex/filters/latex.rb
CHANGED
data/lib/bibtex/lexer.rb
CHANGED
@@ -19,7 +19,6 @@
|
|
19
19
|
require 'strscan'
|
20
20
|
|
21
21
|
module BibTeX
|
22
|
-
|
23
22
|
#
|
24
23
|
# The BibTeX::Lexer handles the lexical analysis of BibTeX bibliographies.
|
25
24
|
#
|
@@ -32,43 +31,43 @@ module BibTeX
|
|
32
31
|
def_delegator :@scanner, :string, :data
|
33
32
|
|
34
33
|
@defaults = {
|
35
|
-
:
|
36
|
-
:
|
37
|
-
:
|
38
|
-
:
|
34
|
+
include: [:errors],
|
35
|
+
strict: true,
|
36
|
+
allow_missing_keys: false,
|
37
|
+
strip: true
|
39
38
|
}
|
40
39
|
|
41
40
|
# Patterns Cache (#37: MacRuby does not cache regular expressions)
|
42
41
|
@patterns = {
|
43
|
-
:
|
44
|
-
:
|
45
|
-
:
|
46
|
-
:
|
47
|
-
:
|
48
|
-
:
|
49
|
-
:
|
50
|
-
:
|
51
|
-
:
|
52
|
-
:
|
53
|
-
:
|
54
|
-
:
|
55
|
-
:
|
56
|
-
:
|
57
|
-
:
|
58
|
-
:
|
59
|
-
:
|
60
|
-
:
|
61
|
-
:
|
62
|
-
:
|
63
|
-
:
|
42
|
+
space: /[\s]+/o,
|
43
|
+
lbrace: /\s*\{/o,
|
44
|
+
rbrace: /\s*\}\s*/o,
|
45
|
+
braces: /\{|\}/o,
|
46
|
+
eq: /\s*=\s*/o,
|
47
|
+
comma: /\s*,\s*/o,
|
48
|
+
number: /[[:digit:]]+/o,
|
49
|
+
name: %r{[[:alpha:][:digit:]/:_!$\?\.%+&\*-]+}io,
|
50
|
+
quote: /\s*"/o,
|
51
|
+
unquote: /[\{\}"]/o,
|
52
|
+
sharp: /\s*#\s*/o,
|
53
|
+
object: /@/o,
|
54
|
+
period: /./o,
|
55
|
+
strict_next: /@[\t ]*/o,
|
56
|
+
next: /(^|\n)[\t ]*@[\t ]*/o,
|
57
|
+
entry: /[a-z\d:_!\.$%&*-]+/io,
|
58
|
+
string: /string/io,
|
59
|
+
comment: /comment\b/io,
|
60
|
+
preamble: /preamble\b/io,
|
61
|
+
key: %r{\s*[[:alpha:][:digit:] /:_!$\?\.%+;&\*'"-]+,}io,
|
62
|
+
optional_key: %r{\s*[[:alpha:][:digit:] /:_!$\?\.%+;&\*'"-]*,}io
|
64
63
|
}
|
65
64
|
|
66
|
-
MODE = Hash.new(:meta).merge(
|
67
|
-
:
|
68
|
-
:
|
69
|
-
:
|
70
|
-
:
|
71
|
-
|
65
|
+
MODE = Hash.new(:meta).merge(
|
66
|
+
bibtex: :bibtex, entry: :bibtex,
|
67
|
+
string: :bibtex, preamble: :bibtex,
|
68
|
+
comment: :bibtex, meta: :meta,
|
69
|
+
literal: :literal, content: :content
|
70
|
+
).freeze
|
72
71
|
|
73
72
|
class << self
|
74
73
|
attr_reader :defaults, :patterns
|
@@ -94,7 +93,10 @@ module BibTeX
|
|
94
93
|
end
|
95
94
|
|
96
95
|
def reset
|
97
|
-
@stack
|
96
|
+
@stack = []
|
97
|
+
@brace_level = 0
|
98
|
+
@mode = :meta
|
99
|
+
@active_object = nil
|
98
100
|
|
99
101
|
# cache options for speed
|
100
102
|
@include_meta_content = @options[:include].include?(:meta_content)
|
@@ -109,17 +111,21 @@ module BibTeX
|
|
109
111
|
reset
|
110
112
|
end
|
111
113
|
|
112
|
-
def symbols
|
114
|
+
def symbols
|
115
|
+
@stack.map(&:first)
|
116
|
+
end
|
113
117
|
|
114
118
|
# Returns the next token from the parse stack.
|
115
|
-
def next_token
|
119
|
+
def next_token
|
120
|
+
@stack.shift
|
121
|
+
end
|
116
122
|
|
117
123
|
# Returns true if the lexer is currenty parsing a BibTeX object.
|
118
124
|
def bibtex_mode?
|
119
125
|
MODE[@mode] == :bibtex
|
120
126
|
end
|
121
127
|
|
122
|
-
[
|
128
|
+
%i[meta literal content].each do |m|
|
123
129
|
define_method("#{m}_mode?") { @mode == m }
|
124
130
|
end
|
125
131
|
|
@@ -171,9 +177,7 @@ module BibTeX
|
|
171
177
|
|
172
178
|
self.data = string || @scanner.string
|
173
179
|
|
174
|
-
until @scanner.eos?
|
175
|
-
send("parse_#{MODE[@mode]}")
|
176
|
-
end
|
180
|
+
send("parse_#{MODE[@mode]}") until @scanner.eos?
|
177
181
|
|
178
182
|
push([false, '$end'])
|
179
183
|
end
|
@@ -184,25 +188,25 @@ module BibTeX
|
|
184
188
|
case
|
185
189
|
when @scanner.scan(Lexer.patterns[:lbrace])
|
186
190
|
@brace_level += 1
|
187
|
-
push([:LBRACE,'{'])
|
191
|
+
push([:LBRACE, '{'])
|
188
192
|
@mode = :content if @brace_level > 1 || @brace_level == 1 && active?(:comment)
|
189
193
|
when @scanner.scan(Lexer.patterns[:rbrace])
|
190
194
|
@brace_level -= 1
|
191
|
-
push([:RBRACE,'}'])
|
195
|
+
push([:RBRACE, '}'])
|
192
196
|
return leave_object if @brace_level == 0
|
193
197
|
return error_unbalanced_braces if @brace_level < 0
|
194
198
|
when @scanner.scan(Lexer.patterns[:eq])
|
195
|
-
push([:EQ,'='])
|
199
|
+
push([:EQ, '='])
|
196
200
|
when @scanner.scan(Lexer.patterns[:comma])
|
197
|
-
push([:COMMA,','])
|
201
|
+
push([:COMMA, ','])
|
198
202
|
when @scanner.scan(Lexer.patterns[:number])
|
199
|
-
push([:NUMBER
|
203
|
+
push([:NUMBER, @scanner.matched])
|
200
204
|
when @scanner.scan(Lexer.patterns[:name])
|
201
|
-
push([:NAME
|
205
|
+
push([:NAME, @scanner.matched.rstrip])
|
202
206
|
when @scanner.scan(Lexer.patterns[:quote])
|
203
207
|
@mode = :literal
|
204
208
|
when @scanner.scan(Lexer.patterns[:sharp])
|
205
|
-
push([:SHARP,'#'])
|
209
|
+
push([:SHARP, '#'])
|
206
210
|
when @scanner.scan(Lexer.patterns[:object])
|
207
211
|
enter_object
|
208
212
|
when @scanner.scan(Lexer.patterns[:space])
|
@@ -215,10 +219,10 @@ module BibTeX
|
|
215
219
|
def parse_meta
|
216
220
|
match = @scanner.scan_until(Lexer.patterns[strict? ? :strict_next : :next])
|
217
221
|
if @scanner.matched
|
218
|
-
push([:META_CONTENT,match.chop])
|
222
|
+
push([:META_CONTENT, match.chop])
|
219
223
|
enter_object
|
220
224
|
else
|
221
|
-
push([:META_CONTENT
|
225
|
+
push([:META_CONTENT, @scanner.rest])
|
222
226
|
@scanner.terminate
|
223
227
|
end
|
224
228
|
end
|
@@ -228,26 +232,25 @@ module BibTeX
|
|
228
232
|
case @scanner.matched
|
229
233
|
when '{'
|
230
234
|
@brace_level += 1
|
231
|
-
push([:CONTENT,match])
|
235
|
+
push([:CONTENT, match])
|
232
236
|
when '}'
|
233
237
|
@brace_level -= 1
|
234
|
-
|
235
|
-
|
236
|
-
push([:
|
237
|
-
push([:RBRACE,'}'])
|
238
|
+
if @brace_level == 0
|
239
|
+
push([:CONTENT, match.chop])
|
240
|
+
push([:RBRACE, '}'])
|
238
241
|
leave_object
|
239
|
-
|
240
|
-
push([:CONTENT,match.chop])
|
241
|
-
push([:RBRACE,'}'])
|
242
|
+
elsif @brace_level == 1 && !active?(:comment)
|
243
|
+
push([:CONTENT, match.chop])
|
244
|
+
push([:RBRACE, '}'])
|
242
245
|
@mode = :bibtex
|
243
|
-
|
244
|
-
push([:CONTENT,match.chop])
|
246
|
+
elsif @brace_level < 0
|
247
|
+
push([:CONTENT, match.chop])
|
245
248
|
error_unbalanced_braces
|
246
249
|
else
|
247
|
-
push([:CONTENT,match])
|
250
|
+
push([:CONTENT, match])
|
248
251
|
end
|
249
252
|
else
|
250
|
-
push([:CONTENT
|
253
|
+
push([:CONTENT, @scanner.rest])
|
251
254
|
@scanner.terminate
|
252
255
|
error_unterminated_content
|
253
256
|
end
|
@@ -258,24 +261,24 @@ module BibTeX
|
|
258
261
|
case @scanner.matched
|
259
262
|
when '{'
|
260
263
|
@brace_level += 1
|
261
|
-
push([:STRING_LITERAL,match])
|
264
|
+
push([:STRING_LITERAL, match])
|
262
265
|
when '}'
|
263
266
|
@brace_level -= 1
|
264
267
|
if @brace_level < 1
|
265
|
-
push([:STRING_LITERAL,match.chop])
|
268
|
+
push([:STRING_LITERAL, match.chop])
|
266
269
|
error_unbalanced_braces
|
267
270
|
else
|
268
|
-
push([:STRING_LITERAL,match])
|
271
|
+
push([:STRING_LITERAL, match])
|
269
272
|
end
|
270
273
|
when '"'
|
271
274
|
if @brace_level == 1
|
272
|
-
push([:STRING_LITERAL,match.chop])
|
275
|
+
push([:STRING_LITERAL, match.chop])
|
273
276
|
@mode = :bibtex
|
274
277
|
else
|
275
|
-
push([:STRING_LITERAL,match])
|
278
|
+
push([:STRING_LITERAL, match])
|
276
279
|
end
|
277
280
|
else
|
278
|
-
push([:STRING_LITERAL
|
281
|
+
push([:STRING_LITERAL, @scanner.rest])
|
279
282
|
@scanner.terminate
|
280
283
|
error_unterminated_string
|
281
284
|
end
|
@@ -284,31 +287,28 @@ module BibTeX
|
|
284
287
|
# Called when the lexer encounters a new BibTeX object.
|
285
288
|
def enter_object
|
286
289
|
@brace_level = 0
|
287
|
-
push [:AT,'@']
|
290
|
+
push [:AT, '@']
|
288
291
|
|
289
|
-
|
290
|
-
when @scanner.scan(Lexer.patterns[:string])
|
292
|
+
if @scanner.scan(Lexer.patterns[:string])
|
291
293
|
@mode = @active_object = :string
|
292
294
|
push [:STRING, @scanner.matched]
|
293
|
-
|
295
|
+
elsif @scanner.scan(Lexer.patterns[:preamble])
|
294
296
|
@mode = @active_object = :preamble
|
295
297
|
push [:PREAMBLE, @scanner.matched]
|
296
|
-
|
298
|
+
elsif @scanner.scan(Lexer.patterns[:comment])
|
297
299
|
@mode = @active_object = :comment
|
298
300
|
push [:COMMENT, @scanner.matched]
|
299
|
-
|
301
|
+
elsif @scanner.scan(Lexer.patterns[:entry])
|
300
302
|
@mode = @active_object = :entry
|
301
303
|
push [:NAME, @scanner.matched]
|
302
304
|
|
303
305
|
# TODO: DRY - try to parse key
|
304
306
|
if @scanner.scan(Lexer.patterns[:lbrace])
|
305
307
|
@brace_level += 1
|
306
|
-
push([:LBRACE,'{'])
|
308
|
+
push([:LBRACE, '{'])
|
307
309
|
@mode = :content if @brace_level > 1 || @brace_level == 1 && active?(:comment)
|
308
310
|
|
309
|
-
if @scanner.scan(Lexer.patterns[allow_missing_keys? ? :optional_key : :key])
|
310
|
-
push [:KEY, @scanner.matched.chop.strip]
|
311
|
-
end
|
311
|
+
push [:KEY, @scanner.matched.chop.strip] if @scanner.scan(Lexer.patterns[allow_missing_keys? ? :optional_key : :key])
|
312
312
|
end
|
313
313
|
|
314
314
|
else
|
@@ -318,7 +318,9 @@ module BibTeX
|
|
318
318
|
|
319
319
|
# Called when parser leaves a BibTeX object.
|
320
320
|
def leave_object
|
321
|
-
@mode
|
321
|
+
@mode = :meta
|
322
|
+
@active_object = nil
|
323
|
+
@brace_level = 0
|
322
324
|
end
|
323
325
|
|
324
326
|
def error_unbalanced_braces
|
@@ -348,11 +350,9 @@ module BibTeX
|
|
348
350
|
|
349
351
|
def backtrace(error)
|
350
352
|
bt = []
|
351
|
-
bt.unshift(@stack.pop) until @stack.empty? || (!bt.empty? && [
|
353
|
+
bt.unshift(@stack.pop) until @stack.empty? || (!bt.empty? && %i[AT META_CONTENT].include?(bt[0][0]))
|
352
354
|
bt << error
|
353
|
-
push [:ERROR,bt]
|
355
|
+
push [:ERROR, bt]
|
354
356
|
end
|
355
|
-
|
356
357
|
end
|
357
|
-
|
358
358
|
end
|
data/lib/bibtex/names.rb
CHANGED
@@ -19,7 +19,6 @@
|
|
19
19
|
require 'forwardable'
|
20
20
|
|
21
21
|
module BibTeX
|
22
|
-
|
23
22
|
# A BibTeX Names value is an ordered list of name values.
|
24
23
|
class Names < Value
|
25
24
|
include Enumerable
|
@@ -28,7 +27,7 @@ module BibTeX
|
|
28
27
|
|
29
28
|
def self.parse(string)
|
30
29
|
new(NameParser.new.parse(string))
|
31
|
-
rescue => e
|
30
|
+
rescue StandardError => e
|
32
31
|
BibTeX.log.info(e.message)
|
33
32
|
nil
|
34
33
|
end
|
@@ -40,7 +39,7 @@ module BibTeX
|
|
40
39
|
end
|
41
40
|
end
|
42
41
|
|
43
|
-
def replace(*
|
42
|
+
def replace(*_arguments)
|
44
43
|
self
|
45
44
|
end
|
46
45
|
|
@@ -53,7 +52,8 @@ module BibTeX
|
|
53
52
|
end
|
54
53
|
|
55
54
|
def to_s(options = {})
|
56
|
-
return value unless options.
|
55
|
+
return value unless options.key?(:quotes)
|
56
|
+
|
57
57
|
q = [options[:quotes]].flatten
|
58
58
|
[q[0], value, q[-1]].compact.join
|
59
59
|
end
|
@@ -82,14 +82,13 @@ module BibTeX
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def strip_braces
|
85
|
-
gsub!(/\{|\}/,'')
|
85
|
+
gsub!(/\{|\}/, '')
|
86
86
|
end
|
87
87
|
|
88
88
|
def add(name)
|
89
|
-
|
90
|
-
when name.is_a?(Name)
|
89
|
+
if name.is_a?(Name)
|
91
90
|
@tokens << name
|
92
|
-
|
91
|
+
elsif name.respond_to?(:to_s)
|
93
92
|
@tokens += Names.parse(name.to_s)
|
94
93
|
else
|
95
94
|
raise ArgumentError, "failed to add #{name.inspect}: not a name."
|
@@ -100,7 +99,7 @@ module BibTeX
|
|
100
99
|
alias << add
|
101
100
|
alias push add
|
102
101
|
|
103
|
-
[
|
102
|
+
%i[convert! rename_if rename_unless extend_initials].each do |method_id|
|
104
103
|
define_method(method_id) do |*arguments|
|
105
104
|
tokens.each { |t| t.send(method_id, *arguments) }
|
106
105
|
self
|
@@ -108,9 +107,8 @@ module BibTeX
|
|
108
107
|
end
|
109
108
|
|
110
109
|
def <=>(other)
|
111
|
-
other.respond_to?(:to_a) ? to_a <=> other.to_a
|
110
|
+
other.respond_to?(:to_a) ? to_a <=> other.to_a : super
|
112
111
|
end
|
113
|
-
|
114
112
|
end
|
115
113
|
|
116
114
|
# A Name comprises individual name parts (first, last, prefix and suffix),
|
@@ -120,14 +118,14 @@ module BibTeX
|
|
120
118
|
include Comparable
|
121
119
|
|
122
120
|
BibTeXML = {
|
123
|
-
:
|
124
|
-
:
|
125
|
-
:
|
126
|
-
:
|
121
|
+
first: :first,
|
122
|
+
last: :last,
|
123
|
+
prefix: :prelast,
|
124
|
+
suffix: :lineage
|
127
125
|
}.freeze
|
128
126
|
|
129
127
|
def_delegators :to_s, :=~, :===,
|
130
|
-
|
128
|
+
*String.instance_methods(false).reject { |m| m =~ /^\W|to_s|replace|each|first|last|!$/ }
|
131
129
|
|
132
130
|
class << self
|
133
131
|
def parse(string)
|
@@ -146,7 +144,7 @@ module BibTeX
|
|
146
144
|
end
|
147
145
|
|
148
146
|
def initialize_copy(other)
|
149
|
-
other.each_pair do |k,v|
|
147
|
+
other.each_pair do |k, v|
|
150
148
|
self[k] = v.dup unless v.nil?
|
151
149
|
end
|
152
150
|
end
|
@@ -185,7 +183,7 @@ module BibTeX
|
|
185
183
|
# Sets the name's first name to the passed-in name if the last name equals
|
186
184
|
# for_last and the current first name has the same initials as with_first.
|
187
185
|
def extend_initials(with_first, for_last)
|
188
|
-
rename_if :
|
186
|
+
rename_if first: with_first do |name|
|
189
187
|
if name.last == for_last
|
190
188
|
mine = name.initials.split(/\.[^[:alpha:]]*/)
|
191
189
|
other = initials(with_first).split(/\.[^[:alpha:]]*/)
|
@@ -256,20 +254,20 @@ module BibTeX
|
|
256
254
|
xml = REXML::Element.new('bibtex:person')
|
257
255
|
|
258
256
|
each_pair do |part, text|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
257
|
+
next if text.nil?
|
258
|
+
|
259
|
+
element = REXML::Element.new("bibtex:#{BibTeXML[part]}")
|
260
|
+
element.text = text
|
261
|
+
xml.add_element(element)
|
264
262
|
end
|
265
263
|
|
266
264
|
xml
|
267
265
|
end
|
268
266
|
|
269
|
-
[
|
267
|
+
%i[strip! upcase! downcase! sub! gsub! chop! chomp! rstrip!].each do |method_id|
|
270
268
|
define_method(method_id) do |*arguments, &block|
|
271
269
|
each do |part|
|
272
|
-
part
|
270
|
+
part&.send(method_id, *arguments, &block)
|
273
271
|
end
|
274
272
|
self
|
275
273
|
end
|
@@ -281,9 +279,8 @@ module BibTeX
|
|
281
279
|
|
282
280
|
def convert!(*filters)
|
283
281
|
filters.flatten.each do |filter|
|
284
|
-
|
285
282
|
f = Filters.resolve(filter) ||
|
286
|
-
|
283
|
+
raise(ArgumentError, "Failed to load filter #{filter.inspect}")
|
287
284
|
|
288
285
|
each_pair do |k, v|
|
289
286
|
self[k] = f.apply(v) unless v.nil?
|
@@ -310,6 +307,5 @@ module BibTeX
|
|
310
307
|
alias jr= suffix=
|
311
308
|
alias von prefix
|
312
309
|
alias von= prefix=
|
313
|
-
|
314
310
|
end
|
315
311
|
end
|