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/test/bibtex/test_filters.rb
CHANGED
@@ -2,31 +2,32 @@ require 'helper.rb'
|
|
2
2
|
|
3
3
|
module BibTeX
|
4
4
|
class FiltersTest < Minitest::Spec
|
5
|
-
|
6
|
-
it "should Filters should be singleton classes" do
|
5
|
+
it 'should Filters should be singleton classes' do
|
7
6
|
assert_equal false, Filter.respond_to?(:new)
|
8
7
|
assert_equal Filter.instance.object_id, Filter.instance.object_id
|
9
8
|
end
|
10
9
|
|
11
10
|
describe 'Filters.resolve' do
|
12
|
-
it
|
11
|
+
it 'should return the filter if a filter is given' do
|
13
12
|
assert_equal Filter.instance.object_id, Filters.resolve(Filter.instance).object_id
|
14
13
|
end
|
15
14
|
|
16
|
-
it
|
15
|
+
it 'should return the parameter if it quacks like a filter' do
|
17
16
|
f = Object.new
|
18
|
-
def f.apply
|
17
|
+
def f.apply
|
18
|
+
nil
|
19
|
+
end
|
19
20
|
assert_equal f.object_id, Filters.resolve(f).object_id
|
20
21
|
end
|
21
22
|
|
22
|
-
it
|
23
|
+
it 'should return the filter if there is a filter by that name' do
|
23
24
|
class FooBar < Filter; end
|
24
25
|
assert_equal FooBar.instance.object_id, Filters.resolve(:foobar).object_id
|
25
26
|
assert_equal FooBar.instance.object_id, Filters.resolve('foobar').object_id
|
26
27
|
Filter.subclasses.delete(FooBar)
|
27
28
|
end
|
28
29
|
|
29
|
-
it
|
30
|
+
it 'should return nil if there is no filter by that name' do
|
30
31
|
assert_equal nil, Filters.resolve(:foobar)
|
31
32
|
assert_equal nil, Filters.resolve('foobar')
|
32
33
|
assert_equal nil, Filters.resolve(nil)
|
data/test/bibtex/test_lexer.rb
CHANGED
@@ -1,42 +1,39 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
1
|
require 'helper.rb'
|
4
2
|
|
5
3
|
module BibTeX
|
6
4
|
class LexerTest < Minitest::Spec
|
7
|
-
|
8
5
|
it 'correctly scans a string literal' do
|
9
|
-
assert_equal Lexer.new.analyse(
|
6
|
+
assert_equal Lexer.new.analyse('@string{ x = "foo" }').symbols, [:AT, :STRING, :LBRACE, :NAME, :EQ, :STRING_LITERAL, :RBRACE, false]
|
10
7
|
end
|
11
8
|
|
12
9
|
it 'strips line breaks by default' do
|
13
|
-
Lexer.new.analyse(%
|
14
|
-
|
10
|
+
Lexer.new.analyse(%(@string{ x = "foo\nbar" })).stack[-3].must_be :==,
|
11
|
+
[:STRING_LITERAL, 'foo bar']
|
15
12
|
end
|
16
13
|
|
17
14
|
it 'strips whitespace after line breaks by default' do
|
18
|
-
Lexer.new.analyse(%
|
19
|
-
|
15
|
+
Lexer.new.analyse(%(@string{ x = "foo\n bar" })).stack[-3].must_be :==,
|
16
|
+
[:STRING_LITERAL, 'foo bar']
|
20
17
|
end
|
21
18
|
|
22
19
|
it 'matches KEY tokens' do
|
23
|
-
Lexer.new.analyse(
|
20
|
+
Lexer.new.analyse('@misc{foo, }').symbols.must_be :==, [:AT, :NAME, :LBRACE, :KEY, :RBRACE, false]
|
24
21
|
end
|
25
22
|
|
26
23
|
it 'matches KEY tokens with non-ascii characters' do
|
27
|
-
Lexer.new.analyse(
|
24
|
+
Lexer.new.analyse('@misc{löwe, }').symbols.must_be :==, [:AT, :NAME, :LBRACE, :KEY, :RBRACE, false]
|
28
25
|
end
|
29
26
|
|
30
27
|
it 'matches KEY tokens after whitespace' do
|
31
|
-
Lexer.new.analyse(
|
28
|
+
Lexer.new.analyse('@misc{ foo, }').symbols.must_be :==, [:AT, :NAME, :LBRACE, :KEY, :RBRACE, false]
|
32
29
|
end
|
33
30
|
|
34
31
|
it "doesn't start a comment for types starting with but not equal @comment" do
|
35
|
-
Lexer.new.analyse(
|
32
|
+
Lexer.new.analyse('@commentary{staudinger, }').symbols.must_be :==, [:AT, :NAME, :LBRACE, :KEY, :RBRACE, false]
|
36
33
|
end
|
37
34
|
|
38
35
|
it "doesn't start a preamble for types starting with but not equal @preamble" do
|
39
|
-
Lexer.new.analyse(
|
36
|
+
Lexer.new.analyse('@preamblestring{ preamble }').symbols.must_be :==, [:AT, :NAME, :LBRACE, :NAME, :RBRACE, false]
|
40
37
|
end
|
41
38
|
end
|
42
39
|
end
|
@@ -2,7 +2,6 @@ require 'helper'
|
|
2
2
|
|
3
3
|
module BibTeX
|
4
4
|
class NameParserTest < Minitest::Spec
|
5
|
-
|
6
5
|
describe "parse a number of entries having a 'van' or 'van den' name prefix" do
|
7
6
|
before do
|
8
7
|
@a = Names.parse('van den Bout, D. E.')
|
@@ -10,20 +9,18 @@ module BibTeX
|
|
10
9
|
end
|
11
10
|
|
12
11
|
it "should parse 'van den' part starting with lowercase letter" do
|
13
|
-
assert_equal(@a[0].to_s,
|
14
|
-
assert_equal(@a[0].prefix,
|
12
|
+
assert_equal(@a[0].to_s, 'van den Bout, D. E.')
|
13
|
+
assert_equal(@a[0].prefix, 'van den')
|
15
14
|
end
|
16
15
|
|
17
16
|
it "should parse 'Van den' part starting with uppercase letter" do
|
18
|
-
assert_equal(@b[0].to_s,
|
19
|
-
assert_equal(@b[0].prefix,
|
17
|
+
assert_equal(@b[0].to_s, 'Van den Bout, D. E.')
|
18
|
+
assert_equal(@b[0].prefix, 'Van den')
|
20
19
|
end
|
21
20
|
|
22
|
-
it
|
23
|
-
assert_equal '', Names.parse(
|
21
|
+
it 'should accept empty strings' do
|
22
|
+
assert_equal '', Names.parse('').to_s
|
24
23
|
end
|
25
|
-
|
26
24
|
end
|
27
|
-
|
28
25
|
end
|
29
26
|
end
|
data/test/bibtex/test_names.rb
CHANGED
@@ -1,17 +1,14 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
1
|
require 'helper'
|
4
2
|
|
5
3
|
module BibTeX
|
6
4
|
class NamesTest < Minitest::Spec
|
7
|
-
|
8
5
|
before do
|
9
|
-
@poe = Name.new(:
|
6
|
+
@poe = Name.new(first: 'Edgar Allen', last: 'Poe')
|
10
7
|
end
|
11
8
|
|
12
9
|
describe 'string behaviour' do
|
13
10
|
before do
|
14
|
-
@name = Name.new(:
|
11
|
+
@name = Name.new(first: 'Charles Louis Xavier Joseph', prefix: 'de la', last: 'Vallee Poussin', suffix: 'Jr.')
|
15
12
|
end
|
16
13
|
it 'should implement upcase!' do
|
17
14
|
assert_equal 'DE LA VALLEE POUSSIN, JR., CHARLES LOUIS XAVIER JOSEPH', @name.upcase!.to_s
|
@@ -30,7 +27,7 @@ module BibTeX
|
|
30
27
|
end
|
31
28
|
|
32
29
|
it 'accepts the :initials option' do
|
33
|
-
@poe.display_order(:
|
30
|
+
@poe.display_order(initials: true).must_be :==, 'E.A. Poe'
|
34
31
|
end
|
35
32
|
end
|
36
33
|
|
@@ -40,7 +37,7 @@ module BibTeX
|
|
40
37
|
end
|
41
38
|
|
42
39
|
it 'accepts the :initials option' do
|
43
|
-
@poe.sort_order(:
|
40
|
+
@poe.sort_order(initials: true).must_be :==, 'Poe, E.A.'
|
44
41
|
end
|
45
42
|
end
|
46
43
|
|
@@ -64,26 +61,26 @@ module BibTeX
|
|
64
61
|
|
65
62
|
describe '#rename_if' do
|
66
63
|
it 'renames the name to the given attributes if no condition is given' do
|
67
|
-
@poe.rename_if(
|
64
|
+
@poe.rename_if(first: 'E.A.').first.must_equal 'E.A.'
|
68
65
|
end
|
69
66
|
|
70
67
|
it 'renames the name to the given attributes if all conditions match' do
|
71
|
-
@poe.rename_if({ :
|
72
|
-
@poe.rename_if({ :
|
68
|
+
@poe.rename_if({ first: 'E.A.' }, last: @poe.last).first.must_equal 'E.A.'
|
69
|
+
@poe.rename_if({ first: 'E.A.' }, last: @poe.last, first: @poe.first).first.must_equal 'E.A.'
|
73
70
|
end
|
74
71
|
|
75
72
|
it 'renames the name to the given attributes if the block returns true' do
|
76
|
-
@poe.rename_if(
|
73
|
+
@poe.rename_if(first: 'E.A.') { |_n| true }.first.must_equal 'E.A.'
|
77
74
|
end
|
78
75
|
|
79
76
|
it 'does not rename the name to the given attributes if at least one condition does not match' do
|
80
|
-
@poe.rename_if({ :
|
81
|
-
@poe.rename_if({ :
|
82
|
-
@poe.rename_if({ :
|
77
|
+
@poe.rename_if({ first: 'E.A.' }, last: 'foo').first.wont_equal 'E.A.'
|
78
|
+
@poe.rename_if({ first: 'E.A.' }, last: 'foo', first: @poe.first).first.wont_equal 'E.A.'
|
79
|
+
@poe.rename_if({ first: 'E.A.' }, last: @poe.last, first: 'foo').first.wont_equal 'E.A.'
|
83
80
|
end
|
84
81
|
|
85
82
|
it 'does not rename the name to the given attributes if the block returns false' do
|
86
|
-
@poe.rename_if(
|
83
|
+
@poe.rename_if(first: 'E.A.') { |_n| false }.first.wont_equal 'E.A.'
|
87
84
|
end
|
88
85
|
end
|
89
86
|
|
@@ -96,73 +93,71 @@ module BibTeX
|
|
96
93
|
|
97
94
|
it 'merges different names' do
|
98
95
|
n1 = Names.new(@poe)
|
99
|
-
n2 = Names.new(Name.new(:
|
100
|
-
assert_equal "#{@poe
|
96
|
+
n2 = Names.new(Name.new(last: 'Plato'))
|
97
|
+
assert_equal "#{@poe} and Plato", n1.merge!(n2).to_s
|
101
98
|
end
|
102
99
|
end
|
103
100
|
|
104
101
|
describe '#normalize_initials' do
|
105
102
|
it 'returns normalized initials of existing initials only' do
|
106
|
-
Name.new(:
|
107
|
-
Name.new(:
|
108
|
-
Name.new(:
|
109
|
-
Name.new(:
|
110
|
-
Name.new(:
|
111
|
-
Name.new(:
|
103
|
+
Name.new(first: 'Edgar A.', last: 'Poe').normalize_initials.must_equal 'Edgar A.'
|
104
|
+
Name.new(first: 'E.A.', last: 'Poe').normalize_initials.must_equal 'E.A.'
|
105
|
+
Name.new(first: 'E. A.', last: 'Poe').normalize_initials.must_equal 'E.A.'
|
106
|
+
Name.new(first: 'E. A', last: 'Poe').normalize_initials.must_equal 'E.A.'
|
107
|
+
Name.new(first: 'E A', last: 'Poe').normalize_initials.must_equal 'E.A.'
|
108
|
+
Name.new(first: 'Edgar A P', last: 'Poe').normalize_initials.must_equal 'Edgar A.P.'
|
112
109
|
end
|
113
110
|
end
|
114
111
|
|
115
112
|
describe '#extend_initials' do
|
116
113
|
it 'extends the first name if the last name and initials match' do
|
117
|
-
Name.new(:
|
118
|
-
Name.new(:
|
119
|
-
Name.new(:
|
120
|
-
Name.new(:
|
121
|
-
Name.new(:
|
122
|
-
Name.new(:
|
123
|
-
Name.new(:
|
114
|
+
Name.new(first: 'E.A.', last: 'Poe').extend_initials('Edgar Allen', 'Poe').first.must_equal 'Edgar Allen'
|
115
|
+
Name.new(first: 'Edgar A.', last: 'Poe').extend_initials('Edgar Allen', 'Poe').first.must_equal 'Edgar Allen'
|
116
|
+
Name.new(first: 'E. A.', last: 'Poe').extend_initials('Edgar Allen', 'Poe').first.must_equal 'Edgar Allen'
|
117
|
+
Name.new(first: 'E. A', last: 'Poe').extend_initials('Edgar Allen', 'Poe').first.must_equal 'Edgar Allen'
|
118
|
+
Name.new(first: 'E A', last: 'Poe').extend_initials('Edgar Allen', 'Poe').first.must_equal 'Edgar Allen'
|
119
|
+
Name.new(first: 'E. Allen', last: 'Poe').extend_initials('Edgar Allen', 'Poe').first.must_equal 'Edgar Allen'
|
120
|
+
Name.new(first: 'E.A.', last: 'Poe').extend_initials('Edgar A.', 'Poe').first.must_equal 'Edgar A.'
|
124
121
|
|
125
|
-
Name.new(:
|
126
|
-
Name.new(:
|
127
|
-
Name.new(:
|
128
|
-
Name.new(:
|
129
|
-
Name.new(:
|
122
|
+
Name.new(first: 'Edgar-A.', last: 'Poe').extend_initials('Edgar-Allen', 'Poe').first.must_equal 'Edgar-Allen'
|
123
|
+
Name.new(first: 'E.-Allen', last: 'Poe').extend_initials('Edgar-Allen', 'Poe').first.must_equal 'Edgar-Allen'
|
124
|
+
Name.new(first: 'E.-A.', last: 'Poe').extend_initials('Edgar-Allen', 'Poe').first.must_equal 'Edgar-Allen'
|
125
|
+
Name.new(first: 'E.-A', last: 'Poe').extend_initials('Edgar-Allen', 'Poe').first.must_equal 'Edgar-Allen'
|
126
|
+
Name.new(first: 'E-A', last: 'Poe').extend_initials('Edgar-Allen', 'Poe').first.must_equal 'Edgar-Allen'
|
130
127
|
end
|
131
128
|
|
132
129
|
it 'extends the first name if the last name and initials name match with extra middle names' do
|
133
|
-
Name.new(:
|
134
|
-
Name.new(:
|
135
|
-
Name.new(:
|
130
|
+
Name.new(first: 'E.', last: 'Poe').extend_initials('Edgar Allen', 'Poe').first.must_equal 'Edgar Allen'
|
131
|
+
Name.new(first: 'E', last: 'Poe').extend_initials('Edgar Allen', 'Poe').first.must_equal 'Edgar Allen'
|
132
|
+
Name.new(first: 'Edgar', last: 'Poe').extend_initials('Edgar Allen', 'Poe').first.must_equal 'Edgar Allen'
|
136
133
|
|
137
|
-
Name.new(:
|
138
|
-
Name.new(:
|
134
|
+
Name.new(first: 'E.A.', last: 'Poe').extend_initials('Edgar', 'Poe').first.must_equal 'E.A.'
|
135
|
+
Name.new(first: 'A.', last: 'Poe').extend_initials('Edgar', 'Poe').first.must_equal 'A.'
|
139
136
|
end
|
140
137
|
|
141
138
|
it 'does not extend the first name if the last name or initials do not match' do
|
142
|
-
Name.new(:
|
143
|
-
Name.new(:
|
144
|
-
Name.new(:
|
139
|
+
Name.new(first: 'E.A.', last: 'Poe').extend_initials('Edgar Allen', 'Poser').first.wont_equal 'Edgar Allen'
|
140
|
+
Name.new(first: 'E.A.', last: 'Poe').extend_initials('Edgar Ellen', 'Poe').first.wont_equal 'Edgar Ellen'
|
141
|
+
Name.new(first: 'E.R.', last: 'Poe').extend_initials('Edgar Allen', 'Poe').first.wont_equal 'Edgar Allen'
|
145
142
|
end
|
146
143
|
end
|
147
144
|
|
148
|
-
|
145
|
+
describe 'conversions' do
|
149
146
|
class UpcaseAll < BibTeX::Filter
|
150
|
-
def apply
|
147
|
+
def apply(value)
|
151
148
|
value.upcase
|
152
149
|
end
|
153
150
|
end
|
154
151
|
|
155
|
-
describe
|
156
|
-
it
|
157
|
-
|
152
|
+
describe '#convert' do
|
153
|
+
it 'converts the value when given a filter instance' do
|
154
|
+
Names.parse('Poe and Hawthorne').convert(UpcaseAll.instance).to_s.must_be :==, 'POE and HAWTHORNE'
|
158
155
|
end
|
159
156
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
157
|
+
it 'converts LaTeX umlauts' do
|
158
|
+
Names.parse("S{\\o}ren Kirkegaard and Emmanuel L\\'evinas").convert(:latex).to_s.must_be :==, 'Kirkegaard, Søren and Lévinas, Emmanuel'
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
166
162
|
end
|
167
|
-
|
168
163
|
end
|
data/test/bibtex/test_parser.rb
CHANGED
@@ -2,10 +2,9 @@ require 'helper.rb'
|
|
2
2
|
|
3
3
|
module BibTeX
|
4
4
|
class ParserTest < Minitest::Spec
|
5
|
-
|
6
5
|
describe 'given a set of valid @entries' do
|
7
6
|
before do
|
8
|
-
@bib = Parser.new(:
|
7
|
+
@bib = Parser.new(debug: false).parse(File.read(Test.fixtures(:entry)))
|
9
8
|
end
|
10
9
|
|
11
10
|
it 'returns a Bibliography instance' do
|
@@ -18,11 +17,11 @@ module BibTeX
|
|
18
17
|
end
|
19
18
|
|
20
19
|
it 'parses the key values' do
|
21
|
-
assert_equal %w
|
20
|
+
assert_equal %w[key:0 key:1 foo staudinger], @bib.map(&:key)
|
22
21
|
end
|
23
22
|
|
24
23
|
it 'should parse the entry types' do
|
25
|
-
assert_equal [
|
24
|
+
assert_equal %i[book article article commentary], @bib.map(&:type)
|
26
25
|
end
|
27
26
|
|
28
27
|
it 'should parse all values correctly' do
|
@@ -35,63 +34,62 @@ module BibTeX
|
|
35
34
|
assert_equal 'American Library', @bib[:'key:0'].publisher
|
36
35
|
assert_equal 'American Library', @bib[:'key:1'].publisher
|
37
36
|
|
38
|
-
assert_equal %q
|
37
|
+
assert_equal %q(Selected \emph{Poetry} and `Tales'), @bib[:'key:0'].title
|
39
38
|
assert_equal 'Tales and Sketches', @bib[:'key:1'].title
|
40
39
|
end
|
41
40
|
end
|
42
41
|
|
43
42
|
describe 'key parsing' do
|
44
43
|
it 'handles whitespace in keys' do
|
45
|
-
input =
|
46
|
-
bib = Parser.new(:
|
47
|
-
assert_equal
|
44
|
+
input = '@Misc{George Martin06,title = {FEAST FOR CROWS}}'
|
45
|
+
bib = Parser.new(debug: false, strict: false).parse(input)
|
46
|
+
assert_equal 'George Martin06', bib.first.key
|
48
47
|
assert bib[:"George Martin06"]
|
49
48
|
end
|
50
49
|
|
51
50
|
it 'handles plus symbols in keys' do
|
52
|
-
input =
|
53
|
-
bib = Parser.new(:
|
54
|
-
assert_equal
|
51
|
+
input = '@Misc{foo+bar,title = {Foobar}}'
|
52
|
+
bib = Parser.new(debug: false, strict: false).parse(input)
|
53
|
+
assert_equal 'foo+bar', bib.first.key
|
55
54
|
assert bib[:"foo+bar"]
|
56
55
|
end
|
57
56
|
|
58
57
|
it 'allows semicolons in keys' do
|
59
|
-
input =
|
60
|
-
bib = Parser.new(:
|
61
|
-
assert_equal
|
58
|
+
input = '@Misc{Gomez;,title = {Foobar}}'
|
59
|
+
bib = Parser.new(debug: false, strict: false).parse(input)
|
60
|
+
assert_equal 'Gomez;', bib.first.key
|
62
61
|
assert bib[:"Gomez;"]
|
63
62
|
end
|
64
63
|
|
65
64
|
it 'allows quotes in keys' do
|
66
|
-
input =
|
67
|
-
bib = Parser.new(:
|
68
|
-
assert_equal %
|
65
|
+
input = %(@Misc{Gomez'1",title = {Foobar}})
|
66
|
+
bib = Parser.new(debug: false, strict: false).parse(input)
|
67
|
+
assert_equal %(Gomez'1"), bib.first.key
|
69
68
|
assert bib[:"Gomez'1\""]
|
70
69
|
end
|
71
70
|
|
72
71
|
it 'fails when there is no cite-key' do
|
73
|
-
input =
|
72
|
+
input = '@misc{title = {Crime and Punishment}}'
|
74
73
|
assert_raises ParseError do
|
75
|
-
Parser.new(:
|
74
|
+
Parser.new(debug: false, strict: false).parse(input)
|
76
75
|
end
|
77
76
|
end
|
78
77
|
|
79
78
|
it 'tolerates missing key with :allow_missing_keys set' do
|
80
|
-
input =
|
81
|
-
assert_equal :misc, Parser.new(
|
82
|
-
:
|
83
|
-
|
79
|
+
input = '@misc{title = {Crime and Punishment}}'
|
80
|
+
assert_equal :misc, Parser.new(
|
81
|
+
debug: false, strict: false, allow_missing_keys: true
|
82
|
+
).parse(input)[0].type
|
84
83
|
end
|
85
84
|
end
|
86
85
|
|
87
86
|
describe 'backslashes and escape sequences' do
|
88
|
-
|
89
87
|
it 'leaves backslashes intact' do
|
90
88
|
Parser.new.parse(%q(@misc{key, title = "a backslash: \"}))[0].title.must_be :==, 'a backslash: \\'
|
91
89
|
end
|
92
90
|
|
93
91
|
it 'parses LaTeX escaped quotes {"}' do
|
94
|
-
Parser.new.parse(
|
92
|
+
Parser.new.parse('@misc{key, title = "{"}"}')[0].title.must_be :==, '{"}'
|
95
93
|
end
|
96
94
|
|
97
95
|
it 'parses complex LaTeX markup' do
|
@@ -110,12 +108,11 @@ module BibTeX
|
|
110
108
|
b.booktitle.must_be :==, "Perception et Intermodalit\\'{e}: Approches Actuelles De La Question De Molyneux"
|
111
109
|
b.editor.to_s.must_be :==, 'Proust, Jo\"{e}lle'
|
112
110
|
end
|
113
|
-
|
114
111
|
end
|
115
112
|
|
116
113
|
describe 'given a set of explicit and implicit comments' do
|
117
114
|
before do
|
118
|
-
@bib = Parser.new(:
|
115
|
+
@bib = Parser.new(debug: false, include: [:meta_content]).parse(File.read(Test.fixtures(:comment)))
|
119
116
|
end
|
120
117
|
|
121
118
|
it 'should parses all @comments' do
|
@@ -128,13 +125,13 @@ module BibTeX
|
|
128
125
|
|
129
126
|
it 'should parse @comment content as string' do
|
130
127
|
assert_equal ' A comment can contain pretty much anything ', @bib.comments[0].content
|
131
|
-
assert_equal %
|
128
|
+
assert_equal %(\n@string{ foo = "bar" }\n\n@string{ bar = "foo" }\n), @bib.comments[1].content
|
132
129
|
end
|
133
130
|
end
|
134
131
|
|
135
132
|
describe 'given a set of @preambles' do
|
136
133
|
before do
|
137
|
-
@bib = Parser.new(:
|
134
|
+
@bib = Parser.new(debug: false).parse(File.read(Test.fixtures(:preamble)))
|
138
135
|
end
|
139
136
|
|
140
137
|
it 'should parse all @preambles' do
|
@@ -150,8 +147,8 @@ module BibTeX
|
|
150
147
|
|
151
148
|
describe 'given an entry containing a multi-line literals' do
|
152
149
|
before do
|
153
|
-
@braces = %
|
154
|
-
@string = %
|
150
|
+
@braces = %(@TechReport{key,\n author = {Donald,\n Duck}\n})
|
151
|
+
@string = %(@TechReport{key,\n author = "Donald,\n Duck"\n})
|
155
152
|
end
|
156
153
|
|
157
154
|
it 'should parse string literals' do
|
@@ -161,18 +158,17 @@ module BibTeX
|
|
161
158
|
it 'should parse braced literals' do
|
162
159
|
refute_nil Parser.new.parse(@braces)[:key]
|
163
160
|
end
|
164
|
-
|
165
161
|
end
|
166
162
|
|
167
163
|
describe 'year values' do
|
168
164
|
it 'parses non-numeric year literals' do
|
169
165
|
assert_equal 'to appear',
|
170
|
-
|
166
|
+
Parser.new.parse('@article{x, year = {to appear}}')['x'].year.to_s
|
171
167
|
end
|
172
168
|
|
173
169
|
it 'parses numeric year literals' do
|
174
170
|
assert_equal 1993,
|
175
|
-
|
171
|
+
Parser.new.parse('@article{x, year = { 1993 }}')['x'].year.to_i
|
176
172
|
end
|
177
173
|
end
|
178
174
|
|