simple-navigation 3.12.0 → 3.12.1

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 (30) hide show
  1. data/CHANGELOG +4 -0
  2. data/generators/navigation_config/navigation_config_generator.rb +3 -3
  3. data/generators/navigation_config/templates/config/navigation.rb +9 -10
  4. data/init.rb +1 -1
  5. data/lib/generators/navigation_config/navigation_config_generator.rb +11 -6
  6. data/lib/simple-navigation.rb +1 -1
  7. data/lib/simple_navigation.rb +93 -65
  8. data/lib/simple_navigation/adapters/base.rb +16 -16
  9. data/lib/simple_navigation/adapters/nanoc.rb +7 -6
  10. data/lib/simple_navigation/adapters/padrino.rb +5 -7
  11. data/lib/simple_navigation/adapters/rails.rb +52 -39
  12. data/lib/simple_navigation/adapters/sinatra.rb +14 -17
  13. data/lib/simple_navigation/core/configuration.rb +73 -34
  14. data/lib/simple_navigation/core/item.rb +110 -54
  15. data/lib/simple_navigation/core/item_adapter.rb +18 -13
  16. data/lib/simple_navigation/core/item_container.rb +93 -66
  17. data/lib/simple_navigation/core/items_provider.rb +12 -10
  18. data/lib/simple_navigation/rails_controller_methods.rb +98 -78
  19. data/lib/simple_navigation/rendering/helpers.rb +130 -68
  20. data/lib/simple_navigation/rendering/renderer/base.rb +30 -25
  21. data/lib/simple_navigation/rendering/renderer/breadcrumbs.rb +26 -19
  22. data/lib/simple_navigation/rendering/renderer/json.rb +11 -13
  23. data/lib/simple_navigation/rendering/renderer/links.rb +18 -13
  24. data/lib/simple_navigation/rendering/renderer/list.rb +28 -15
  25. data/lib/simple_navigation/rendering/renderer/text.rb +7 -12
  26. data/lib/simple_navigation/version.rb +1 -1
  27. data/spec/lib/simple_navigation/core/item_adapter_spec.rb +1 -1
  28. data/spec/lib/simple_navigation/core/item_container_spec.rb +118 -68
  29. data/spec/lib/simple_navigation_spec.rb +16 -5
  30. metadata +2 -2
@@ -1,31 +1,36 @@
1
1
  module SimpleNavigation
2
2
  module Renderer
3
-
4
- # Renders an ItemContainer as a <div> element and its containing items as <a> elements.
3
+ # Renders an ItemContainer as a <div> element and its containing items as
4
+ # <a> elements.
5
5
  # It adds the 'selected' class to the <a> element that is currently active.
6
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_attributes are applied to the surrounding <div> element.
7
+ # The Links renderer cannot be used to render nested navigations. If you
8
+ # would like it to use with nested navigations, you have to render each
9
+ # level separately.
12
10
  #
11
+ # By default, the renderer sets the item's key as dom_id for the rendered
12
+ # <a> element unless the config option <tt>autogenerate_item_ids</tt> is set
13
+ # to false.
14
+ # The id can also be explicitely specified by setting the id in the
15
+ # html-options of the 'item' method in the config/navigation.rb file.
16
+ # The ItemContainer's dom_attributes are applied to the surrounding <div>
17
+ # element.
13
18
  class Links < SimpleNavigation::Renderer::Base
14
19
  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, item_container.dom_attributes)
20
+ div_content = item_container.items
21
+ .map { |item| tag_for(item) }
22
+ .join(join_with)
23
+ content_tag :div, div_content, item_container.dom_attributes
19
24
  end
20
25
 
21
26
  protected
22
27
 
23
28
  def join_with
24
- @join_with ||= options[:join_with] || ""
29
+ @join_with ||= options[:join_with] || ''
25
30
  end
26
31
 
27
32
  def options_for(item)
28
- {:method => item.method}.merge(item.html_options)
33
+ { method: item.method }.merge(item.html_options)
29
34
  end
30
35
  end
31
36
  end
@@ -1,28 +1,41 @@
1
1
  module SimpleNavigation
2
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.
3
+ # Renders an ItemContainer as a <ul> element and its containing items as
4
+ # <li> elements.
5
+ # It adds the 'selected' class to li element AND the link inside the li
6
+ # element that is currently active.
6
7
  #
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
+ # If the sub navigation should be included (based on the level and
9
+ # expand_all options), it renders another <ul> containing the sub navigation
10
+ # inside the active <li> element.
8
11
  #
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.
12
+ # By default, the renderer sets the item's key as dom_id for the rendered
13
+ # <li> element unless the config option <tt>autogenerate_item_ids</tt> is
14
+ # set to false.
15
+ # The id can also be explicitely specified by setting the id in the
16
+ # html-options of the 'item' method in the config/navigation.rb file.
11
17
  class List < SimpleNavigation::Renderer::Base
12
18
  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}
19
+ if skip_if_empty? && item_container.empty?
20
+ ''
21
+ else
22
+ tag = options[:ordered] ? :ol : :ul
23
+ content = list_content(item_container)
24
+ content_tag(tag, content, item_container.dom_attributes)
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def list_content(item_container)
31
+ item_container.items.map { |item|
32
+ li_options = item.html_options.except(:link)
15
33
  li_content = tag_for(item)
16
34
  if include_sub_navigation?(item)
17
35
  li_content << render_sub_navigation_for(item)
18
36
  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, item_container.dom_attributes)
25
- end
37
+ content_tag(:li, li_content, li_options)
38
+ }.join
26
39
  end
27
40
  end
28
41
  end
@@ -1,26 +1,21 @@
1
1
  module SimpleNavigation
2
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
- #
3
+ # Renders the 'chain' of selected navigation items as simple text items,
4
+ # joined with an optional separator (similar to breadcrumbs, but without
5
+ # markup).
6
6
  class Text < SimpleNavigation::Renderer::Base
7
-
8
7
  def render(item_container)
9
- list(item_container).compact.join(options[:join_with] || " ")
8
+ list(item_container).compact.join(options[:join_with] || ' ')
10
9
  end
11
10
 
12
11
  private
13
12
 
14
13
  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
14
+ item_container.items.keep_if(&:selected?).map do |item|
15
+ [item.name(apply_generator: false)] +
16
+ (include_sub_navigation?(item) ? list(item.sub_navigation) : [])
21
17
  end
22
18
  end
23
-
24
19
  end
25
20
  end
26
21
  end
@@ -1,3 +1,3 @@
1
1
  module SimpleNavigation
2
- VERSION = '3.12.0'
2
+ VERSION = '3.12.1'
3
3
  end
@@ -62,7 +62,7 @@ module SimpleNavigation
62
62
  end
63
63
 
64
64
  context 'and items is not empty' do
65
- let(:items) { double(:items, empty?: false) }
65
+ let(:items) { [true] }
66
66
 
67
67
  before { item.stub(items: items) }
68
68
 
@@ -2,19 +2,72 @@ require 'spec_helper'
2
2
 
3
3
  module SimpleNavigation
4
4
  describe ItemContainer do
5
- let(:item_container) { ItemContainer.new }
5
+ subject(:item_container) { ItemContainer.new }
6
6
 
7
- describe '#initialize' do
8
- it 'sets the renderer to the globally-configured renderer per default' do
9
- expect(Configuration.instance).to receive(:renderer)
10
- ItemContainer.new
7
+ shared_examples 'adding the item to the list' do
8
+ it 'adds the item to the list' do
9
+ Item.stub(:new).and_return(item)
10
+ item_container.item(*args)
11
+ expect(item_container.items).to include(item)
12
+ end
13
+ end
14
+
15
+ shared_examples 'not adding the item to the list' do
16
+ it "doesn't add the item to the list" do
17
+ Item.stub(:new).and_return(item)
18
+ item_container.item(*args)
19
+ expect(item_container.items).not_to include(item)
11
20
  end
21
+ end
12
22
 
13
- it "sets an empty items array" do
23
+ describe '#initialize' do
24
+ it 'sets an empty items array' do
14
25
  expect(item_container.items).to be_empty
15
26
  end
16
27
  end
17
28
 
29
+ describe '#dom_attributes' do
30
+ let(:dom_attributes) {{ id: 'test_id', class: 'test_class' }}
31
+
32
+ before { item_container.dom_attributes = dom_attributes }
33
+
34
+ it "returns the container's dom_attributes" do
35
+ expect(item_container.dom_attributes).to eq dom_attributes
36
+ end
37
+
38
+ context 'when the dom_attributes do not contain any id or class' do
39
+ let(:dom_attributes) {{ test: 'test' }}
40
+
41
+ context "and the container hasn't any dom_id" do
42
+ it "returns the contaier's dom_attributes without any id" do
43
+ expect(item_container.dom_attributes).not_to include(:id)
44
+ end
45
+ end
46
+
47
+ context 'and the container has a dom_id' do
48
+ before { item_container.dom_id = 'test_id' }
49
+
50
+ it "returns the contaier's dom_attributes including the #dom_id" do
51
+ expect(item_container.dom_attributes).to include(id: 'test_id')
52
+ end
53
+ end
54
+
55
+ context "and the container hasn't any dom_class" do
56
+ it "returns the contaier's dom_attributes without any class" do
57
+ expect(item_container.dom_attributes).not_to include(:class)
58
+ end
59
+ end
60
+
61
+ context 'and the container has a dom_class' do
62
+ before { item_container.dom_class = 'test_class' }
63
+
64
+ it "returns the contaier's dom_attributes including the #dom_class" do
65
+ expect(item_container.dom_attributes).to include(class: 'test_class')
66
+ end
67
+ end
68
+ end
69
+ end
70
+
18
71
  describe '#items=' do
19
72
  let(:item) { double(:item) }
20
73
  let(:items) { [item] }
@@ -31,23 +84,13 @@ module SimpleNavigation
31
84
  end
32
85
 
33
86
  context 'when item should be added' do
34
- let(:simple_navigation_item) { double(:simple_navigation_item) }
87
+ let(:wrapped_item) { double(:wrapped_item).as_null_object }
35
88
 
36
- before do
37
- item_container.stub(should_add_item?: true)
38
- item_adapter.stub(to_simple_navigation_item: simple_navigation_item)
39
- end
89
+ before { ItemAdapter.stub(:new).with(item).and_return(wrapped_item) }
40
90
 
41
- it 'converts the item to an Item' do
42
- expect(item_adapter).to receive(:to_simple_navigation_item)
43
- .with(item_container)
44
- item_container.items = items
45
- end
46
-
47
- it 'adds the item to the items-collection' do
48
- expect(item_container.items).to receive(:<<)
49
- .with(simple_navigation_item)
91
+ it 'converts item to an Item and adds it to the items collection' do
50
92
  item_container.items = items
93
+ expect(item_container.items).to include(wrapped_item)
51
94
  end
52
95
  end
53
96
 
@@ -177,65 +220,54 @@ module SimpleNavigation
177
220
  end
178
221
 
179
222
  describe '#item' do
180
- context 'when the item has no :if or :unless option' do
181
- let(:options) { Hash.new }
182
-
183
- before { item_container.stub(:should_add_item?).and_return(true) }
184
-
185
- context 'when a block is given' do
186
- let(:sub_container) { double(:sub_container) }
187
- let(:block) { proc{} }
188
-
189
- before { ItemContainer.stub(:new).with(2).and_return(sub_container) }
223
+ let(:options) { Hash.new }
224
+ let(:item) { double(:item) }
190
225
 
191
- it 'yields a new ItemContainer' do
192
- expect{ |blk|
193
- item_container.item('key', 'name', 'url', options, &blk)
194
- }.to yield_with_args(sub_container)
195
- end
226
+ context 'when a block is given' do
227
+ let(:block) { proc{} }
228
+ let(:sub_container) { double(:sub_container) }
196
229
 
197
- it "creates a new Navigation-Item with the given params and block" do
198
- expect(Item).to receive(:new)
199
- .with(item_container, 'key', 'name', 'url',
200
- options, nil, &block)
201
- item_container.item('key', 'name', 'url', options, &block)
202
- end
230
+ it 'yields a new ItemContainer' do
231
+ Item.any_instance
232
+ .stub(:sub_navigation)
233
+ .and_return(sub_container)
203
234
 
204
- it 'adds the created item to the list of items' do
205
- expect(item_container.items).to receive(:<<)
206
- item_container.item('key', 'name', 'url', options) {}
207
- end
235
+ expect{ |blk|
236
+ item_container.item('key', 'name', 'url', options, &blk)
237
+ }.to yield_with_args(sub_container)
208
238
  end
209
239
 
210
- context 'when no block is given' do
211
- it "creates a new Navigation_item with the given params and nil as sub_navigation" do
212
- expect(Item).to receive(:new)
213
- .with(item_container, 'key', 'name', 'url', options, nil)
214
- item_container.item('key', 'name', 'url', options)
215
- end
240
+ it "creates a new Item with the given params and block" do
241
+ Item.stub(:new)
242
+ .with(item_container, 'key', 'name', 'url', options, nil, &block)
243
+ .and_return(item)
244
+ item_container.item('key', 'name', 'url', options, &block)
245
+ expect(item_container.items).to include(item)
246
+ end
216
247
 
217
- it 'adds the created item to the list of items' do
218
- expect(item_container.items).to receive(:<<)
219
- item_container.item('key', 'name', 'url', options)
220
- end
248
+ it 'adds the created item to the list of items' do
249
+ item_container.item('key', 'name', 'url', options) {}
250
+ expect(item_container.items).not_to include(item)
221
251
  end
222
252
  end
223
253
 
224
- describe 'Optional url and optional options' do
225
- shared_examples 'adding the item to the list' do
226
- it 'adds the item to the list' do
227
- expect(item_container.items).to receive(:<<)
228
- item_container.item(*args)
229
- end
254
+ context 'when no block is given' do
255
+ it 'creates a new Item with the given params and no sub navigation' do
256
+ Item.stub(:new)
257
+ .with(item_container, 'key', 'name', 'url', options, nil)
258
+ .and_return(item)
259
+ item_container.item('key', 'name', 'url', options)
260
+ expect(item_container.items).to include(item)
230
261
  end
231
262
 
232
- shared_examples 'not adding the item to the list' do
233
- it "doesn't add the item to the list" do
234
- expect(item_container.items).not_to receive(:<<)
235
- item_container.item(*args)
236
- end
263
+ it 'adds the created item to the list of items' do
264
+ Item.stub(:new).and_return(item)
265
+ item_container.item('key', 'name', 'url', options) {}
266
+ expect(item_container.items).to include(item)
237
267
  end
268
+ end
238
269
 
270
+ describe 'Optional url and optional options' do
239
271
  context 'when item specifed without url or options' do
240
272
  it_behaves_like 'adding the item to the list' do
241
273
  let(:args) { ['key', 'name'] }
@@ -302,7 +334,7 @@ module SimpleNavigation
302
334
  context 'and it evals to true' do
303
335
  let(:condition) { true }
304
336
 
305
- it 'creates a new Navigation-Item' do
337
+ it 'creates a new Item' do
306
338
  expect(Item).to receive(:new)
307
339
  item_container.item('key', 'name', 'url', options)
308
340
  end
@@ -311,7 +343,7 @@ module SimpleNavigation
311
343
  context 'and it evals to false' do
312
344
  let(:condition) { false }
313
345
 
314
- it "doesn't create a new Navigation-Item" do
346
+ it "doesn't create a new Item" do
315
347
  expect(Item).not_to receive(:new)
316
348
  item_container.item('key', 'name', 'url', options)
317
349
  end
@@ -429,6 +461,24 @@ module SimpleNavigation
429
461
  end
430
462
  end
431
463
 
464
+ describe '#renderer' do
465
+ context 'when no renderer is set explicitly' do
466
+ it 'returns globally-configured renderer' do
467
+ expect(item_container.renderer).to be Configuration.instance.renderer
468
+ end
469
+ end
470
+
471
+ context 'when a renderer is set explicitly' do
472
+ let(:renderer) { double(:renderer) }
473
+
474
+ before { item_container.renderer = renderer }
475
+
476
+ it 'returns the specified renderer' do
477
+ expect(item_container.renderer).to be renderer
478
+ end
479
+ end
480
+ end
481
+
432
482
  describe '#level_for_item' do
433
483
  before(:each) do
434
484
  item_container.item(:p1, 'p1', 'p1')
@@ -45,7 +45,7 @@ describe SimpleNavigation do
45
45
  before { subject.config_file_paths = ['my_config_file_path'] }
46
46
 
47
47
  context 'and the requested config file exists' do
48
- before { File.stub(exists?: true) }
48
+ before { File.stub(exist?: true) }
49
49
 
50
50
  it 'returns the path to the config_file' do
51
51
  expect(subject.config_file).to eq 'my_config_file_path/navigation.rb'
@@ -53,7 +53,7 @@ describe SimpleNavigation do
53
53
  end
54
54
 
55
55
  context 'and the requested config file does not exist' do
56
- before { File.stub(exists?: false) }
56
+ before { File.stub(exist?: false) }
57
57
 
58
58
  it 'returns nil' do
59
59
  expect(subject.config_file).to be_nil
@@ -65,7 +65,7 @@ describe SimpleNavigation do
65
65
  before { subject.config_file_paths = ['first_path', 'second_path'] }
66
66
 
67
67
  context 'and the requested config file exists' do
68
- before { File.stub(exists?: true) }
68
+ before { File.stub(exist?: true) }
69
69
 
70
70
  it 'returns the path to the first matching config_file' do
71
71
  expect(subject.config_file).to eq 'first_path/navigation.rb'
@@ -73,7 +73,7 @@ describe SimpleNavigation do
73
73
  end
74
74
 
75
75
  context 'and the requested config file does not exist' do
76
- before { File.stub(exists?: false) }
76
+ before { File.stub(exist?: false) }
77
77
 
78
78
  it 'returns nil' do
79
79
  expect(subject.config_file).to be_nil
@@ -196,7 +196,7 @@ describe SimpleNavigation do
196
196
  before do
197
197
  subject.config_file_path = 'path_to_config'
198
198
  IO.stub(:read).and_return('file_content')
199
- File.stub(exists?: true)
199
+ File.stub(exist?: true)
200
200
  end
201
201
 
202
202
  after { subject.config_files = {} }
@@ -286,4 +286,15 @@ describe SimpleNavigation do
286
286
  it_behaves_like 'loading the right adapter', :padrino, :Padrino
287
287
  it_behaves_like 'loading the right adapter', :sinatra, :Sinatra
288
288
  end
289
+
290
+ describe '.init_adapter_from' do
291
+ let(:adapter) { double(:adapter) }
292
+ let(:adapter_class) { double(:adapter_class, new: adapter) }
293
+
294
+ it 'sets the adapter to a new instance of adapter_class' do
295
+ subject.adapter_class = adapter_class
296
+ subject.init_adapter_from(:default)
297
+ expect(subject.adapter).to be adapter
298
+ end
299
+ end
289
300
  end