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.
Files changed (77) hide show
  1. data/.document +5 -0
  2. data/.gitignore +8 -0
  3. data/.gitmodules +6 -0
  4. data/.rspec +3 -0
  5. data/.simplecov +2 -0
  6. data/.travis.yml +13 -0
  7. data/.yardopts +2 -0
  8. data/AGPL +662 -0
  9. data/BSDL +29 -0
  10. data/Gemfile +24 -0
  11. data/Guardfile +14 -0
  12. data/README.md +39 -0
  13. data/Rakefile +45 -0
  14. data/csl.gemspec +36 -0
  15. data/cucumber.yml +1 -0
  16. data/features/locales/loading.feature +57 -0
  17. data/features/locales/ordinalize.feature +861 -0
  18. data/features/parser/info.feature +27 -0
  19. data/features/parser/localized_dates.feature +35 -0
  20. data/features/parser/terms.feature +28 -0
  21. data/features/step_definitions/locale_steps.rb +34 -0
  22. data/features/step_definitions/parser_steps.rb +28 -0
  23. data/features/step_definitions/style_steps.rb +16 -0
  24. data/features/style/loading.feature +53 -0
  25. data/features/support/env.rb +8 -0
  26. data/lib/csl.rb +54 -0
  27. data/lib/csl/compatibility.rb +19 -0
  28. data/lib/csl/errors.rb +15 -0
  29. data/lib/csl/extensions.rb +63 -0
  30. data/lib/csl/info.rb +40 -0
  31. data/lib/csl/loader.rb +78 -0
  32. data/lib/csl/locale.rb +393 -0
  33. data/lib/csl/locale/date.rb +48 -0
  34. data/lib/csl/locale/style_options.rb +10 -0
  35. data/lib/csl/locale/term.rb +185 -0
  36. data/lib/csl/node.rb +285 -0
  37. data/lib/csl/parser.rb +92 -0
  38. data/lib/csl/pretty_printer.rb +33 -0
  39. data/lib/csl/schema.rb +109 -0
  40. data/lib/csl/style.rb +53 -0
  41. data/lib/csl/style/bibliography.rb +15 -0
  42. data/lib/csl/style/citation.rb +17 -0
  43. data/lib/csl/style/conditional.rb +11 -0
  44. data/lib/csl/style/date.rb +16 -0
  45. data/lib/csl/style/group.rb +9 -0
  46. data/lib/csl/style/label.rb +14 -0
  47. data/lib/csl/style/layout.rb +10 -0
  48. data/lib/csl/style/macro.rb +9 -0
  49. data/lib/csl/style/names.rb +54 -0
  50. data/lib/csl/style/number.rb +33 -0
  51. data/lib/csl/style/sort.rb +21 -0
  52. data/lib/csl/style/text.rb +10 -0
  53. data/lib/csl/treelike.rb +442 -0
  54. data/lib/csl/version.rb +3 -0
  55. data/spec/csl/info_spec.rb +116 -0
  56. data/spec/csl/locale/date_spec.rb +63 -0
  57. data/spec/csl/locale/style_options_spec.rb +19 -0
  58. data/spec/csl/locale/term_spec.rb +96 -0
  59. data/spec/csl/locale_spec.rb +128 -0
  60. data/spec/csl/node_spec.rb +100 -0
  61. data/spec/csl/parser_spec.rb +92 -0
  62. data/spec/csl/schema_spec.rb +70 -0
  63. data/spec/csl/style/bibliography_spec.rb +7 -0
  64. data/spec/csl/style/citation_spec.rb +7 -0
  65. data/spec/csl/style/conditional_spec.rb +7 -0
  66. data/spec/csl/style/date_spec.rb +11 -0
  67. data/spec/csl/style/group_spec.rb +7 -0
  68. data/spec/csl/style/label_spec.rb +7 -0
  69. data/spec/csl/style/layout_spec.rb +7 -0
  70. data/spec/csl/style/macro_spec.rb +7 -0
  71. data/spec/csl/style/names_spec.rb +23 -0
  72. data/spec/csl/style/number_spec.rb +84 -0
  73. data/spec/csl/style/text_spec.rb +7 -0
  74. data/spec/csl/style_spec.rb +19 -0
  75. data/spec/csl/treelike_spec.rb +151 -0
  76. data/spec/spec_helper.rb +30 -0
  77. metadata +192 -0
