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.
@@ -195,8 +195,10 @@ module CSL
195
195
  self
196
196
  end
197
197
 
198
- def translate(query)
199
- terms[query]
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
 
@@ -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
- term = registry[name].detect { |t| t.match?(options) }
28
- return term unless term.nil? && options.delete(:'gender-form')
29
-
30
- registry[name].detect { |t| t.match?(options) }
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
- not attributes.gender.blank?
169
+ !attributes.gender.blank?
166
170
  end
167
171
 
168
172
  def neutral?
169
- not gendered?
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
- not text.blank?
185
+ !text.blank?
174
186
  end
175
187
 
176
188
  def singularize
@@ -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 idenifying valid keys (similar to Hash#values_at).
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
- super(*arguments.flatten.map { |k| k.is_a?(Symbol) ? keys.index(k) : k })
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
  })
@@ -1,3 +1,3 @@
1
1
  module CSL
2
- VERSION = '1.0.0.pre11'.freeze
2
+ VERSION = '1.0.0.pre12'.freeze
3
3
  end
@@ -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
@@ -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.pre11
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: 2012-10-05 00:00:00.000000000 Z
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: -1272288240557992685
186
+ hash: 1070711312713509519
187
187
  required_rubygems_version: !ruby/object:Gem::Requirement
188
188
  none: false
189
189
  requirements: