csl 1.0.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +8 -0
- data/.gitmodules +6 -0
- data/.rspec +3 -0
- data/.simplecov +2 -0
- data/.travis.yml +13 -0
- data/.yardopts +2 -0
- data/AGPL +662 -0
- data/BSDL +29 -0
- data/Gemfile +24 -0
- data/Guardfile +14 -0
- data/README.md +39 -0
- data/Rakefile +45 -0
- data/csl.gemspec +36 -0
- data/cucumber.yml +1 -0
- data/features/locales/loading.feature +57 -0
- data/features/locales/ordinalize.feature +861 -0
- data/features/parser/info.feature +27 -0
- data/features/parser/localized_dates.feature +35 -0
- data/features/parser/terms.feature +28 -0
- data/features/step_definitions/locale_steps.rb +34 -0
- data/features/step_definitions/parser_steps.rb +28 -0
- data/features/step_definitions/style_steps.rb +16 -0
- data/features/style/loading.feature +53 -0
- data/features/support/env.rb +8 -0
- data/lib/csl.rb +54 -0
- data/lib/csl/compatibility.rb +19 -0
- data/lib/csl/errors.rb +15 -0
- data/lib/csl/extensions.rb +63 -0
- data/lib/csl/info.rb +40 -0
- data/lib/csl/loader.rb +78 -0
- data/lib/csl/locale.rb +393 -0
- data/lib/csl/locale/date.rb +48 -0
- data/lib/csl/locale/style_options.rb +10 -0
- data/lib/csl/locale/term.rb +185 -0
- data/lib/csl/node.rb +285 -0
- data/lib/csl/parser.rb +92 -0
- data/lib/csl/pretty_printer.rb +33 -0
- data/lib/csl/schema.rb +109 -0
- data/lib/csl/style.rb +53 -0
- data/lib/csl/style/bibliography.rb +15 -0
- data/lib/csl/style/citation.rb +17 -0
- data/lib/csl/style/conditional.rb +11 -0
- data/lib/csl/style/date.rb +16 -0
- data/lib/csl/style/group.rb +9 -0
- data/lib/csl/style/label.rb +14 -0
- data/lib/csl/style/layout.rb +10 -0
- data/lib/csl/style/macro.rb +9 -0
- data/lib/csl/style/names.rb +54 -0
- data/lib/csl/style/number.rb +33 -0
- data/lib/csl/style/sort.rb +21 -0
- data/lib/csl/style/text.rb +10 -0
- data/lib/csl/treelike.rb +442 -0
- data/lib/csl/version.rb +3 -0
- data/spec/csl/info_spec.rb +116 -0
- data/spec/csl/locale/date_spec.rb +63 -0
- data/spec/csl/locale/style_options_spec.rb +19 -0
- data/spec/csl/locale/term_spec.rb +96 -0
- data/spec/csl/locale_spec.rb +128 -0
- data/spec/csl/node_spec.rb +100 -0
- data/spec/csl/parser_spec.rb +92 -0
- data/spec/csl/schema_spec.rb +70 -0
- data/spec/csl/style/bibliography_spec.rb +7 -0
- data/spec/csl/style/citation_spec.rb +7 -0
- data/spec/csl/style/conditional_spec.rb +7 -0
- data/spec/csl/style/date_spec.rb +11 -0
- data/spec/csl/style/group_spec.rb +7 -0
- data/spec/csl/style/label_spec.rb +7 -0
- data/spec/csl/style/layout_spec.rb +7 -0
- data/spec/csl/style/macro_spec.rb +7 -0
- data/spec/csl/style/names_spec.rb +23 -0
- data/spec/csl/style/number_spec.rb +84 -0
- data/spec/csl/style/text_spec.rb +7 -0
- data/spec/csl/style_spec.rb +19 -0
- data/spec/csl/treelike_spec.rb +151 -0
- data/spec/spec_helper.rb +30 -0
- metadata +192 -0
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module CSL
|
4
|
+
|
5
|
+
describe Parser do
|
6
|
+
|
7
|
+
describe '.instance' do
|
8
|
+
it 'returns the parser' do
|
9
|
+
Parser.instance.should be_instance_of(Parser)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
Parser.engines.each_pair do |name, parser|
|
14
|
+
describe "when using the #{name} parser " do
|
15
|
+
before(:all) { Parser.instance.parser = parser }
|
16
|
+
|
17
|
+
describe '#parse' do
|
18
|
+
|
19
|
+
describe 'for <foo/>' do
|
20
|
+
let(:source) { '<foo/>' }
|
21
|
+
|
22
|
+
it 'returns a CSL::Node' do
|
23
|
+
Parser.instance.parse(source).should be_a(Node)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'returns a node with nodename "foo"' do
|
27
|
+
Parser.instance.parse(source).nodename.should == 'foo'
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'returns a node with no attributes' do
|
31
|
+
Parser.instance.parse(source).should_not have_attributes
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'returns a node with no children' do
|
35
|
+
Parser.instance.parse(source).should_not have_children
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'for <foo bar="x"/>' do
|
40
|
+
let(:source) { '<foo bar="x"/>' }
|
41
|
+
|
42
|
+
it 'returns a node with attributes' do
|
43
|
+
Parser.instance.parse(source).should have_attributes
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'returns a node with attribute bar' do
|
47
|
+
Parser.instance.parse(source).attribute?(:bar).should be
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'bar should be "x"' do
|
51
|
+
Parser.instance.parse(source)[:bar].should == 'x'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'for <foo>Foo Bar</foo>' do
|
56
|
+
let(:source) { '<foo>Foo Bar</foo>' }
|
57
|
+
|
58
|
+
it 'returns text node' do
|
59
|
+
Parser.instance.parse(source).should be_textnode
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'returns a regular node for <x>\n <y/></x>' do
|
64
|
+
Parser.instance.parse("<x>\n <y/></x>").should_not be_textnode
|
65
|
+
end
|
66
|
+
|
67
|
+
describe 'xml comments' do
|
68
|
+
it 'ignores comment-only documents' do
|
69
|
+
Parser.instance.parse("<!--x></x-->").should be_nil
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'ignores comments in normal nodes' do
|
73
|
+
Parser.instance.parse("<x><!-- comment --></x>").should_not have_children
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'ignores comments in text nodes' do
|
77
|
+
node = Parser.instance.parse("<x>foo<!-- comment --></x>")
|
78
|
+
node.should be_textnode
|
79
|
+
node.should_not have_children
|
80
|
+
node.text.should == 'foo'
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module CSL
|
4
|
+
describe 'Schema' do
|
5
|
+
|
6
|
+
describe '.version' do
|
7
|
+
it 'returns a version string' do
|
8
|
+
Schema.version.should match(/^\d+\.\d+\.\d+/)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'is greater than 1.0' do
|
12
|
+
Schema.version.split(/\./)[0].to_i.should >= 1
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '.variables' do
|
17
|
+
it 'contains :names fields' do
|
18
|
+
Schema.variables[:names].should_not be_empty
|
19
|
+
Schema.variables[:name].should equal Schema.variables[:names]
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'contains :date fields' do
|
23
|
+
Schema.variables[:date].should_not be_empty
|
24
|
+
Schema.variables[:dates].should equal Schema.variables[:date]
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'contains :text fields' do
|
28
|
+
Schema.variables[:text].should_not be_empty
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'contains :number fields' do
|
32
|
+
Schema.variables[:numbers].should_not be_empty
|
33
|
+
Schema.variables[:number].should_not be_empty
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'accepts either string or symbol input' do
|
37
|
+
Schema.variables[:names].should equal Schema.variables['names']
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '.types' do
|
42
|
+
it 'returns an array' do
|
43
|
+
Schema.types.should be_a(Array)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'is not empty' do
|
47
|
+
Schema.types.should_not be_empty
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'includes :article' do
|
51
|
+
Schema.types.should include(:article)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '.categories' do
|
56
|
+
it 'given a field name returns the corresponding type' do
|
57
|
+
Schema.categories[:author].should == :names
|
58
|
+
Schema.categories[:issued].should == :date
|
59
|
+
Schema.categories[:abstract].should == :text
|
60
|
+
Schema.categories[:issue].should == :number
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'accepts either string or symbol input' do
|
64
|
+
Schema.categories.should have_key(:author)
|
65
|
+
Schema.categories['author'].should equal Schema.categories[:author]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module CSL
|
4
|
+
describe Style::Names do
|
5
|
+
|
6
|
+
end
|
7
|
+
|
8
|
+
describe Style::Name do
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
describe Style::NamePart do
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
describe Style::EtAl do
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
describe Style::Substitute do
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module CSL
|
4
|
+
describe Style::Number do
|
5
|
+
|
6
|
+
describe '.new' do
|
7
|
+
it 'returns an empty number tag by default' do
|
8
|
+
Style::Number.new.should_not have_attributes
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'accepts a form attribute' do
|
12
|
+
Style::Number.new(:form => 'roman').should be_roman
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#numeric?' do
|
17
|
+
it 'returns true by default' do
|
18
|
+
Style::Number.new.should be_numeric
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'returns false if the form attribute is set to a value other than :numeric' do
|
22
|
+
Style::Number.new(:form => 'foo').should_not be_numeric
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'returns false if the form attribute is set to :numeric' do
|
26
|
+
Style::Number.new(:form => 'numeric').should be_numeric
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#roman?' do
|
31
|
+
it 'returns false by default' do
|
32
|
+
Style::Number.new.should_not be_roman
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'returns false if the form attribute is set to a value other than :numeric' do
|
36
|
+
Style::Number.new(:form => 'ordinal').should_not be_roman
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'returns false if the form attribute is set to :roman' do
|
40
|
+
Style::Number.new(:form => 'roman').should be_roman
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#ordinal?' do
|
45
|
+
it 'returns false by default' do
|
46
|
+
Style::Number.new.should_not be_ordinal
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'returns false if the form attribute is set to a value other than :ordinal' do
|
50
|
+
Style::Number.new(:form => 'long-ordinal').should_not be_ordinal
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'returns false if the form attribute is set to :ordinal' do
|
54
|
+
Style::Number.new(:form => 'ordinal').should be_ordinal
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '#long_ordinal?' do
|
59
|
+
it 'returns false by default' do
|
60
|
+
Style::Number.new.should_not be_long_ordinal
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'returns false if the form attribute is set to a value other than :"long-ordinal"' do
|
64
|
+
Style::Number.new(:form => 'ordinal').should_not be_long_ordinal
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'returns false if the form attribute is set to :ordinal' do
|
68
|
+
Style::Number.new(:form => 'long-ordinal').should be_long_ordinal
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
describe '#to_xml' do
|
74
|
+
it 'returns an empty number tag by default' do
|
75
|
+
Style::Number.new.to_xml.should == '<number/>'
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'returns a tag with a all attribute assignments' do
|
79
|
+
Style::Number.new(:form => 'roman').to_xml.should == '<number form="roman"/>'
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module CSL
|
4
|
+
describe Style do
|
5
|
+
|
6
|
+
it { should be }
|
7
|
+
|
8
|
+
it 'has a 1.x version by default' do
|
9
|
+
Style.new[:version].should match(/1\.\d+(\.\d+)?/)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#to_xml' do
|
13
|
+
it 'returns an empty style' do
|
14
|
+
Style.new.to_xml.should match(/<style[^>]*\/>/)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module CSL
|
4
|
+
describe 'Treelike' do
|
5
|
+
|
6
|
+
before(:all) do
|
7
|
+
class TestTree
|
8
|
+
include Treelike
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@children = self.class.create_children
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:node) { TestTree.new }
|
17
|
+
|
18
|
+
let(:lvl1) { TestTree.new.add_child(TestTree.new) }
|
19
|
+
let(:lvl2) { TestTree.new.add_child(TestTree.new).add_child(TestTree.new) }
|
20
|
+
|
21
|
+
it 'has no children by default' do
|
22
|
+
node.should_not have_children
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'is empty by default' do
|
26
|
+
node.should be_empty
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#children' do
|
30
|
+
|
31
|
+
it 'is empty by default' do
|
32
|
+
node.children.should be_empty
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'grows when adding child nodes' do
|
36
|
+
expect { node << TestTree.new }.to change { node.children.length }.by(1)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#nodename' do
|
42
|
+
it 'returns the class name in attribute form by default' do
|
43
|
+
node.nodename.should == 'test-tree'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#ancestors' do
|
48
|
+
it 'returns and empty list by default' do
|
49
|
+
node.ancestors.should be_empty
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'returns a list with one ancestor at level 1' do
|
53
|
+
lvl1.ancestors.should have(1).element
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'the last ancestor is also the root node at levels 1 and deeper' do
|
57
|
+
lvl1.ancestors.last.should be_root
|
58
|
+
lvl2.ancestors.last.should be_root
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'returns a list with two ancestors at level 2' do
|
62
|
+
lvl2.ancestors.should have(2).elements
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'is a root node by default' do
|
67
|
+
node.should be_root
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '#root' do
|
71
|
+
it 'returns self at level 0' do
|
72
|
+
node.root.should equal(node)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'returns the parent at level 1' do
|
76
|
+
lvl1.root.should == lvl1.parent
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'returns parent.parent at level 2' do
|
80
|
+
lvl2.root.should == lvl2.parent.parent
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe '#depth' do
|
85
|
+
it 'returns 0 by default' do
|
86
|
+
node.depth.should == 0
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'returns 1 at level 1' do
|
90
|
+
lvl1.depth.should == 1
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'returns 2 at level 2' do
|
94
|
+
lvl2.depth.should == 2
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'grows when the node is added to another node' do
|
98
|
+
expect { TestTree.new << node }.to change { node.depth }.by(1)
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
describe 'named children' do
|
104
|
+
before(:all) do
|
105
|
+
class TestTree
|
106
|
+
attr_children :'test-tree'
|
107
|
+
end
|
108
|
+
class AnotherTree
|
109
|
+
include Treelike
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'the class contains a children struct' do
|
114
|
+
TestTree.const?(:Children).should be true
|
115
|
+
end
|
116
|
+
|
117
|
+
describe '.create_children' do
|
118
|
+
it 'returns the children struct' do
|
119
|
+
TestTree.create_children.should be_a(Struct)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe '#children' do
|
124
|
+
it 'returns a children struct instance' do
|
125
|
+
TestTree.new.children.should be_a(Struct)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'has no children by default' do
|
130
|
+
TestTree.new.should_not have_children
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'has children when adding child nodes' do
|
134
|
+
expect { node << TestTree.new }.to change { node.has_children? }.to(true)
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'raises an error when adding a child with an invalid name' do
|
138
|
+
expect { node << AnotherTree.new }.to raise_error(ValidationError)
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'accepts multiple nodes of the same name' do
|
142
|
+
expect { node << TestTree.new << TestTree.new }.to change {
|
143
|
+
node.children.each.to_a.length
|
144
|
+
}.from(0).to(2)
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|