bibtex-ruby 4.4.7 → 5.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.
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
|