jordanyeo-simple-navigation 3.11.0

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 (52) hide show
  1. data/CHANGELOG +265 -0
  2. data/Gemfile +17 -0
  3. data/README +22 -0
  4. data/Rakefile +47 -0
  5. data/VERSION +1 -0
  6. data/generators/navigation_config/USAGE +1 -0
  7. data/generators/navigation_config/navigation_config_generator.rb +8 -0
  8. data/generators/navigation_config/templates/config/navigation.rb +76 -0
  9. data/lib/generators/navigation_config/navigation_config_generator.rb +12 -0
  10. data/lib/simple-navigation.rb +1 -0
  11. data/lib/simple_navigation.rb +167 -0
  12. data/lib/simple_navigation/adapters.rb +10 -0
  13. data/lib/simple_navigation/adapters/base.rb +37 -0
  14. data/lib/simple_navigation/adapters/nanoc.rb +45 -0
  15. data/lib/simple_navigation/adapters/padrino.rb +20 -0
  16. data/lib/simple_navigation/adapters/rails.rb +93 -0
  17. data/lib/simple_navigation/adapters/sinatra.rb +69 -0
  18. data/lib/simple_navigation/core.rb +5 -0
  19. data/lib/simple_navigation/core/configuration.rb +72 -0
  20. data/lib/simple_navigation/core/item.rb +144 -0
  21. data/lib/simple_navigation/core/item_adapter.rb +63 -0
  22. data/lib/simple_navigation/core/item_container.rb +147 -0
  23. data/lib/simple_navigation/core/items_provider.rb +35 -0
  24. data/lib/simple_navigation/rails_controller_methods.rb +144 -0
  25. data/lib/simple_navigation/rendering.rb +12 -0
  26. data/lib/simple_navigation/rendering/helpers.rb +123 -0
  27. data/lib/simple_navigation/rendering/renderer/base.rb +107 -0
  28. data/lib/simple_navigation/rendering/renderer/breadcrumbs.rb +59 -0
  29. data/lib/simple_navigation/rendering/renderer/json.rb +29 -0
  30. data/lib/simple_navigation/rendering/renderer/links.rb +32 -0
  31. data/lib/simple_navigation/rendering/renderer/list.rb +29 -0
  32. data/lib/simple_navigation/rendering/renderer/text.rb +26 -0
  33. data/rails/init.rb +1 -0
  34. data/spec/lib/simple_navigation/adapters/padrino_spec.rb +31 -0
  35. data/spec/lib/simple_navigation/adapters/rails_spec.rb +287 -0
  36. data/spec/lib/simple_navigation/adapters/sinatra_spec.rb +80 -0
  37. data/spec/lib/simple_navigation/core/configuration_spec.rb +128 -0
  38. data/spec/lib/simple_navigation/core/item_adapter_spec.rb +212 -0
  39. data/spec/lib/simple_navigation/core/item_container_spec.rb +451 -0
  40. data/spec/lib/simple_navigation/core/item_spec.rb +566 -0
  41. data/spec/lib/simple_navigation/core/items_provider_spec.rb +60 -0
  42. data/spec/lib/simple_navigation/rails_controller_methods_spec.rb +249 -0
  43. data/spec/lib/simple_navigation/rendering/helpers_spec.rb +276 -0
  44. data/spec/lib/simple_navigation/rendering/renderer/base_spec.rb +199 -0
  45. data/spec/lib/simple_navigation/rendering/renderer/breadcrumbs_spec.rb +101 -0
  46. data/spec/lib/simple_navigation/rendering/renderer/json_spec.rb +48 -0
  47. data/spec/lib/simple_navigation/rendering/renderer/links_spec.rb +64 -0
  48. data/spec/lib/simple_navigation/rendering/renderer/list_spec.rb +211 -0
  49. data/spec/lib/simple_navigation/rendering/renderer/text_spec.rb +41 -0
  50. data/spec/lib/simple_navigation_spec.rb +307 -0
  51. data/spec/spec_helper.rb +108 -0
  52. metadata +199 -0
