bibtex-ruby 1.3.7 → 1.3.8

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.

data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bibtex-ruby (1.3.7)
4
+ bibtex-ruby (1.3.8)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
data/History.txt CHANGED
@@ -1,3 +1,7 @@
1
+ === 1.3.8 / 2011-07-05
2
+
3
+ * Added a converter-plugin framework
4
+
1
5
  === 1.3.7 / 2011-06-30
2
6
 
3
7
  * Added option to toggle dropping/non-dropping behaviour of 'von' parts
data/Manifest CHANGED
@@ -39,6 +39,9 @@ lib/bibtex/elements.rb
39
39
  lib/bibtex/entry.rb
40
40
  lib/bibtex/error.rb
41
41
  lib/bibtex/extensions.rb
42
+ lib/bibtex/filters
43
+ lib/bibtex/filters/latex.rb
44
+ lib/bibtex/filters.rb
42
45
  lib/bibtex/lexer.rb
43
46
  lib/bibtex/name_parser.output
44
47
  lib/bibtex/name_parser.rb
@@ -57,6 +60,7 @@ test/bibtex
57
60
  test/bibtex/test_bibliography.rb
58
61
  test/bibtex/test_elements.rb
59
62
  test/bibtex/test_entry.rb
63
+ test/bibtex/test_filters.rb
60
64
  test/bibtex/test_lexer.rb
61
65
  test/bibtex/test_name_parser.rb
62
66
  test/bibtex/test_names.rb
data/lib/bibtex.rb CHANGED
@@ -54,6 +54,7 @@ end
54
54
 
55
55
  require 'bibtex/extensions'
56
56
  require 'bibtex/value'
57
+ require 'bibtex/filters'
57
58
  require 'bibtex/name_parser'
58
59
  require 'bibtex/names'
59
60
  require 'bibtex/replaceable'
@@ -47,10 +47,11 @@ module BibTeX
47
47
  #
48
48
  # -:parse_names: set to false to disable automatic name parsing
49
49
  # -:parse_months: set to false to disable automatic month conversion
50
+ # -:filter: convert all entries using the sepcified filter (not set by default)
50
51
  #
51
52
  def open(path, options = {})
52
53
  b = parse(Kernel.open(path).read, options)
53
- return b unless !b.nil? and block_given?
54
+ return b unless block_given?
54
55
 
55
56
  begin
56
57
  yield b
@@ -61,7 +62,7 @@ module BibTeX
61
62
 
62
63
  # Parses the given string and returns a corresponding Bibliography instance.
63
64
  def parse(bibtex, options = {})
64
- Parser.new(options).parse(bibtex)
65
+ Parser.new(options).parse(bibtex) || Bibliography.new(options)
65
66
  end
66
67
 
67
68
  #
@@ -119,15 +120,22 @@ module BibTeX
119
120
  end
120
121
 
121
122
  def parse_names
122
- @entries.values.each { |e| e.parse_names }
123
+ @entries.each_value { |e| e.parse_names }
123
124
  self
124
125
  end
125
126
 
126
127
  def parse_months
127
- @entries.values.each { |e| e.parse_month }
128
+ @entries.each_value { |e| e.parse_month }
128
129
  self
129
130
  end
130
131
 
132
+ # Converts all enties using the given filter. If an optional block is given
133
+ # the block is used as a condition (the block will be called with each
134
+ # entry). @see Entry#convert!
135
+ def convert (filter)
136
+ @entries.each_value { |e| e.convert!(filter) if !block_given? || yield(e) }
137
+ end
138
+
131
139
  #
132
140
  # Deletes an object, or a list of objects from the bibliography.
133
141
  # If a list of objects is to be deleted, you can either supply the list
data/lib/bibtex/entry.rb CHANGED
@@ -117,6 +117,15 @@ module BibTeX
117
117
  yield self if block_given?
118
118
  end
119
119
 
120
+ def initialize_copy (other)
121
+ @fields = {}
122
+
123
+ self.type = other.type
124
+ self.key = other.key
125
+
126
+ add(other.fields)
127
+ end
128
+
120
129
  # Sets the key of the entry
121
130
  def key=(key)
