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.
- data/CHANGELOG +4 -0
- data/generators/navigation_config/navigation_config_generator.rb +3 -3
- data/generators/navigation_config/templates/config/navigation.rb +9 -10
- data/init.rb +1 -1
- data/lib/generators/navigation_config/navigation_config_generator.rb +11 -6
- data/lib/simple-navigation.rb +1 -1
- data/lib/simple_navigation.rb +93 -65
- data/lib/simple_navigation/adapters/base.rb +16 -16
- data/lib/simple_navigation/adapters/nanoc.rb +7 -6
- data/lib/simple_navigation/adapters/padrino.rb +5 -7
- data/lib/simple_navigation/adapters/rails.rb +52 -39
- data/lib/simple_navigation/adapters/sinatra.rb +14 -17
- data/lib/simple_navigation/core/configuration.rb +73 -34
- data/lib/simple_navigation/core/item.rb +110 -54
- data/lib/simple_navigation/core/item_adapter.rb +18 -13
- data/lib/simple_navigation/core/item_container.rb +93 -66
- data/lib/simple_navigation/core/items_provider.rb +12 -10
- data/lib/simple_navigation/rails_controller_methods.rb +98 -78
- data/lib/simple_navigation/rendering/helpers.rb +130 -68
- data/lib/simple_navigation/rendering/renderer/base.rb +30 -25
- data/lib/simple_navigation/rendering/renderer/breadcrumbs.rb +26 -19
- data/lib/simple_navigation/rendering/renderer/json.rb +11 -13
- data/lib/simple_navigation/rendering/renderer/links.rb +18 -13
- data/lib/simple_navigation/rendering/renderer/list.rb +28 -15
- data/lib/simple_navigation/rendering/renderer/text.rb +7 -12
- data/lib/simple_navigation/version.rb +1 -1
- data/spec/lib/simple_navigation/core/item_adapter_spec.rb +1 -1
- data/spec/lib/simple_navigation/core/item_container_spec.rb +118 -68
- data/spec/lib/simple_navigation_spec.rb +16 -5
- metadata +2 -2
@@ -1,31 +1,36 @@
|
|
1
1
|
module SimpleNavigation
|
2
2
|
module Renderer
|
3
|
-
|
4
|
-
#
|
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
|
8
|
-
#
|
9
|
-
#
|
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
|
16
|
-
|
17
|
-
|
18
|
-
content_tag
|
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
|
-
{:
|
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
|
-
#
|
5
|
-
# It adds the 'selected' class to li element AND the link inside the li
|
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
|
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
|
10
|
-
#
|
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
|
-
|
14
|
-
|
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
|
-
|
20
|
-
|
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
|
-
#
|
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.
|
16
|
-
|
17
|
-
|
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
|
@@ -2,19 +2,72 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module SimpleNavigation
|
4
4
|
describe ItemContainer do
|
5
|
-
|
5
|
+
subject(:item_container) { ItemContainer.new }
|
6
6
|
|
7
|
-
|
8
|
-
it '
|
9
|
-
|
10
|
-
|
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
|
-
|
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(:
|
87
|
+
let(:wrapped_item) { double(:wrapped_item).as_null_object }
|
35
88
|
|
36
|
-
before
|
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
|
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
|
-
|
181
|
-
|
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
|
-
|
192
|
-
|
193
|
-
|
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
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
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
|
-
|
205
|
-
|
206
|
-
|
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
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
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
|
-
|
218
|
-
|
219
|
-
|
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
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
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
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
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
|
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
|
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(
|
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(
|
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(
|
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(
|
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(
|
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
|