csl 1.0.0.pre11 → 1.0.0.pre12
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/csl/locale.rb +4 -2
- data/lib/csl/locale/term.rb +26 -14
- data/lib/csl/node.rb +8 -2
- data/lib/csl/version.rb +1 -1
- data/spec/csl/locale/term_spec.rb +33 -0
- data/spec/csl/node_spec.rb +72 -24
- metadata +3 -3
data/lib/csl/locale.rb
CHANGED
@@ -195,8 +195,10 @@ module CSL
|
|
195
195
|
self
|
196
196
|
end
|
197
197
|
|
198
|
-
|
199
|
-
|
198
|
+
# @return [String, nil] the term's translation
|
199
|
+
def translate(name, options = {})
|
200
|
+
term = terms.lookup name, options
|
201
|
+
term && term.to_s(options)
|
200
202
|
end
|
201
203
|
alias t translate
|
202
204
|
|
data/lib/csl/locale/term.rb
CHANGED
@@ -21,16 +21,20 @@ module CSL
|
|
21
21
|
|
22
22
|
alias each each_child
|
23
23
|
|
24
|
+
# @return [Term, nil] the first term that matches the query
|
24
25
|
def lookup(name, options = {})
|
25
26
|
options[:name] = name = name.to_s
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
registry[name].detect { |t| t.match?(
|
28
|
+
# specialize search conditions
|
29
|
+
conditions = options.select { |k,_| Term::Attributes.keys.include?(k.to_sym) }
|
30
|
+
|
31
|
+
term = registry[name].detect { |t| t.match?(conditions) }
|
32
|
+
return term unless term.nil? && conditions.delete(:'gender-form')
|
33
|
+
|
34
|
+
registry[name].detect { |t| t.match?(conditions) }
|
31
35
|
end
|
32
36
|
alias [] lookup
|
33
|
-
|
37
|
+
|
34
38
|
def ordinalize_modulo(number, divisor, options = {})
|
35
39
|
ordinal = ordinalize(number, options)
|
36
40
|
return unless ordinal && ordinal.match_modulo?(divisor)
|
@@ -39,21 +43,21 @@ module CSL
|
|
39
43
|
|
40
44
|
def ordinalize(number, options = {})
|
41
45
|
return unless has_ordinals?
|
42
|
-
|
46
|
+
|
43
47
|
if number == :default
|
44
48
|
options[:name] = 'ordinal'
|
45
49
|
else
|
46
50
|
options[:name] = 'ordinal-%02d' % number
|
47
51
|
end
|
48
|
-
|
52
|
+
|
49
53
|
if options[:form].to_s =~ /^long/i
|
50
54
|
options.delete :form
|
51
55
|
options[:name][0,0] = 'long-'
|
52
56
|
end
|
53
|
-
|
57
|
+
|
54
58
|
ordinal = ordinals[number].detect { |t| t.match?(options) }
|
55
59
|
return ordinal unless ordinal.nil? && options.delete(:'gender-form')
|
56
|
-
|
60
|
+
|
57
61
|
ordinals[number].detect { |t| t.match?(options) }
|
58
62
|
end
|
59
63
|
|
@@ -70,7 +74,7 @@ module CSL
|
|
70
74
|
def has_legacy_ordinals?
|
71
75
|
has_ordinals? && !ordinals.key?(:default)
|
72
76
|
end
|
73
|
-
|
77
|
+
|
74
78
|
def drop_ordinals
|
75
79
|
tmp = ordinals.values.flatten(1)
|
76
80
|
ordinals.clear
|
@@ -113,7 +117,7 @@ module CSL
|
|
113
117
|
registry[term[:name]].delete(term)
|
114
118
|
end
|
115
119
|
end
|
116
|
-
|
120
|
+
|
117
121
|
end
|
118
122
|
|
119
123
|
class Term < Node
|
@@ -162,15 +166,23 @@ module CSL
|
|
162
166
|
end
|
163
167
|
|
164
168
|
def gendered?
|
165
|
-
|
169
|
+
!attributes.gender.blank?
|
166
170
|
end
|
167
171
|
|
168
172
|
def neutral?
|
169
|
-
|
173
|
+
!gendered?
|
174
|
+
end
|
175
|
+
|
176
|
+
def short?
|
177
|
+
attribute?(:form) && attributes.form.to_s =~ /^short$/i
|
178
|
+
end
|
179
|
+
|
180
|
+
def long?
|
181
|
+
!short?
|
170
182
|
end
|
171
183
|
|
172
184
|
def textnode?
|
173
|
-
|
185
|
+
!text.blank?
|
174
186
|
end
|
175
187
|
|
176
188
|
def singularize
|
data/lib/csl/node.rb
CHANGED
@@ -183,7 +183,7 @@ module CSL
|
|
183
183
|
# Returns an array containing the attributes in self according
|
184
184
|
# to the given selector(s). The selectors may be either integer
|
185
185
|
# indices, ranges (functionality inherited from Struct) or
|
186
|
-
# symbols
|
186
|
+
# symbols identifying valid keys (similar to Hash#values_at).
|
187
187
|
#
|
188
188
|
# @example
|
189
189
|
# attributes.values_at(:family, :nick) #=> ['Matsumoto', 'Matz']
|
@@ -191,7 +191,13 @@ module CSL
|
|
191
191
|
# @see Struct#values_at
|
192
192
|
# @return [Array] the list of values
|
193
193
|
def values_at(*arguments)
|
194
|
-
|
194
|
+
arguments.flatten.inject([]) do |values, key|
|
195
|
+
if key.is_a?(Symbol)
|
196
|
+
values.push fetch(key)
|
197
|
+
else
|
198
|
+
values.concat super(key)
|
199
|
+
end
|
200
|
+
end
|
195
201
|
end
|
196
202
|
|
197
203
|
})
|
data/lib/csl/version.rb
CHANGED
@@ -36,8 +36,41 @@ module CSL
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
39
|
+
|
39
40
|
end
|
40
41
|
|
42
|
+
describe '#lookup' do
|
43
|
+
|
44
|
+
describe "given standard English terms" do
|
45
|
+
let(:en) do
|
46
|
+
Locale::Terms.parse <<-EOS
|
47
|
+
<terms>
|
48
|
+
<term name="page" form="short">
|
49
|
+
<single>p.</single>
|
50
|
+
<multiple>pp.</multiple>
|
51
|
+
</term>
|
52
|
+
<term name="page">
|
53
|
+
<single>page</single>
|
54
|
+
<multiple>pages</multiple>
|
55
|
+
</term>
|
56
|
+
</terms>
|
57
|
+
EOS
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'returns nil if there is no matching term' do
|
61
|
+
en.lookup(:foo).should be_nil
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'returns the first matching form by default' do
|
65
|
+
en.lookup(:page).should be_short
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'ignores irrelevant options' do
|
69
|
+
en.lookup(:page, :plural => true).should_not be_nil
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
41
74
|
end
|
42
75
|
|
43
76
|
describe Locale::Term do
|
data/spec/csl/node_spec.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
module CSL
|
4
|
-
|
4
|
+
|
5
5
|
describe Node do
|
6
6
|
|
7
7
|
it { should_not be nil }
|
8
8
|
it { should_not have_children }
|
9
9
|
it { should_not have_attributes }
|
10
|
-
|
10
|
+
|
11
11
|
describe 'given a FooBarNode with attributes :foo and :bar and a TestNode without defined attributes' do
|
12
12
|
before(:all) do
|
13
13
|
class FooBarNode < Node
|
@@ -16,15 +16,15 @@ module CSL
|
|
16
16
|
class TestNode < Node
|
17
17
|
end
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
it 'creates FooBarNode::Attributes' do
|
21
21
|
FooBarNode.const_defined?(:Attributes).should be_true
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
it 'does not create TestNode::Attributes' do
|
25
25
|
TestNode.const_defined?(:Attributes).should_not be_true
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
it 'TestNode attributes are a regular Hash' do
|
29
29
|
TestNode.new.attributes.should be_a(Hash)
|
30
30
|
end
|
@@ -32,21 +32,65 @@ module CSL
|
|
32
32
|
it 'FooBarNode attributes are a Struct' do
|
33
33
|
FooBarNode.new.attributes.should be_a(Struct)
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
|
+
describe '#match?' do
|
37
|
+
it 'matches an empty query' do
|
38
|
+
FooBarNode.new.match?({}).should be_true
|
39
|
+
FooBarNode.new(:foo => 'Foo').match?({}).should be_true
|
40
|
+
TestNode.new.match?({}).should be_true
|
41
|
+
TestNode.new(:foo => 'Foo').match?({}).should be_true
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'returns true for a matching query' do
|
45
|
+
FooBarNode.new(:foo => 'bar').match?(:foo => 'bar').should be_true
|
46
|
+
FooBarNode.new(:bar => 'b', :foo => 'f').match?(:foo => 'f', :bar => 'b').should be_true
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'returns false for non-matching query' do
|
50
|
+
FooBarNode.new.match?(:foo => 'bar').should be_false
|
51
|
+
FooBarNode.new(:foo => 'f').match?(:foo => 'f', :bar => 'b').should be_false
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'returns false if the query contains unknown attributes' do
|
55
|
+
FooBarNode.new(:foo => 'f').match?(:foo => 'f', :unknown => 'u').should be_false
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'matches irrespective of order' do
|
59
|
+
FooBarNode.new(:bar => 'b', :foo => 'f').match?(:foo => 'f', :bar => 'b').should be_true
|
60
|
+
FooBarNode.new(:foo => 'f', :bar => 'b').match?(:foo => 'f', :bar => 'b').should be_true
|
61
|
+
FooBarNode.new(:foo => 'f', :bar => 'b').match?(:bar => 'b', :foo => 'f').should be_true
|
62
|
+
FooBarNode.new(:bar => 'b', :foo => 'f').match?(:bar => 'b', :foo => 'f').should be_true
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'matches an empty query with the correct node name' do
|
66
|
+
FooBarNode.new.match?('foo-bar-node', {}).should be_true
|
67
|
+
FooBarNode.new(:foo => 'Foo').match?('foo-bar-node', {}).should be_true
|
68
|
+
TestNode.new.match?('test-node', {}).should be_true
|
69
|
+
TestNode.new(:foo => 'Foo').match?('test-node', {}).should be_true
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'does not match other node names' do
|
73
|
+
FooBarNode.new.match?(:name, {}).should_not be_true
|
74
|
+
FooBarNode.new(:foo => 'Foo').match?(:name, {}).should_not be_true
|
75
|
+
TestNode.new.match?(:name, {}).should_not be_true
|
76
|
+
TestNode.new(:foo => 'Foo').match?(:name, {}).should_not be_true
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
36
80
|
describe '#attributes_for' do
|
37
81
|
it 'returns an empty hash when there no attributes are set' do
|
38
82
|
TestNode.new.attributes_for.should be_empty
|
39
83
|
TestNode.new.attributes_for(:x, :y).should be_empty
|
40
|
-
|
84
|
+
|
41
85
|
FooBarNode.new.attributes_for.should be_empty
|
42
86
|
FooBarNode.new.attributes_for(:x, :y).should be_empty
|
43
87
|
FooBarNode.new.attributes_for(:foo, :bar).should be_empty
|
44
88
|
end
|
45
|
-
|
89
|
+
|
46
90
|
it 'returns an empty hash when no attributes match the filter' do
|
47
91
|
TestNode.new(:foo => 'foo').attributes_for.should be_empty
|
48
92
|
TestNode.new(:foo => 'foo').attributes_for(:x, :y).should be_empty
|
49
|
-
|
93
|
+
|
50
94
|
FooBarNode.new(:foo => 'foo').attributes_for.should be_empty
|
51
95
|
FooBarNode.new(:foo => 'foo').attributes_for(:x, :y).should be_empty
|
52
96
|
end
|
@@ -56,33 +100,37 @@ module CSL
|
|
56
100
|
FooBarNode.new(:foo => 'foo', :bar => 'bar').attributes_for(:x, :foo).should == { :foo => 'foo' }
|
57
101
|
end
|
58
102
|
end
|
59
|
-
|
103
|
+
|
60
104
|
describe '#formatting_options' do
|
61
105
|
it 'returns an empty hash by default' do
|
62
106
|
TestNode.new.formatting_options.should be_empty
|
63
107
|
FooBarNode.new.formatting_options.should be_empty
|
64
108
|
end
|
65
|
-
|
109
|
+
|
66
110
|
it 'returns an empty hash if there are no formatting attributes' do
|
67
111
|
TestNode.new(:foo => 'foo', :bar => 'bar').formatting_options.should be_empty
|
68
112
|
FooBarNode.new(:foo => 'foo', :bar => 'bar').formatting_options.should be_empty
|
69
113
|
end
|
70
|
-
|
114
|
+
|
71
115
|
it "returns a hash of the node's formatting attributes" do
|
72
116
|
TestNode.new(:foo => 'foo', :'font-style' => 'italic').formatting_options.should == { :'font-style' => 'italic' }
|
73
117
|
end
|
74
118
|
end
|
75
|
-
|
119
|
+
|
76
120
|
describe '#values_at' do
|
77
121
|
it 'FooBarNode accepts attribute names' do
|
78
122
|
FooBarNode.new(:foo => 'Foo', :bar => 'Bar').values_at(:bar, :foo).should == %w{ Bar Foo }
|
123
|
+
FooBarNode.new(:foo => 'Foo').values_at(:bar, :foo).should == [nil, 'Foo']
|
124
|
+
FooBarNode.new(:foo => 'Foo').values_at(:unknown, :foo).should == [nil, 'Foo']
|
79
125
|
end
|
80
|
-
|
126
|
+
|
81
127
|
it 'TestNode accepts attribute names' do
|
82
128
|
TestNode.new(:foo => 'Foo', :bar => 'Bar').values_at(:bar, :foo).should == %w{ Bar Foo }
|
129
|
+
TestNode.new(:foo => 'Foo').values_at(:bar, :foo).should == [nil, 'Foo']
|
130
|
+
TestNode.new(:foo => 'Foo').values_at(:unknown, :foo).should == [nil, 'Foo']
|
83
131
|
end
|
84
132
|
end
|
85
|
-
|
133
|
+
|
86
134
|
describe '#to_a' do
|
87
135
|
it 'returns an empty list by default' do
|
88
136
|
Node.new.attributes.to_a.should == []
|
@@ -91,7 +139,7 @@ module CSL
|
|
91
139
|
it 'TestNode returns an empty list by default' do
|
92
140
|
TestNode.new.attributes.to_a.should == []
|
93
141
|
end
|
94
|
-
|
142
|
+
|
95
143
|
# it 'TestNode returns a list of all key/value pairs' do
|
96
144
|
# TestNode.new(:foo => 'Foo', :bar => 'Bar').attributes.to_a.map(&:last).sort.should == %w{ Bar Foo }
|
97
145
|
# end
|
@@ -99,12 +147,12 @@ module CSL
|
|
99
147
|
# it 'FooBarNode returns an empty list by default' do
|
100
148
|
# FooBarNode.new.attributes.to_a.should == []
|
101
149
|
# end
|
102
|
-
|
150
|
+
|
103
151
|
# it 'FooBarNode returns a list of all key/value pairs' do
|
104
152
|
# FooBarNode.new(:foo => 'Foo', :bar => 'Bar').attributes.to_a.map(&:last).sort.should == %w{ Bar Foo }
|
105
153
|
# end
|
106
154
|
end
|
107
|
-
|
155
|
+
|
108
156
|
describe 'attributes.keys' do
|
109
157
|
it 'returns all attribute names as symbols' do
|
110
158
|
TestNode.new.attributes.keys.should be_empty
|
@@ -115,28 +163,28 @@ module CSL
|
|
115
163
|
end
|
116
164
|
|
117
165
|
describe TextNode do
|
118
|
-
|
166
|
+
|
119
167
|
it { should_not be nil }
|
120
168
|
it { should_not have_children }
|
121
169
|
it { should_not have_attributes }
|
122
|
-
|
170
|
+
|
123
171
|
describe '.new' do
|
124
172
|
it 'accepts a hash of attributes' do
|
125
173
|
TextNode.new(:foo => 'bar').should have_attributes
|
126
174
|
end
|
127
|
-
|
175
|
+
|
128
176
|
it 'yields itself to the optional block' do
|
129
177
|
TextNode.new { |n| n.text = 'foo' }.text.should == 'foo'
|
130
178
|
end
|
131
|
-
|
179
|
+
|
132
180
|
it 'accepts hash and yields itself to the optional block' do
|
133
181
|
TextNode.new(:foo => 'bar') { |n| n.text = 'foo' }.to_xml.should == '<text-node foo="bar">foo</text-node>'
|
134
182
|
end
|
135
183
|
end
|
136
|
-
|
184
|
+
|
137
185
|
describe '#pretty_print' do
|
138
186
|
TextNode.new(:foo => 'bar') { |n| n.text = 'foo' }.pretty_print.should == '<text-node foo="bar">foo</text-node>'
|
139
187
|
end
|
140
188
|
end
|
141
|
-
|
189
|
+
|
142
190
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: csl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.pre12
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-01-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: namae
|
@@ -183,7 +183,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
183
183
|
version: '0'
|
184
184
|
segments:
|
185
185
|
- 0
|
186
|
-
hash:
|
186
|
+
hash: 1070711312713509519
|
187
187
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
188
188
|
none: false
|
189
189
|
requirements:
|