122
131
  raise(ArgumentError, "keys must be convertible to Symbol; was: #{type.class.name}.") unless type.respond_to?(:to_sym)
@@ -133,8 +142,8 @@ module BibTeX
133
142
  @key ||= default_key
134
143
  end
135
144
 
136
- alias :id :key
137
- alias :id= :key=
145
+ alias id key
146
+ alias id= key=
138
147
 
139
148
  # Sets the type of the entry.
140
149
  def type=(type)
@@ -150,14 +159,15 @@ module BibTeX
150
159
  @fields.has_key?(field)
151
160
  end
152
161
 
153
- def method_missing(name, *args)
162
+ def method_missing(name, *args, &block)
154
163
  return self[name] if @fields.has_key?(name)
155
164
  return self.send(:add, name.to_s.chop.to_sym, args[0]) if name.to_s.match(/=$/)
165
+ return $2 ? convert!($1, &block) : convert($1, &block) if name =~ /^(?:convert|from)_([a-z]+)(!)?$/
156
166
  super
157
167
  end
158
168
 
159
169
  def respond_to?(method)
160
- @fields.has_key?(method.to_sym) || method.to_s.match(/=$/) || super
170
+ @fields.has_key?(method.to_sym) || method.to_s.match(/=$/) || method =~ /^(?:convert|from)_([a-z]+)(!)?$/ || super
161
171
  end
162
172
 
163
173
  # Returns a copy of the Entry with all the field names renamed.
@@ -207,7 +217,7 @@ module BibTeX
207
217
  self
208
218
  end
209
219
 
210
- alias :<< :add
220
+ alias << add
211
221
 
212
222
  # Removes the field with a given name from the entry.
213
223
  # Returns the value of the deleted field; nil if the field was not set.
@@ -229,6 +239,7 @@ module BibTeX
229
239
  bibliography.entries[key] = self
230
240
  parse_names if bibliography.options[:parse_names]
231
241
  parse_months if bibliography.options[:parse_months]
242
+ convert(bibliography.options[:filter]) if bibliography.options[:filter]
232
243
  self
233
244
  end
234
245
 
@@ -259,7 +270,7 @@ module BibTeX
259
270
  self
260
271
  end
261
272
 
262
- alias :parse_months :parse_month
273
+ alias parse_months parse_month
263
274
 
264
275
  # Parses all name values of the entry. Tries to replace and join the
265
276
  # value prior to parsing.
@@ -309,7 +320,7 @@ module BibTeX
309
320
  { 'date-parts' => [[@fields[:year],m].compact.map(&:to_i)] }
310
321
  end
311
322
 
312
- alias :citeproc_date :issued
323
+ alias citeproc_date issued
313
324
 
314
325
  def to_xml(options = {})
315
326
  require 'rexml/document'
@@ -324,6 +335,22 @@ module BibTeX
324
335
  xml
325
336
  end
326
337
 
338
+ # Returns a duplicate entry with all values converted using the filter.
339
+ # If an optional block is given, only those values will be converted where
340
+ # the block returns true (the block will be called with each key-value pair).
341
+ #
342
+ # @see convert!
343
+ #
344
+ def convert (filter)
345
+ block_given? ? dup.convert!(filter, &Proc.new) : dup.convert!(filter)
346
+ end
347
+
348
+ # In-place variant of @see convert
349
+ def convert! (filter)
350
+ @fields.each_pair { |k,v| !block_given? || yield(k,v) ? v.convert!(filter) : v }
351
+ self
352
+ end
353
+
327
354
  def <=>(other)
328
355
  type != other.type ? type <=> other.type : key != other.key ? key <=> other.key : to_s <=> other.to_s
329
356
  end