@@ -0,0 +1,3 @@
1
+ module CSL
2
+ VERSION = '1.0.0.pre1'.freeze
3
+ end
@@ -0,0 +1,116 @@
1
+ require 'spec_helper'
2
+
3
+ module CSL
4
+
5
+ describe Info do
6
+
7
+ it { should_not be_nil }
8
+ it { should_not have_children }
9
+
10
+ describe '#nodename' do
11
+ it 'returns "info"' do
12
+ subject.nodename.should == 'info'
13
+ end
14
+ end
15
+
16
+ describe '#children' do
17
+ it 'returns a Info::Children instance' do
18
+ Info.new.children.should be_a(Info::Children)
19
+ end
20
+
21
+ it 'allows to set the id by writer method' do
22
+ lambda { Info.new.children.id = 'foo' }.should_not raise_error
23
+ end
24
+
25
+ it 'allows to set the id by array accessor' do
26
+ lambda { Info.new.children[:id] = 'foo' }.should_not raise_error
27
+ end
28
+ end
29
+
30
+ describe '#category' do
31
+ it 'returns nil by default' do
32
+ Info.new.category.should be nil
33
+ end
34
+ end
35
+
36
+ describe '#to_xml' do
37
+ it 'returns an empty info element by default' do
38
+ subject.to_xml.should == '<info/>'
39
+ end
40
+
41
+ it 'prints the id if present' do
42
+ Info.new { |i| i.set_child_id 'apa' }.to_xml.should == '<info><id>apa</id></info>'
43
+ end
44
+
45
+ it 'prints the category if present' do
46
+ Info.new { |i| i.category = 'author' }.to_xml.should == '<info><category>author</category></info>'
47
+ end
48
+
49
+ end
50
+
51
+ end
52
+
53
+ describe Info::Author do
54
+ it { should_not be_nil }
55
+
56
+ let(:poe) {
57
+ Info::Author.new { |a|
58
+ a.email = 'poe@baltimore.com'
59
+ a.name = 'E. A. Poe'
60
+ }
61
+ }
62
+
63
+ describe '#name' do
64
+ it 'returns nil by default' do
65
+ subject.name.should be nil
66
+ end
67
+
68
+ it 'returns the name if set' do
69
+ poe.name.to_s.should == 'E. A. Poe'
70
+ end
71
+ end
72
+
73
+ describe '#email' do
74
+ it 'returns the email' do
75
+ poe.email.to_s.should == 'poe@baltimore.com'
76
+ end
77
+ end
78
+
79
+ describe '#to_xml' do
80
+ it 'returns an empty author by default' do
81
+ subject.to_xml.should == '<author/>'
82
+ end
83
+
84
+ it 'prints all children' do
85
+ poe.to_xml.should == '<author><name>E. A. Poe</name><email>poe@baltimore.com</email></author>'
86
+ end
87
+ end
88
+
89
+ end
90
+
91
+ describe Info::Contributor do
92
+
93
+ it { should_not be_nil }
94
+
95
+ let(:bruce) { Info::Contributor.new { |c| c.name = "Bruce D'Arcus" } }
96
+
97
+ describe '#name' do
98
+ it 'returns the name' do
99
+ bruce.name.to_s.should == "Bruce D'Arcus"
100
+ end
101
+ end
102
+
103
+
104
+ describe '#to_xml' do
105
+ it 'returns an empty contributor by default' do
106
+ subject.to_xml.should == '<contributor/>'
107
+ end
108
+
109
+ it 'prints the name tag if present' do
110
+ bruce.to_xml.should == "<contributor><name>Bruce D'Arcus</name></contributor>"
111
+ end
112
+ end
113
+
114
+ end
115
+
116
+ end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+
3
+ module CSL
4
+
5
+ describe Locale::Date do
6
+
7
+ let(:date) { Locale::Date.new }
8
+
9
+ it { should_not be_nil }
10
+
11
+ it { should_not be_text }
12
+ it { should_not be_numeric }
13
+
14
+ describe '#parts' do
15
+
16
+ it 'returns nil by default' do
17
+ date.parts.should be_empty
18
+ end
19
+
20
+ end
21
+
22
+ describe '#to_xml' do
23
+
24
+ it 'returns <date/> by default' do
25
+ Locale::Date.new.to_xml.should == '<date/>'
26
+ end
27
+
28
+ it 'returns <date form="numeric"/> for an empty numeric date' do
29
+ Locale::Date.new(:form => 'numeric').to_xml.should == '<date form="numeric"/>'
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+ describe Locale::DatePart do
37
+
38
+ it { should_not be_nil }
39
+
40
+ it { should_not be_day }
41
+ it { should_not be_month }
42
+ it { should_not be_year }
43
+
44
+ describe '#to_xml' do
45
+
46
+ it 'returns <date-part/> by default' do
47
+ Locale::DatePart.new.to_xml.should == "<date-part/>"
48
+ end
49
+
50
+ it 'returns <date-part name="year"/> when the name is "year"' do
51
+ Locale::DatePart.new(:name => 'year').to_xml.should == '<date-part name="year"/>'
52
+ end
53
+
54
+ it 'returns <date-part name="month" form="numeric" prefix="-"/> for a numeric month with prefix "-"' do
55
+ Locale::DatePart.new(:name => 'month', :form => 'numeric', :prefix => '-').to_xml.should match(/(\s(name|form|prefix)="[^"]+"){3}/)
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+
62
+
63
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ module CSL
4
+ describe Locale::StyleOptions do
5
+
6
+ it { should_not be nil }
7
+
8
+ it 'punctuation-in-quote is false by default' do
9
+ subject[:'punctuation-in-quote'].should be false
10
+ end
11
+
12
+ describe '#to_xml' do
13
+ it 'returns <style-options punctuation-in-quote="false"/> by default' do
14
+ subject.to_xml.should == '<style-options punctuation-in-quote="false"/>'
15
+ end
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+
3
+ module CSL
4
+ describe Locale::Terms do
5
+
6
+ it { should_not be nil }
7
+
8
+ describe '#to_xml' do
9
+ it 'returns <terms/> by default' do
10
+ subject.to_xml.should == '<terms/>'
11
+ end
12
+ end
13
+
14
+ end
15
+
16
+ describe Locale::Term do
17
+
18
+ it { should_not be_nil }
19
+
20
+ it { should_not be_gendered }
21
+
22
+ it { should be_neutral }
23
+
24
+ it 'is not a textnode by default' do
25
+ subject.should_not be_textnode
26
+ end
27
+
28
+ it 'is a textnode when the text is "foo"' do
29
+ Locale::Term.new { |t| t.text = 'foo' }.should be_textnode
30
+ end
31
+
32
+ describe 'gender attribute is set' do
33
+ let(:m) { Locale::Term.new(:name => 'month-05') { |t| t.masculine!; t.text = 'Mai' } }
34
+ let(:f) { Locale::Term.new(:name => 'edition') { |t| t.feminine!; t.text = 'Ausgabe' } }
35
+
36
+ it 'is gendered' do
37
+ m.should be_gendered
38
+ f.should be_gendered
39
+ end
40
+
41
+ it 'is feminine or masculine' do
42
+ m.should be_masculine
43
+ f.should be_feminine
44
+ end
45
+
46
+ it 'is not neutral' do
47
+ m.should_not be_neutral
48
+ f.should_not be_neutral
49
+ end
50
+
51
+ describe '#to_xml' do
52
+ it 'contains the correct gender' do
53
+ m.to_xml.should =~ /gender="masculine"/
54
+ f.to_xml.should =~ /gender="feminine"/
55
+ end
56
+ end
57
+
58
+ describe '#match?' do
59
+ it 'matches the name when passed a string' do
60
+ m.matches?('month-05').should be_true
61
+ end
62
+
63
+ it 'matches the name when passed a pattern' do
64
+ m.matches?(/month-\d\d/).should be_true
65
+ end
66
+
67
+ it 'does not match when passed a matching hash without gender' do
68
+ f.matches?(:name => 'edition').should_not be_true
69
+ end
70
+
71
+ it 'does not match when passed a matching hash with wrong gender' do
72
+ f.matches?(:name => 'edition', :gender => 'masculine').should_not be_true
73
+ end
74
+
75
+ it 'matches when passed a matching hash with matching gender' do
76
+ f.matches?(:name => 'edition', :gender => 'feminine').should be_true
77
+ end
78
+ end
79
+ end
80
+
81
+ describe '#to_xml' do
82
+ it 'returns <term/> by default' do
83
+ subject.to_xml.should == '<term/>'
84
+ end
85
+
86
+ it 'returns <term>foo</term> when the text is "foo"' do
87
+ Locale::Term.new { |t| t.text = 'foo' }.to_xml.should == '<term>foo</term>'
88
+ end
89
+
90
+ it 'returns <term><multiple>foo</multiple></term> when multiple is "foo"' do
91
+ Locale::Term.new { |t| t.multiple = 'foo' }.to_xml.should == '<term><multiple>foo</multiple></term>'
92
+ end
93
+
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,128 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ module CSL
6
+
7
+ describe Locale do
8
+
9
+ let(:locale) { Locale.new }
10
+
11
+ let(:en) { Locale.new('en-US') }
12
+ let(:de) { Locale.new('de-DE') }
13
+ let(:fr) { Locale.new('fr-FR') }
14
+
15
+ describe '.regions' do
16
+
17
+ it 'returns the default region when passed a language symbol' do
18
+ Locale.regions[:en].should == :US
19
+ end
20
+
21
+ end
22
+
23
+ describe '.languages' do
24
+
25
+ describe 'the language hash' do
26
+ it 'returns the default language when passed a region string' do
27
+ %w{ US en GB en AT de DE de }.map(&:to_sym).each_slice(2) do |region, language|
28
+ Locale.languages[region].should == language
29
+ end
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ describe '.new' do
36
+ it { should_not be_nil }
37
+
38
+ it 'defaults to default language' do
39
+ Locale.new.language.should == Locale.default.split(/-/)[0].to_sym
40
+ end
41
+
42
+ it 'defaults to default region' do
43
+ Locale.new.region.should == Locale.default.split(/-/)[1].to_sym
44
+ end
45
+
46
+ it 'contains no dates by default' do
47
+ Locale.new.dates.should be_nil
48
+ end
49
+
50
+ it 'contains no terms by default' do
51
+ Locale.new.terms.should be_nil
52
+ end
53
+
54
+ end
55
+
56
+ describe '.load' do
57
+
58
+ describe 'when called with "en-GB" ' do
59
+ let(:locale) { Locale.load('en-GB') }
60
+
61
+ it 'the returned locale has the correct IETF tag' do
62
+ locale.to_s.should == 'en-GB'
63
+ end
64
+
65
+ it 'the locale has language :en' do
66
+ locale.language.should == :en
67
+ end
68
+
69
+ it 'the locale has region :GB' do
70
+ locale.region.should == :GB
71
+ end
72
+
73
+ end
74
+
75
+ end
76
+
77
+ describe '#set' do
78
+
79
+ it 'when passed "en-GB" sets language to :en and region to :GB' do
80
+ locale.set('en-GB')
81
+ [locale.language, locale.region].should == [:en, :GB]
82
+ end
83
+
84
+ it 'when passed "de" sets language to :de and region to :DE' do
85
+ locale.set('de')
86
+ [locale.language, locale.region].should == [:de, :DE]
87
+ end
88
+
89
+ it 'when passed "-AT" sets language to :de and region to :AT' do
90
+ locale.set('-AT')
91
+ [locale.language, locale.region].should == [:de, :AT]
92
+ end
93
+
94
+ end
95
+
96
+ describe '#legacy?' do
97
+ it 'returns false by default' do
98
+ locale.should_not be_legacy
99
+ end
100
+
101
+ it 'returns true if the version is less than 1.0.1' do
102
+ locale.version = '1.0'
103
+ locale.should be_legacy
104
+ end
105
+ end
106
+
107
+ describe '#ordinalize_query_for' do
108
+
109
+ it 'returns { :name => "ordinal-%02d" } by default' do
110
+ locale.send(:ordinalize_query_for, nil).should == { :name => "ordinal-%02d" }
111
+ end
112
+
113
+ it 'returns { :name => "ordinal-%02d" } for { :form => :short }' do
114
+ locale.send(:ordinalize_query_for, { :form => :short }).should == { :name => "ordinal-%02d" }
115
+ end
116
+
117
+ it 'returns { :name => "long-ordinal-%02d" } for { :form => :long }' do
118
+ locale.send(:ordinalize_query_for, { :form => :long }).should == { :name => "long-ordinal-%02d" }
119
+ end
120
+
121
+ it 'returns { :name => "ordinal-%02d", :"gender-form" => "feminine" } for { :gender => :feminine }' do
122
+ locale.send(:ordinalize_query_for, { :gender => :feminine }).should == { :name => "ordinal-%02d", :'gender-form' => 'feminine' }
123
+ end
124
+
125
+ end
126
+
127
+ end
128
+ end
@@ -0,0 +1,100 @@
1
+ require 'spec_helper'
2
+
3
+ module CSL
4
+
5
+ describe Node do
6
+
7
+ it { should_not be nil }
8
+ it { should_not have_children }
9
+ it { should_not have_attributes }
10
+
11
+ describe 'given a FooBarNode with attributes :foo and :bar and a TestNode without defined attributes' do
12
+ before(:all) do
13
+ class FooBarNode < Node
14
+ attr_struct :foo, :bar
15
+ end
16
+ class TestNode < Node
17
+ end
18
+ end
19
+
20
+ it 'creates FooBarNode::Attributes' do
21
+ FooBarNode.const_defined?(:Attributes).should be_true
22
+ end
23
+
24
+ it 'does not create TestNode::Attributes' do
25
+ TestNode.const_defined?(:Attributes).should_not be_true
26
+ end
27
+
28
+ it 'TestNode attributes are a regular Hash' do
29
+ TestNode.new.attributes.should be_a(Hash)
30
+ end
31
+
32
+ it 'FooBarNode attributes are a Struct' do
33
+ FooBarNode.new.attributes.should be_a(Struct)
34
+ end
35
+
36
+ describe '#values_at' do
37
+ it 'FooBarNode accepts attribute names' do
38
+ FooBarNode.new(:foo => 'Foo', :bar => 'Bar').values_at(:bar, :foo).should == %w{ Bar Foo }
39
+ end
40
+
41
+ it 'TestNode accepts attribute names' do
42
+ TestNode.new(:foo => 'Foo', :bar => 'Bar').values_at(:bar, :foo).should == %w{ Bar Foo }
43
+ end
44
+ end
45
+
46
+ describe '#to_a' do
47
+ it 'returns an empty list by default' do
48
+ Node.new.attributes.to_a.should == []
49
+ end
50
+
51
+ it 'TestNode returns an empty list by default' do
52
+ TestNode.new.attributes.to_a.should == []
53
+ end
54
+
55
+ # it 'TestNode returns a list of all key/value pairs' do
56
+ # TestNode.new(:foo => 'Foo', :bar => 'Bar').attributes.to_a.map(&:last).sort.should == %w{ Bar Foo }
57
+ # end
58
+
59
+ # it 'FooBarNode returns an empty list by default' do
60
+ # FooBarNode.new.attributes.to_a.should == []
61
+ # end
62
+
63
+ # it 'FooBarNode returns a list of all key/value pairs' do
64
+ # FooBarNode.new(:foo => 'Foo', :bar => 'Bar').attributes.to_a.map(&:last).sort.should == %w{ Bar Foo }
65
+ # end
66
+ end
67
+
68
+ describe 'attributes.keys' do
69
+ it 'returns all attribute names as symbols' do
70
+ TestNode.new.attributes.keys.should be_empty
71
+ FooBarNode.new.attributes.keys.should == [:foo, :bar]
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ describe TextNode do
78
+
79
+ it { should_not be nil }
80
+ it { should_not have_children }
81
+ it { should_not have_attributes }
82
+
83
+ describe '.new' do
84
+ it 'accepts a hash of attributes' do
85
+ TextNode.new(:foo => 'bar').should have_attributes
86
+ end
87
+
88
+ it 'yields itself to the optional block' do
89
+ TextNode.new { |n| n.text = 'foo' }.text.should == 'foo'
90
+ end
91
+
92
+ it 'accepts hash and yields itself to the optional block' do
93
+ TextNode.new(:foo => 'bar') { |n| n.text = 'foo' }.to_xml.should == '<text-node foo="bar">foo</text-node>'
94
+ end
95
+
96
+ end
97
+
98
+ end
99
+
100
+ end