csl 1.0.0.pre11 → 1.0.0.pre12

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.
@@ -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: