csl 1.0.0.pre1
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.
- 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
|