@@ -0,0 +1,49 @@
1
+ require 'singleton'
2
+
3
+ module BibTeX
4
+ class Filter
5
+ include Singleton
6
+
7
+ class << self
8
+ # Hook called by Ruby if Filter is subclassed
9
+ def inherited (base)
10
+ base.class_eval { include Singleton }
11
+ subclasses << base
12
+ end
13
+
14
+ # Returns a list of all current Filters
15
+ def subclasses
16
+ @subclasses ||= []
17
+ end
18
+ end
19
+
20
+ def apply (value); value; end
21
+
22
+ alias convert apply
23
+ alias << apply
24
+
25
+ end
26
+
27
+ module Filters
28
+ LOAD_PATH = [File.expand_path('..', __FILE__), 'filters'].join('/').freeze
29
+
30
+ Dir.glob("#{LOAD_PATH}/*.rb").each do |filter|
31
+ require filter
32
+ end
33
+
34
+ def self.resolve (filter)
35
+ case
36
+ when filter.respond_to?(:apply)
37
+ filter
38
+ when filter.respond_to?(:to_s)
39
+ klass = Filter.subclasses.detect do |c|
40
+ c.name == filter.to_s || c.name.split(/::/)[-1] =~ /^#{filter}$/i
41
+ end
42
+ klass && klass.instance
43
+ else
44
+ nil
45
+ end
46
+ end
47
+ end
48
+ end
49
+
@@ -0,0 +1,13 @@
1
+ # require 'latex/decode'
2
+ #
3
+ # module BibTeX
4
+ # module Filters
5
+ #
6
+ # class LaTeX < Filter
7
+ # def apply (value)
8
+ # LaTeX.decode(value)
9
+ # end
10
+ # end
11
+ #
12
+ # end
13
+ # end
data/lib/bibtex/value.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # -*- coding: utf-8 -*-
2
+
1
3
  #--
2
4
  # BibTeX-Ruby
3
5
  # Copyright (C) 2010-2011 Sylvester Keil <sylvester.keil.or.at>
@@ -48,7 +50,7 @@ module BibTeX
48
50
  include Comparable
49
51
 
50
52
  attr_reader :tokens
51
- alias :to_a :tokens
53
+ alias to_a tokens
52
54
 
53
55
  def_delegators :to_s, :empty?, :=~, :match, :intern, :to_sym, :to_i, :to_f, :end_with?, :start_with?, :include?, :upcase, :downcase, :reverse, :chop, :chomp, :rstrip, :gsub, :sub, :size, :strip, :succ, :to_c, :to_r, :to_str, :split, :each_byte, :each_char, :each_line
54
56
  def_delegators :@tokens, :[], :length
@@ -82,8 +84,8 @@ module BibTeX
82
84
  self
83
85
  end
84
86
 
85
- alias :<< :add
86
- alias :push :add
87
+ alias << add
88
+ alias push add
87
89
 
88
90
  [:strip!, :upcase!, :downcase!, :sub!, :gsub!, :chop!, :chomp!, :rstrip!].each do |method_id|
89
91
  define_method(method_id) do |*arguments, &block|
@@ -128,6 +130,9 @@ module BibTeX
128
130
  # If the Value is atomic and the option :quotes is given, the string
129
131
  # will be quoted using the quote symbols specified.
130
132
  #
133
+ # If the option :filter is given, the Value will be converted using
134
+ # the filter(s) specified.
135
+ #
131
136
  # call-seq:
132
137
  # Value.new('foo').to_s #=> "foo"
133
138
  # Value.new(:foo).to_s #=> "foo"
@@ -136,8 +141,10 @@ module BibTeX
136
141
  # Value.new('foo').to_s(:quotes => ['{','}']) #=> "{foo}"
137
142
  # Value.new(:foo, 'bar').to_s #=> "foo # \"bar\""
138
143
  # Value.new('foo', 'bar').to_s #=> "\"foo\" # \"bar\""
144
+ # Value.new('\"u').to_s(:filter => :latex) #=> "ü"
139
145
  #
140
146
  def to_s(options = {})
147
+ return convert(options.delete(:filter)).to_s(options) if options.has_key?(:filter)
141
148
  return value.to_s unless options.has_key?(:quotes) && atomic?
142
149
  *q = options[:quotes]
143
150
  [q[0], value, q[-1]].compact.join
@@ -172,13 +179,13 @@ module BibTeX
172
179
  Names.parse(to_s)
173
180
  end
174
181
 
175
- alias :to_names :to_name
182
+ alias to_names to_name
176
183
 
177
184
  # Returns true if the Value's content looks like a date.
178
185
  def date?
179
186
  end
180
187
 
181
- alias :is_date? :date?
188
+ alias is_date? date?
182
189
 
183
190
  # Returns the string as a citeproc date. TODO use edtf format instead.
184
191
  def to_date
@@ -190,9 +197,9 @@ module BibTeX
190
197
  to_s =~ /^\s*[+-]?\d+[\/\.]?\d*\s*$/
191
198
  end
192
199
 
193
- alias :is_numeric? :numeric?
200
+ alias is_numeric? numeric?
194
201
 
195
- def to_citeproc(options = {})
202
+ def to_citeproc (options = {})
196
203
  to_s(options)
197
204
  end
198
205
 
@@ -201,14 +208,45 @@ module BibTeX
201
208
  @tokens.detect { |v| v.is_a?(Symbol) }
202
209
  end
203
210
 
204
- alias :has_symbol? :symbol?
211
+ alias has_symbol? symbol?
205
212
 
206
213
  # Returns all symbols contained in the Value.
207
214
  def symbols
208
215
  @tokens.select { |v| v.is_a?(Symbol) }
209
216
  end
210
217
 
211
- def <=>(other)
218
+ def each_token; @tokens.each; end
219
+
220
+ # Returns a new Value with all string values converted according to the given filter.
221
+ def convert (filter)
222
+ dup.convert!(filter)
223
+ end
224
+
225
+ # Converts all string values according to the given filter.
226
+ def convert! (filter)
227
+ f = Filters.resolve(filter)
228
+
229
+ unless f
230
+ message = "Failed to load filter #{f.inspect}"
231
+ Log.error message
232
+ raise ArgumentError.new(message)
233
+ end
234
+
235
+ @tokens.map! { |t| f.apply(t) }
236
+ self
237
+ end
238
+
239
+ def method_missing (name, *args)
240
+ return $2 ? convert!($1) : convert($1) if name =~ /^(?:convert|from)_([a-z]+)(!)?$/
241
+ super
242
+ end
243
+
244
+ def respond_to? (method)
245
+ method =~ /^(?:convert|from)_([a-z]+)(!)?$/ || super
246
+ end
247
+
248
+
249
+ def <=> (other)
212
250
  to_s <=> other.to_s
213
251
  end
214
252
 
@@ -18,6 +18,6 @@
18
18
 
19
19
  module BibTeX
20
20
  module Version
21
- STRING = '1.3.7'.freeze
21
+ STRING = '1.3.8'.freeze
22
22
  end
23
23
  end
@@ -135,6 +135,25 @@ module BibTeX
135
135
  assert_equal @bib, BibTeX.open(tmp.path)
136
136
  end
137
137
 
138
+ context 'given a filter' do
139
+ setup do
140
+ @filter = Object
141
+ def @filter.apply (value); value.is_a?(::String) ? value.upcase : value; end
142
+ end
143
+
144
+ should 'support arbitrary conversions' do
145
+ @bib.convert(@filter)
146
+ assert_equal 'RUBY, RAILS', @bib[:rails].keywords
147
+ end
148
+
149
+ should 'support conditional arbitrary conversions' do
150
+ @bib.convert(@filter) { |e| e.key != :rails }
151
+ assert_equal 'ruby, rails', @bib[:rails].keywords
152
+ assert_equal 'RUBY', @bib[:flanagan2008].keywords
153
+ end
154
+
155
+ end
156
+
138
157
  end
139
158
 
140
159
 
@@ -40,7 +40,6 @@ module BibTeX
40
40
  end
41
41
 
42
42
  end
43
-
44
43
 
45
44
  context 'given an entry' do
46
45
  setup do
@@ -57,11 +56,25 @@ module BibTeX
57
56
  end
58
57
  end
59
58
 
60
- should 'support renaming of field attributes' do
61
- @entry.rename(:title => :foo)
59
+ should 'support renaming! of field attributes' do
60
+ @entry.rename!(:title => :foo)
62
61
  refute @entry.has_field?(:title)
63
62
  assert_equal 'Moby Dick', @entry[:foo]
64
63
  end
64
+
65
+ should 'support renaming of field attributes' do
66
+ e = @entry.rename(:title => :foo)
67
+
68
+ assert @entry.has_field?(:title)
69
+ refute @entry.has_field?(:foo)
70
+
71
+ assert e.has_field?(:foo)
72
+ refute e.has_field?(:title)
73
+
74
+ assert_equal 'Moby Dick', @entry[:title]
75
+ assert_equal 'Moby Dick', e[:foo]
76
+ end
77
+
65
78
 
66
79
  should 'support citeproc export' do
67
80
  e = @entry.to_citeproc
@@ -72,6 +85,39 @@ module BibTeX
72
85
  assert_equal 'Herman', e['author'][0]['given']
73
86
  assert_equal 'Melville', e['author'][0]['family']
74
87
  end
88
+
89
+ context 'given a filter' do
90
+ setup do
91
+ @filter = Object.new
92
+ def @filter.apply (value); value.is_a?(::String) ? value.upcase : value; end
93
+ end
94
+
95
+ should 'support arbitrary conversion' do
96
+ e = @entry.convert(@filter)
97
+ assert_equal 'MOBY DICK', e.title
98
+ assert_equal 'Moby Dick', @entry.title
99
+ end
100
+
101
+ should 'support arbitrary in-place conversion' do
102
+ @entry.convert!(@filter)
103
+ assert_equal 'MOBY DICK', @entry.title
104
+ end
105
+
106
+ should 'support conditional arbitrary in-place conversion' do
107
+ @entry.convert!(@filter) { |k,v| k.to_s =~ /publisher/i }
108
+ assert_equal 'Moby Dick', @entry.title
109
+ assert_equal 'PENGUIN', @entry.publisher
110
+ end
111
+
112
+ should 'support conditional arbitrary conversion' do
113
+ e = @entry.convert(@filter) { |k,v| k.to_s =~ /publisher/i }
114
+ assert_equal 'Moby Dick', e.title
115
+ assert_equal 'PENGUIN', e.publisher
116
+ assert_equal 'Penguin', @entry.publisher
117
+ end
118
+
119
+ end
120
+
75
121
  end
76
122
 
77
123
  context 'citeproc export' do
@@ -0,0 +1,37 @@
1
+ require 'helper.rb'
2
+
3
+ module BibTeX
4
+ class FiltersTest < MiniTest::Spec
5
+
6
+ should "Filters should be singleton classes" do
7
+ assert_equal false, Filter.respond_to?(:new)
8
+ assert_equal Filter.instance.object_id, Filter.instance.object_id
9
+ end
10
+
11
+ context 'Filters.resolve' do
12
+ should "return the filter if a filter is given" do
13
+ assert_equal Filter.instance.object_id, Filters.resolve(Filter.instance).object_id
14
+ end
15
+
16
+ should "return the parameter if it quacks like a filter" do
17
+ f = Object.new
18
+ def f.apply; nil; end
19
+ assert_equal f.object_id, Filters.resolve(f).object_id
20
+ end
21
+
22
+ should "return the filter if there is a filter by that name" do
23
+ class FooBar < Filter; end
24
+ assert_equal FooBar.instance.object_id, Filters.resolve(:foobar).object_id
25
+ assert_equal FooBar.instance.object_id, Filters.resolve('foobar').object_id
26
+ Filter.subclasses.delete(FooBar)
27
+ end
28
+
29
+ should "return nil if there is no filter by that name" do
30
+ assert_equal nil, Filters.resolve(:foobar)
31
+ assert_equal nil, Filters.resolve('foobar')
32
+ assert_equal nil, Filters.resolve(nil)
33
+ end
34
+ end
35
+
36
+ end
37
+ end
@@ -66,5 +66,70 @@ module BibTeX
66
66
  assert_equal '"foo" # bar', Value.new('foo', :bar).to_s
67
67
  end
68
68
  end