@@ -0,0 +1,29 @@
1
+ module SimpleNavigation
2
+ module Renderer
3
+
4
+ # Renders the navigation items as a object tree serialized as a json string, can also output raw ruby Hashes
5
+ class Json < SimpleNavigation::Renderer::Base
6
+
7
+ def render(item_container)
8
+ results = hash_render(item_container)
9
+ results = results.to_json unless options[:as_hash]
10
+ results
11
+ end
12
+
13
+ private
14
+
15
+ def hash_render(item_container)
16
+ return nil if item_container.nil?
17
+ item_container.items.map do |item|
18
+ item_hash = {
19
+ :name => item.name,
20
+ :url => item.url,
21
+ :selected => item.selected?,
22
+ :items => hash_render(item.sub_navigation)
23
+ }
24
+ end
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,32 @@
1
+ module SimpleNavigation
2
+ module Renderer
3
+
4
+ # Renders an ItemContainer as a <div> element and its containing items as <a> elements.
5
+ # It adds the 'selected' class to the <a> element that is currently active.
6
+ #
7
+ # The Links renderer cannot be used to render nested navigations. If you would like it to use with nested navigations, you have to render each level separately.
8
+ #
9
+ # By default, the renderer sets the item's key as dom_id for the rendered <a> element unless the config option <tt>autogenerate_item_ids</tt> is set to false.
10
+ # The id can also be explicitely specified by setting the id in the html-options of the 'item' method in the config/navigation.rb file.
11
+ # The ItemContainer's dom_class and dom_id are applied to the surrounding <div> element.
12
+ #
13
+ class Links < SimpleNavigation::Renderer::Base
14
+ def render(item_container)
15
+ div_content = item_container.items.inject([]) do |list, item|
16
+ list << tag_for(item)
17
+ end.join(join_with)
18
+ content_tag(:div, div_content, {:id => item_container.dom_id, :class => item_container.dom_class})
19
+ end
20
+
21
+ protected
22
+
23
+ def join_with
24
+ @join_with ||= options[:join_with] || ""
25
+ end
26
+
27
+ def options_for(item)
28
+ {:method => item.method}.merge(item.html_options)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,29 @@
1
+ module SimpleNavigation
2
+ module Renderer
3
+
4
+ # Renders an ItemContainer as a <ul> element and its containing items as <li> elements.
5
+ # It adds the 'selected' class to li element AND the link inside the li element that is currently active.
6
+ #
7
+ # If the sub navigation should be included (based on the level and expand_all options), it renders another <ul> containing the sub navigation inside the active <li> element.
8
+ #
9
+ # By default, the renderer sets the item's key as dom_id for the rendered <li> element unless the config option <tt>autogenerate_item_ids</tt> is set to false.
10
+ # The id can also be explicitely specified by setting the id in the html-options of the 'item' method in the config/navigation.rb file.
11
+ class List < SimpleNavigation::Renderer::Base
12
+ def render(item_container)
13
+ list_content = item_container.items.inject([]) do |list, item|
14
+ li_options = item.html_options.reject {|k, v| k == :link}
15
+ li_content = tag_for(item)
16
+ if include_sub_navigation?(item)
17
+ li_content << render_sub_navigation_for(item)
18
+ end
19
+ list << content_tag(:li, li_content, li_options)
20
+ end.join
21
+ if skip_if_empty? && item_container.empty?
22
+ ''
23
+ else
24
+ content_tag((options[:ordered] ? :ol : :ul), list_content , {:id => item_container.dom_id, :class => item_container.dom_class})
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,26 @@
1
+ module SimpleNavigation
2
+ module Renderer
3
+
4
+ # Renders the 'chain' of selected navigation items as simple text items, joined with an optional separator (similar to breadcrumbs, but without markup).
5
+ #
6
+ class Text < SimpleNavigation::Renderer::Base
7
+
8
+ def render(item_container)
9
+ list(item_container).compact.join(options[:join_with] || " ")
10
+ end
11
+
12
+ private
13
+
14
+ def list(item_container)
15
+ item_container.items.inject([]) do |array, item|
16
+ if item.selected?
17
+ array + [item.name(:apply_generator => false)] + (include_sub_navigation?(item) ? list(item.sub_navigation) : [])
18
+ else
19
+ array
20
+ end
21
+ end
22
+ end
23
+
24
+ end
25
+ end
26
+ end
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ SimpleNavigation.register
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleNavigation::Adapters::Padrino do
4
+
5
+ def create_adapter
6
+ SimpleNavigation::Adapters::Padrino.new(@context)
7
+ end
8
+
9
+ before(:each) do
10
+ @request = stub(:request)
11
+ @content = stub(:content)
12
+ @context = stub(:context, :request => @request)
13
+ @adapter = create_adapter
14
+ end
15
+
16
+ describe 'link_to' do
17
+ it "should delegate to context" do
18
+ @context.should_receive(:link_to).with('name', 'url', :my_option => true)
19
+ @adapter.link_to('name', 'url', :my_option => true)
20
+ end
21
+ end
22
+
23
+ describe 'content_tag' do
24
+ it "should delegate to context" do
25
+ @content.should_receive(:html_safe).and_return('content')
26
+ @context.should_receive(:content_tag).with('type', 'content', :my_option => true)
27
+ @adapter.content_tag('type', @content, :my_option => true)
28
+ end
29
+ end
30
+
31
+ end
@@ -0,0 +1,287 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleNavigation::Adapters::Rails do
4
+
5
+ def create_adapter
6
+ SimpleNavigation::Adapters::Rails.new(@context)
7
+ end
8
+
9
+ before(:each) do
10
+ @context = stub(:context)
11
+ @controller = stub(:controller)
12
+ @context.stub!(:controller => @controller)
13
+ @request = stub(:request)
14
+ @template = stub(:template, :request => @request)
15
+ @adapter = create_adapter
16
+ end
17
+
18
+ describe 'self.register' do
19
+ before(:each) do
20
+ ActionController::Base.stub!(:include)
21
+ end
22
+ it "should call set_env" do
23
+ SimpleNavigation.should_receive(:set_env).with('./', 'test')
24
+ SimpleNavigation.register
25
+ end
26
+ it "should extend the ActionController::Base with the Helpers" do
27
+ ActionController::Base.should_receive(:include).with(SimpleNavigation::Helpers)
28
+ SimpleNavigation.register
29
+ end
30
+ it "should install the helper methods in the controller" do
31
+ ActionController::Base.should_receive(:helper_method).with(:render_navigation)
32
+ ActionController::Base.should_receive(:helper_method).with(:active_navigation_item_name)
33
+ ActionController::Base.should_receive(:helper_method).with(:active_navigation_item_key)
34
+ ActionController::Base.should_receive(:helper_method).with(:active_navigation_item)
35
+ ActionController::Base.should_receive(:helper_method).with(:active_navigation_item_container)
36
+ SimpleNavigation.register
37
+ end
38
+
39
+ end
40
+
41
+ describe 'initialize' do
42
+ context 'regarding setting the request' do
43
+ context 'template is present' do
44
+ before(:each) do
45
+ @controller.stub!(:instance_variable_get => @template)
46
+ @adapter = create_adapter
47
+ end
48
+ it {@adapter.request.should == @request}
49
+ end
50
+ context 'template is not present' do
51
+ before(:each) do
52
+ @controller.stub!(:instance_variable_get => nil)
53
+ end
54
+ it {@adapter.request.should be_nil}
55
+ end
56
+ end
57
+ context 'regarding setting the controller' do
58
+ it "should set the controller" do
59
+ @adapter.controller.should == @controller
60
+ end
61
+ end
62
+ context 'regarding setting the template' do
63
+ context 'template is stored in controller as instance_var (Rails2)' do
64
+ context 'template is set' do
65
+ before(:each) do
66
+ @controller.stub!(:instance_variable_get => @template)
67
+ @adapter = create_adapter
68
+ end
69
+ it {@adapter.template.should == @template}
70
+ end
71
+ context 'template is not set' do
72
+ before(:each) do
73
+ @controller.stub!(:instance_variable_get => nil)
74
+ @adapter = create_adapter
75
+ end
76
+ it {@adapter.template.should be_nil}
77
+ end
78
+ end
79
+ context 'template is stored in controller as view_context (Rails3)' do
80
+ context 'template is set' do
81
+ before(:each) do
82
+ @controller.stub!(:view_context => @template)
83
+ @adapter = create_adapter
84
+ end
85
+ it {@adapter.template.should == @template}
86
+ end
87
+ context 'template is not set' do
88
+ before(:each) do
89
+ @controller.stub!(:view_context => nil)
90
+ @adapter = create_adapter
91
+ end
92
+ it {@adapter.template.should be_nil}
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+ describe 'request_uri' do
99
+ context 'request is set' do
100
+ context 'fullpath is defined on request' do
101
+ before(:each) do
102
+ @request = stub(:request, :fullpath => '/fullpath')
103
+ @adapter.stub!(:request => @request)
104
+ end
105
+ it {@adapter.request_uri.should == '/fullpath'}
106
+ end
107
+ context 'fullpath is not defined on request' do
108
+ before(:each) do
109
+ @request = stub(:request, :request_uri => '/request_uri')
110
+ @adapter.stub!(:request => @request)
111
+ end
112
+ it {@adapter.request_uri.should == '/request_uri'}
113
+ end
114
+ end
115
+ context 'request is not set' do
116
+ before(:each) do
117
+ @adapter.stub!(:request => nil)
118
+ end
119
+ it {@adapter.request_uri.should == ''}
120
+ end
121
+ end
122
+
123
+ describe 'request_path' do
124
+ context 'request is set' do
125
+ before(:each) do
126
+ @request = stub(:request, :path => '/request_path')
127
+ @adapter.stub!(:request => @request)
128
+ end
129
+ it {@adapter.request_path.should == '/request_path'}
130
+ end
131
+ context 'request is not set' do
132
+ before(:each) do
133
+ @adapter.stub!(:request => nil)
134
+ end
135
+ it {@adapter.request_path.should == ''}
136
+ end
137
+ end
138
+
139
+ describe 'context_for_eval' do
140
+ context 'controller is present' do
141
+ before(:each) do
142
+ @controller = stub(:controller)
143
+ @adapter.instance_variable_set(:@controller, @controller)
144
+ end
145
+ context 'template is present' do
146
+ before(:each) do
147
+ @template = stub(:template)
148
+ @adapter.instance_variable_set(:@template, @template)
149
+ end
150
+ it {@adapter.context_for_eval.should == @template}
151
+ end
152
+ context 'template is not present' do
153
+ before(:each) do
154
+ @adapter.instance_variable_set(:@template, nil)
155
+ end
156
+ it {@adapter.context_for_eval.should == @controller}
157
+ end
158
+ end
159
+ context 'controller is not present' do
160
+ before(:each) do
161
+ @adapter.instance_variable_set(:@controller, nil)
162
+ end
163
+ context 'template is present' do
164
+ before(:each) do
165
+ @template = stub(:template)
166
+ @adapter.instance_variable_set(:@template, @template)
167
+ end
168
+ it {@adapter.context_for_eval.should == @template}
169
+ end
170
+ context 'template is not present' do
171
+ before(:each) do
172
+ @adapter.instance_variable_set(:@template, nil)
173
+ end
174
+ it {lambda {@adapter.context_for_eval}.should raise_error}
175
+ end
176
+ end
177
+ end
178
+
179
+ describe 'current_page?' do
180
+ context 'template is set' do
181
+ before(:each) do
182
+ @adapter.stub!(:template => @template)
183
+ end
184
+ it "should delegate the call to the template" do
185
+ @template.should_receive(:current_page?).with(:page)
186
+ @adapter.current_page?(:page)
187
+ end
188
+ end
189
+ context 'template is not set' do
190
+ before(:each) do
191
+ @adapter.stub!(:template => nil)
192
+ end
193
+ it {@adapter.should_not be_current_page(:page)}
194
+ end
195
+ end
196
+
197
+ describe 'link_to' do
198
+ context 'template is set' do
199
+ before(:each) do
200
+ @adapter.stub!(:template => @template)
201
+ @adapter.stub!(:html_safe => 'safe_text')
202
+ @options = stub(:options)
203
+ end
204
+ it "should delegate the call to the template (with html_safe text)" do
205
+ @template.should_receive(:link_to).with('safe_text', 'url', @options)
206
+ @adapter.link_to('text', 'url', @options)
207
+ end
208
+ end
209
+ context 'template is not set' do
210
+ before(:each) do
211
+ @adapter.stub!(:template => nil)
212
+ end
213
+ it {@adapter.link_to('text', 'url', @options).should be_nil}
214
+ end
215
+ end
216
+
217
+ describe 'content_tag' do
218
+ context 'template is set' do
219
+ before(:each) do
220
+ @adapter.stub!(:template => @template)
221
+ @adapter.stub!(:html_safe => 'safe_text')
222
+ @options = stub(:options)
223
+ end
224
+ it "should delegate the call to the template (with html_safe text)" do
225
+ @template.should_receive(:content_tag).with(:div, 'safe_text', @options)
226
+ @adapter.content_tag(:div, 'text', @options)
227
+ end
228
+ end
229
+ context 'template is not set' do
230
+ before(:each) do
231
+ @adapter.stub!(:template => nil)
232
+ end
233
+ it {@adapter.content_tag(:div, 'text', @options).should be_nil}
234
+ end
235
+ end
236
+
237
+ describe 'self.extract_controller_from' do
238
+ context 'object responds to controller' do
239
+ before(:each) do
240
+ @context.stub!(:controller => @controller)
241
+ end
242
+ it "should return the controller" do
243
+ @adapter.send(:extract_controller_from, @context).should == @controller
244
+ end
245
+ end
246
+ context 'object does not respond to controller' do
247
+ before(:each) do
248
+ @context = stub(:context)
249
+ end
250
+ it "should return the context" do
251
+ @adapter.send(:extract_controller_from, @context).should == @context
252
+ end
253
+ end
254
+ end
255
+
256
+ describe 'html_safe' do
257
+ before(:each) do
258
+ @input = stub :input
259
+ end
260
+ context 'input does respond to html_safe' do
261
+ before(:each) do
262
+ @safe = stub :safe
263
+ @input.stub!(:html_safe => @safe)
264
+ end
265
+ it {@adapter.send(:html_safe, @input).should == @safe}
266
+ end
267
+ context 'input does not respond to html_safe' do
268
+ it {@adapter.send(:html_safe, @input).should == @input}
269
+ end
270
+ end
271
+
272
+ describe 'template_from' do
273
+ context 'Rails3' do
274
+ before(:each) do
275
+ @controller.stub!(:view_context => 'view')
276
+ end
277
+ it {@adapter.send(:template_from, @controller).should == 'view'}
278
+ end
279
+ context 'Rails2' do
280
+ before(:each) do
281
+ @controller.instance_variable_set(:@template, 'view')
282
+ end
283
+ it {@adapter.send(:template_from, @controller).should == 'view'}
284
+ end
285
+ end
286
+
287
+ end
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleNavigation::Adapters::Sinatra do
4
+
5
+ def create_adapter
6
+ SimpleNavigation::Adapters::Sinatra.new(@context)
7
+ end
8
+
9
+ before(:each) do
10
+ @context = stub(:context)
11
+ @request = stub(:request, :fullpath => '/full?param=true', :path => '/full')
12
+ @context.stub!(:request => @request)
13
+ @adapter = create_adapter
14
+ end
15
+
16
+ describe 'context_for_eval' do
17
+ it "should raise error if no context" do
18
+ @adapter.stub!(:context => nil)
19
+ lambda {@adapter.context_for_eval}.should raise_error
20
+ end
21
+ it "should return the context" do
22
+ @adapter.context_for_eval.should == @context
23
+ end
24
+ end
25
+
26
+ describe 'request_uri' do
27
+ it {@adapter.request_uri.should == '/full?param=true'}
28
+ end
29
+
30
+ describe 'request_path' do
31
+ it {@adapter.request_path.should == '/full'}
32
+ end
33
+
34
+ describe 'current_page?' do
35
+ before(:each) do
36
+ @request.stub!(:scheme => 'http', :host_with_port => 'my_host:5000')
37
+ end
38
+
39
+ describe 'when URL is not encoded' do
40
+ it {@adapter.current_page?('/full?param=true').should be_true}
41
+ it {@adapter.current_page?('/full?param3=true').should be_false}
42
+ it {@adapter.current_page?('/full').should be_true}
43
+ it {@adapter.current_page?('http://my_host:5000/full?param=true').should be_true}
44
+ it {@adapter.current_page?('http://my_host:5000/full?param3=true').should be_false}
45
+ it {@adapter.current_page?('http://my_host:5000/full').should be_true}
46
+ it {@adapter.current_page?('https://my_host:5000/full').should be_false}
47
+ it {@adapter.current_page?('http://my_host:6000/full').should be_false}
48
+ it {@adapter.current_page?('http://my_other_host:5000/full').should be_false}
49
+ end
50
+
51
+ describe 'when URL is encoded' do
52
+ before(:each) do
53
+ @request.stub!(:fullpath => '/full%20with%20spaces?param=true', :path => '/full%20with%20spaces')
54
+ end
55
+
56
+ it {@adapter.current_page?('/full%20with%20spaces?param=true').should be_true}
57
+ it {@adapter.current_page?('/full%20with%20spaces?param3=true').should be_false}
58
+ it {@adapter.current_page?('/full%20with%20spaces').should be_true}
59
+ it {@adapter.current_page?('http://my_host:5000/full%20with%20spaces?param=true').should be_true}
60
+ it {@adapter.current_page?('http://my_host:5000/full%20with%20spaces?param3=true').should be_false}
61
+ it {@adapter.current_page?('http://my_host:5000/full%20with%20spaces').should be_true}
62
+ it {@adapter.current_page?('https://my_host:5000/full%20with%20spaces').should be_false}
63
+ it {@adapter.current_page?('http://my_host:6000/full%20with%20spaces').should be_false}
64
+ it {@adapter.current_page?('http://my_other_host:5000/full%20with%20spaces').should be_false}
65
+ end
66
+ end
67
+
68
+ describe 'link_to' do
69
+ it "should return a link" do
70
+ @adapter.link_to('link', 'url', :class => 'clazz', :id => 'id').should == "<a href='url' class='clazz' id='id'>link</a>"
71
+ end
72
+ end
73
+
74
+ describe 'content_tag' do
75
+ it "should return a tag" do
76
+ @adapter.content_tag(:div, 'content', :class => 'clazz', :id => 'id').should == "<div class='clazz' id='id'>content</div>"
77
+ end
78
+ end
79
+
80
+ end