69
+
70
+ context "conversions" do
71
+ setup do
72
+ class Upcase < BibTeX::Filter
73
+ def apply (value)
74
+ value.is_a?(::String) ? value.upcase : value
75
+ end
76
+ end
77
+ @values = [Value.new('foo'), Value.new('foo', :bar)]
78
+ end
79
+
80
+ context "#convert" do
81
+ should "convert the value when given a filter instance" do
82
+ assert_equal ['FOO', '"FOO" # bar'], @values.map { |v| v.convert(Upcase.instance).to_s }
83
+ end
84
+
85
+ should "convert the value when given a filter class" do
86
+ assert_equal ['FOO', '"FOO" # bar'], @values.map { |v| v.convert(Upcase).to_s }
87
+ end
88
+
89
+ should "convert the value when given the name of a filter" do
90
+ assert_equal ['FOO', '"FOO" # bar'], @values.map { |v| v.convert(:upcase).to_s }
91
+ assert_equal ['FOO', '"FOO" # bar'], @values.map { |v| v.convert('upcase').to_s }
92
+ end
93
+
94
+ should "convert the value when using a ghost method" do
95
+ assert_equal ['FOO', '"FOO" # bar'], @values.map { |v| v.convert_upcase.to_s }
96
+ end
97
+
98
+ should "not alter the value when using a filter name" do
99
+ @values.each { |v| v.convert(:upcase) }
100
+ assert_equal ['foo', '"foo" # bar'], @values.map(&:to_s)
101
+ end
102
+
103
+ should "not alter the value when using a ghost method" do
104
+ @values.each { |v| v.convert_upcase }
105
+ assert_equal ['foo', '"foo" # bar'], @values.map(&:to_s)
106
+ end
107
+ end
108
+
109
+ context "#convert!" do
110
+ should "convert the value when given the name of a filter" do
111
+ assert_equal ['FOO', '"FOO" # bar'], @values.map { |v| v.convert!(:upcase).to_s }
112
+ end
113
+
114
+ should "alter the value when given the name of a filter" do
115
+ @values.each { |v| v.convert!(:upcase) }
116
+ assert_equal ['FOO', '"FOO" # bar'], @values.map(&:to_s)
117
+ end
118
+
119
+ should "alter the value when using a ghost method" do
120
+ @values.each { |v| v.convert_upcase! }
121
+ assert_equal ['FOO', '"FOO" # bar'], @values.map(&:to_s)
122
+ end
123
+
124
+ end
125
+
126
+ context "#to_s" do
127
+ should 'accept a :filter option and convert the values accordingly without changing the value' do
128
+ assert_equal '"FOO" # bar', @values[1].to_s(:filter => :upcase)
129
+ assert_equal '"foo" # bar', @values[1].to_s
130
+ end
131
+ end
132
+ end
133
+
69
134
  end
70
135
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: bibtex-ruby
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 1.3.7
5
+ version: 1.3.8
6
6
  platform: ruby
7
7
  authors:
8
8
  - Sylvester Keil
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-06-30 00:00:00 +02:00
13
+ date: 2011-07-05 00:00:00 +02:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -165,6 +165,8 @@ files:
165
165
  - lib/bibtex/entry.rb
166
166
  - lib/bibtex/error.rb
167
167
  - lib/bibtex/extensions.rb
168
+ - lib/bibtex/filters/latex.rb
169
+ - lib/bibtex/filters.rb
168
170
  - lib/bibtex/lexer.rb
169
171
  - lib/bibtex/name_parser.output
170
172
  - lib/bibtex/name_parser.rb
@@ -181,6 +183,7 @@ files:
181
183
  - test/bibtex/test_bibliography.rb
182
184
  - test/bibtex/test_elements.rb
183
185
  - test/bibtex/test_entry.rb
186
+ - test/bibtex/test_filters.rb
184
187
  - test/bibtex/test_lexer.rb
185
188
  - test/bibtex/test_name_parser.rb
186
189
  - test/bibtex/test_names.rb
@@ -224,7 +227,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
224
227
  requirements:
225
228
  - - ">="
226
229
  - !ruby/object:Gem::Version
227
- hash: -3039077610417701704
230
+ hash: -4114590851027997026
228
231
  segments:
229
232
  - 0
230
233
  version: "0"
@@ -245,6 +248,7 @@ test_files:
245
248
  - test/bibtex/test_bibliography.rb
246
249
  - test/bibtex/test_elements.rb
247
250
  - test/bibtex/test_entry.rb
251
+ - test/bibtex/test_filters.rb
248
252
  - test/bibtex/test_lexer.rb
249
253
  - test/bibtex/test_name_parser.rb
250
254
  - test/bibtex/test_names.rb