simple-navigation 4.4.1 → 4.5.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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +84 -0
- data/.rspec +1 -2
- data/.rubocop.yml +49 -0
- data/.rubocop_todo.yml +38 -0
- data/Appraisals +55 -0
- data/CHANGELOG.md +7 -0
- data/Gemfile +21 -0
- data/Guardfile +4 -2
- data/README.md +11 -23
- data/Rakefile +2 -27
- data/bin/_guard-core +16 -0
- data/bin/appraisal +16 -0
- data/bin/guard +16 -0
- data/bin/rake +16 -0
- data/bin/rspec +16 -0
- data/bin/rubocop +16 -0
- data/gemfiles/rails_6.1.gemfile +35 -0
- data/gemfiles/rails_7.0.gemfile +23 -0
- data/gemfiles/rails_7.1.gemfile +23 -0
- data/gemfiles/rails_7.2.gemfile +23 -0
- data/gemfiles/rails_8.0.gemfile +23 -0
- data/gemfiles/rails_8.1.gemfile +23 -0
- data/generators/navigation_config/navigation_config_generator.rb +2 -0
- data/generators/navigation_config/templates/config/navigation.rb +30 -26
- data/lib/generators/navigation_config/navigation_config_generator.rb +2 -0
- data/lib/simple-navigation.rb +3 -1
- data/lib/simple_navigation/adapters/base.rb +2 -0
- data/lib/simple_navigation/adapters/nanoc.rb +8 -3
- data/lib/simple_navigation/adapters/padrino.rb +3 -1
- data/lib/simple_navigation/adapters/rails.rb +12 -14
- data/lib/simple_navigation/adapters/sinatra.rb +4 -6
- data/lib/simple_navigation/config_file.rb +1 -1
- data/lib/simple_navigation/config_file_finder.rb +3 -3
- data/lib/simple_navigation/configuration.rb +5 -5
- data/lib/simple_navigation/helpers.rb +9 -11
- data/lib/simple_navigation/item.rb +26 -20
- data/lib/simple_navigation/item_adapter.rb +16 -5
- data/lib/simple_navigation/item_container.rb +13 -7
- data/lib/simple_navigation/items_provider.rb +6 -4
- data/lib/simple_navigation/railtie.rb +3 -1
- data/lib/simple_navigation/renderer/base.rb +5 -5
- data/lib/simple_navigation/renderer/breadcrumbs.rb +4 -3
- data/lib/simple_navigation/renderer/json.rb +1 -1
- data/lib/simple_navigation/renderer/links.rb +2 -0
- data/lib/simple_navigation/renderer/list.rb +5 -5
- data/lib/simple_navigation/renderer/text.rb +3 -1
- data/lib/simple_navigation/version.rb +3 -1
- data/lib/simple_navigation.rb +32 -24
- data/simple-navigation.gemspec +16 -27
- data/spec/fake_app/config/navigation.rb +4 -2
- data/spec/fake_app/rails_app.rb +5 -3
- data/spec/integration/rendering_navigation_spec.rb +7 -5
- data/spec/simple_navigation/adapters/nanoc_spec.rb +97 -0
- data/spec/simple_navigation/adapters/padrino_spec.rb +41 -22
- data/spec/simple_navigation/adapters/rails_spec.rb +199 -206
- data/spec/simple_navigation/adapters/sinatra_spec.rb +21 -5
- data/spec/simple_navigation/config_file_finder_spec.rb +32 -28
- data/spec/simple_navigation/config_file_spec.rb +14 -14
- data/spec/simple_navigation/configuration_spec.rb +128 -121
- data/spec/simple_navigation/helpers_spec.rb +282 -284
- data/spec/simple_navigation/item_adapter_spec.rb +109 -122
- data/spec/simple_navigation/item_container_spec.rb +407 -408
- data/spec/simple_navigation/item_spec.rb +333 -301
- data/spec/simple_navigation/items_provider_spec.rb +30 -27
- data/spec/simple_navigation/renderer/base_spec.rb +166 -168
- data/spec/simple_navigation/renderer/breadcrumbs_spec.rb +81 -83
- data/spec/simple_navigation/renderer/json_spec.rb +49 -56
- data/spec/simple_navigation/renderer/links_spec.rb +81 -83
- data/spec/simple_navigation/renderer/list_spec.rb +111 -91
- data/spec/simple_navigation/renderer/text_spec.rb +37 -39
- data/spec/simple_navigation_spec.rb +54 -47
- data/spec/spec_helper.rb +146 -53
- metadata +25 -164
- data/.travis.yml +0 -23
- data/gemfiles/rails-3-2-stable.gemfile +0 -11
- data/gemfiles/rails-4-1-stable.gemfile +0 -7
- data/gemfiles/rails-4-2-stable.gemfile +0 -7
- data/gemfiles/rails-5-2-stable.gemfile +0 -7
- data/gemfiles/rails-6-0-stable.gemfile +0 -9
- data/gemfiles/rails-6-1-stable.gemfile +0 -9
- data/init.rb +0 -1
- data/install.rb +0 -5
- data/lib/simple_navigation/adapters.rb +0 -10
- data/lib/simple_navigation/renderer.rb +0 -12
- data/spec/initializers/coveralls.rb +0 -3
- data/spec/initializers/have_css_matcher.rb +0 -19
- data/spec/initializers/memfs.rb +0 -7
- data/spec/initializers/rails.rb +0 -4
- data/spec/initializers/rspec.rb +0 -7
- data/uninstall.rb +0 -1
|
@@ -1,49 +1,53 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
# Configures your navigation
|
|
3
4
|
SimpleNavigation::Configuration.run do |navigation|
|
|
4
5
|
# Specify a custom renderer if needed.
|
|
5
6
|
# The default renderer is SimpleNavigation::Renderer::List which renders HTML lists.
|
|
6
7
|
# The renderer can also be specified as option in the render_navigation call.
|
|
7
|
-
#navigation.renderer = Your::Custom::Renderer
|
|
8
|
+
# navigation.renderer = Your::Custom::Renderer
|
|
8
9
|
|
|
9
|
-
# Specify the class that will be applied to active navigation items. Defaults to 'selected'
|
|
10
|
-
#navigation.selected_class = 'selected'
|
|
10
|
+
# Specify the class that will be applied to active navigation items. Defaults to 'selected'
|
|
11
|
+
# navigation.selected_class = 'selected'
|
|
11
12
|
|
|
12
13
|
# Specify the class that will be applied to the current leaf of
|
|
13
14
|
# active navigation items. Defaults to 'simple-navigation-active-leaf'
|
|
14
|
-
#navigation.active_leaf_class = 'simple-navigation-active-leaf'
|
|
15
|
+
# navigation.active_leaf_class = 'simple-navigation-active-leaf'
|
|
15
16
|
|
|
16
17
|
# Specify if item keys are added to navigation items as id. Defaults to true
|
|
17
|
-
#navigation.autogenerate_item_ids = true
|
|
18
|
+
# navigation.autogenerate_item_ids = true
|
|
18
19
|
|
|
19
20
|
# You can override the default logic that is used to autogenerate the item ids.
|
|
20
21
|
# To do this, define a Proc which takes the key of the current item as argument.
|
|
21
22
|
# The example below would add a prefix to each key.
|
|
22
|
-
#navigation.id_generator = Proc.new {|key| "my-prefix-#{key}"}
|
|
23
|
+
# navigation.id_generator = Proc.new {|key| "my-prefix-#{key}"}
|
|
23
24
|
|
|
24
25
|
# If you need to add custom html around item names, you can define a proc that
|
|
25
26
|
# will be called with the name you pass in to the navigation.
|
|
26
27
|
# The example below shows how to wrap items spans.
|
|
27
|
-
#navigation.name_generator = Proc.new {|name, item| tag.span(name) }
|
|
28
|
+
# navigation.name_generator = Proc.new {|name, item| tag.span(name) }
|
|
28
29
|
|
|
29
30
|
# Specify if the auto highlight feature is turned on (globally, for the whole navigation). Defaults to true
|
|
30
|
-
#navigation.auto_highlight = true
|
|
31
|
-
|
|
32
|
-
# Specifies whether auto highlight should ignore query params and/or anchors when
|
|
33
|
-
# comparing the navigation items with the current URL. Defaults to true
|
|
34
|
-
#navigation.ignore_query_params_on_auto_highlight = true
|
|
35
|
-
#navigation.ignore_anchors_on_auto_highlight = true
|
|
36
|
-
|
|
37
|
-
# If this option is set to true, all item names will be considered as safe
|
|
38
|
-
#
|
|
31
|
+
# navigation.auto_highlight = true
|
|
32
|
+
|
|
33
|
+
# Specifies whether auto highlight should ignore query params and/or anchors when
|
|
34
|
+
# comparing the navigation items with the current URL. Defaults to true
|
|
35
|
+
# navigation.ignore_query_params_on_auto_highlight = true
|
|
36
|
+
# navigation.ignore_anchors_on_auto_highlight = true
|
|
37
|
+
|
|
38
|
+
# If this option is set to true, all item names will be considered as safe
|
|
39
|
+
# (passed through html_safe). Defaults to false.
|
|
40
|
+
# navigation.consider_item_names_as_safe = false
|
|
39
41
|
|
|
40
42
|
# Define the primary navigation
|
|
41
43
|
navigation.items do |primary|
|
|
42
44
|
# Add an item to the primary navigation. The following params apply:
|
|
43
45
|
# key - a symbol which uniquely defines your navigation item in the scope of the primary_navigation
|
|
44
46
|
# name - will be displayed in the rendered navigation. This can also be a call to your I18n-framework.
|
|
45
|
-
# url - the address that the generated item links to. You can also use url_helpers
|
|
46
|
-
#
|
|
47
|
+
# url - the address that the generated item links to. You can also use url_helpers
|
|
48
|
+
# (named routes, restful routes helper, url_for etc.)
|
|
49
|
+
# options - can be used to specify attributes that will be included in the rendered
|
|
50
|
+
# navigation item (e.g. id, class etc.)
|
|
47
51
|
# some special options that can be set:
|
|
48
52
|
# :html - Specifies html attributes that will be included in the rendered navigation item
|
|
49
53
|
# :if - Specifies a proc to call to determine if the item should
|
|
@@ -57,25 +61,25 @@ SimpleNavigation::Configuration.run do |navigation|
|
|
|
57
61
|
# when the item should be highlighted, you can set a regexp which is matched
|
|
58
62
|
# against the current URI. You may also use a proc, or the symbol <tt>:subpath</tt>.
|
|
59
63
|
#
|
|
60
|
-
primary.item :
|
|
64
|
+
primary.item :key1, 'name', url, options
|
|
61
65
|
|
|
62
66
|
# Add an item which has a sub navigation (same params, but with block)
|
|
63
|
-
primary.item :
|
|
67
|
+
primary.item :key2, 'name', url, options do |sub_nav|
|
|
64
68
|
# Add an item to the sub navigation (same params again)
|
|
65
|
-
sub_nav.item :
|
|
69
|
+
sub_nav.item :key21, 'name', url, options
|
|
66
70
|
end
|
|
67
71
|
|
|
68
72
|
# You can also specify a condition-proc that needs to be fullfilled to display an item.
|
|
69
73
|
# Conditions are part of the options. They are evaluated in the context of the views,
|
|
70
74
|
# thus you can use all the methods and vars you have available in the views.
|
|
71
|
-
primary.item :
|
|
72
|
-
primary.item :
|
|
75
|
+
primary.item :key3, 'Admin', url, html: { class: 'special' }, if: -> { current_user.admin? }
|
|
76
|
+
primary.item :key4, 'Account', url, unless: -> { logged_in? }
|
|
73
77
|
|
|
74
78
|
# you can also specify html attributes to attach to this particular level
|
|
75
79
|
# works for all levels of the menu
|
|
76
|
-
#primary.dom_attributes = {id: 'menu-id', class: 'menu-class'}
|
|
80
|
+
# primary.dom_attributes = {id: 'menu-id', class: 'menu-class'}
|
|
77
81
|
|
|
78
82
|
# You can turn off auto highlighting for a specific level
|
|
79
|
-
#primary.auto_highlight = false
|
|
83
|
+
# primary.auto_highlight = false
|
|
80
84
|
end
|
|
81
85
|
end
|
data/lib/simple-navigation.rb
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module SimpleNavigation
|
|
2
4
|
module Adapters
|
|
5
|
+
# @deprecated This adapter is for Nanoc3 (circa 2011-2012) and is no longer actively maintained.
|
|
6
|
+
# Nanoc3 is obsolete and has been replaced by Nanoc 4+. This adapter is kept for
|
|
7
|
+
# backward compatibility but should not be used for new projects.
|
|
3
8
|
class Nanoc < Base
|
|
4
9
|
class << self
|
|
5
10
|
def register(root)
|
|
6
11
|
SimpleNavigation.set_env(root, 'development')
|
|
7
|
-
Nanoc3::Context.
|
|
12
|
+
Nanoc3::Context.include SimpleNavigation::Helpers
|
|
8
13
|
end
|
|
9
14
|
end
|
|
10
15
|
|
|
11
|
-
def initialize(ctx)
|
|
16
|
+
def initialize(ctx) # rubocop:disable Lint/MissingSuper
|
|
12
17
|
@context = ctx
|
|
13
18
|
end
|
|
14
19
|
|
|
@@ -39,7 +44,7 @@ module SimpleNavigation
|
|
|
39
44
|
private
|
|
40
45
|
|
|
41
46
|
def to_attributes(options)
|
|
42
|
-
options.
|
|
47
|
+
options.filter_map { |k, v| v.nil? ? nil : "#{k}='#{v}'" }.join(' ')
|
|
43
48
|
end
|
|
44
49
|
end
|
|
45
50
|
end
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module SimpleNavigation
|
|
2
4
|
module Adapters
|
|
3
5
|
class Padrino < Sinatra
|
|
4
|
-
def self.register(
|
|
6
|
+
def self.register(_app)
|
|
5
7
|
SimpleNavigation.set_env(::Padrino.root, ::Padrino.env)
|
|
6
8
|
::Padrino::Application.send(:helpers, SimpleNavigation::Helpers)
|
|
7
9
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module SimpleNavigation
|
|
2
4
|
module Adapters
|
|
3
5
|
class Rails < Base
|
|
@@ -10,23 +12,19 @@ module SimpleNavigation
|
|
|
10
12
|
# This delays the hook initialization using the on_load
|
|
11
13
|
# hooks, but does not change behaviour for existing
|
|
12
14
|
# rails versions.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
SimpleNavigation::Adapters::Rails.register_controller_helpers
|
|
16
|
-
end
|
|
17
|
-
else
|
|
18
|
-
register_controller_helpers
|
|
15
|
+
ActiveSupport.on_load(:action_controller_base) do
|
|
16
|
+
SimpleNavigation::Adapters::Rails.register_controller_helpers
|
|
19
17
|
end
|
|
20
18
|
end
|
|
21
19
|
|
|
22
20
|
def self.register_controller_helpers
|
|
23
|
-
ActionController::Base.
|
|
21
|
+
ActionController::Base.include SimpleNavigation::Helpers
|
|
24
22
|
SimpleNavigation::Helpers.instance_methods.each do |m|
|
|
25
23
|
ActionController::Base.send(:helper_method, m.to_sym)
|
|
26
24
|
end
|
|
27
25
|
end
|
|
28
26
|
|
|
29
|
-
def initialize(context)
|
|
27
|
+
def initialize(context) # rubocop:disable Lint/MissingSuper
|
|
30
28
|
@controller = extract_controller_from context
|
|
31
29
|
@template = template_from @controller
|
|
32
30
|
@request = @template.request if @template
|
|
@@ -47,21 +45,21 @@ module SimpleNavigation
|
|
|
47
45
|
end
|
|
48
46
|
|
|
49
47
|
def context_for_eval
|
|
50
|
-
template
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
template ||
|
|
49
|
+
controller ||
|
|
50
|
+
raise('no context set for evaluation the config file')
|
|
53
51
|
end
|
|
54
52
|
|
|
55
53
|
def current_page?(url)
|
|
56
|
-
template
|
|
54
|
+
template&.current_page?(url)
|
|
57
55
|
end
|
|
58
56
|
|
|
59
57
|
def link_to(name, url, options = {})
|
|
60
|
-
template
|
|
58
|
+
template&.link_to(link_title(name), url, options)
|
|
61
59
|
end
|
|
62
60
|
|
|
63
61
|
def content_tag(type, content, options = {})
|
|
64
|
-
template
|
|
62
|
+
template&.content_tag(type, html_safe(content), options)
|
|
65
63
|
end
|
|
66
64
|
|
|
67
65
|
protected
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module SimpleNavigation
|
|
4
4
|
module Adapters
|
|
@@ -7,13 +7,13 @@ module SimpleNavigation
|
|
|
7
7
|
SimpleNavigation.set_env(app.root, app.environment)
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
def initialize(context)
|
|
10
|
+
def initialize(context) # rubocop:disable Lint/MissingSuper
|
|
11
11
|
@context = context
|
|
12
12
|
@request = context.request
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def context_for_eval
|
|
16
|
-
context ||
|
|
16
|
+
context || raise('no context set for evaluation the config file')
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def request_uri
|
|
@@ -32,9 +32,7 @@ module SimpleNavigation
|
|
|
32
32
|
request_uri.split('?').first
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
uri = "#{request.scheme}://#{request.host_with_port}#{uri}"
|
|
37
|
-
end
|
|
35
|
+
uri = "#{request.scheme}://#{request.host_with_port}#{uri}" if %r{^\w+://}.match?(url_string)
|
|
38
36
|
|
|
39
37
|
url_string == CGI.unescape(uri)
|
|
40
38
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module SimpleNavigation
|
|
4
4
|
# Internal: Encapsulates the configuration file finding logic.
|
|
@@ -22,8 +22,8 @@ module SimpleNavigation
|
|
|
22
22
|
config_file_name = config_file_name_for_context(context)
|
|
23
23
|
|
|
24
24
|
find_config_file(config_file_name) ||
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
raise("Config file '#{config_file_name}' not found in " \
|
|
26
|
+
"path(s) #{paths.join(', ')}!")
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
private
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module SimpleNavigation
|
|
4
4
|
# Responsible for evaluating and handling the config/navigation.rb file.
|
|
@@ -27,8 +27,8 @@ module SimpleNavigation
|
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
# Starts processing the configuration
|
|
30
|
-
def self.run
|
|
31
|
-
|
|
30
|
+
def self.run
|
|
31
|
+
yield Configuration.instance
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
# Sets the config's default-settings
|
|
@@ -75,13 +75,13 @@ module SimpleNavigation
|
|
|
75
75
|
#
|
|
76
76
|
def items(items_provider = nil, &block)
|
|
77
77
|
if (items_provider && block) || (items_provider.nil? && block.nil?)
|
|
78
|
-
|
|
78
|
+
raise('please specify either items_provider or block, but not both')
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
self.primary_navigation = ItemContainer.new
|
|
82
82
|
|
|
83
83
|
if block
|
|
84
|
-
|
|
84
|
+
yield primary_navigation
|
|
85
85
|
else
|
|
86
86
|
primary_navigation.items = ItemsProvider.new(items_provider).items
|
|
87
87
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module SimpleNavigation
|
|
2
4
|
# View helpers to render the navigation.
|
|
3
5
|
#
|
|
@@ -30,14 +32,12 @@ module SimpleNavigation
|
|
|
30
32
|
SimpleNavigation.load_config context
|
|
31
33
|
SimpleNavigation::Configuration.eval_config context
|
|
32
34
|
|
|
33
|
-
if block_given? || options[:items]
|
|
34
|
-
SimpleNavigation.config.items(options[:items], &block)
|
|
35
|
-
end
|
|
35
|
+
SimpleNavigation.config.items(options[:items], &block) if block_given? || options[:items]
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
return if SimpleNavigation.primary_navigation
|
|
38
|
+
|
|
39
|
+
raise 'no primary navigation defined, either use a navigation config ' \
|
|
40
|
+
'file or pass items directly to render_navigation'
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
def self.apply_defaults(options)
|
|
@@ -85,7 +85,7 @@ module SimpleNavigation
|
|
|
85
85
|
#
|
|
86
86
|
def render_navigation(options = {}, &block)
|
|
87
87
|
container = active_navigation_item_container(options, &block)
|
|
88
|
-
container
|
|
88
|
+
container&.render(options)
|
|
89
89
|
end
|
|
90
90
|
|
|
91
91
|
# Returns the name of the currently active navigation item belonging to the
|
|
@@ -138,9 +138,7 @@ module SimpleNavigation
|
|
|
138
138
|
# by default) if no active item can be found for the specified
|
|
139
139
|
# options
|
|
140
140
|
def active_navigation_item(options = {}, value_for_nil = nil)
|
|
141
|
-
if options[:level].nil? || options[:level] == :all
|
|
142
|
-
options[:level] = :leaves
|
|
143
|
-
end
|
|
141
|
+
options[:level] = :leaves if options[:level].nil? || options[:level] == :all
|
|
144
142
|
container = active_navigation_item_container(options)
|
|
145
143
|
if container && (item = container.selected_item)
|
|
146
144
|
block_given? ? yield(item) : item
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module SimpleNavigation
|
|
2
4
|
# Represents an item in your navigation.
|
|
3
5
|
# Gets generated by the item method in the config-file.
|
|
4
|
-
class Item
|
|
6
|
+
class Item # rubocop:disable Metrics/ClassLength
|
|
5
7
|
attr_reader :key,
|
|
6
8
|
:name,
|
|
7
9
|
:sub_navigation,
|
|
@@ -27,7 +29,7 @@ module SimpleNavigation
|
|
|
27
29
|
# the name will be passed to the name_generator specified
|
|
28
30
|
# in the configuration.
|
|
29
31
|
#
|
|
30
|
-
def name(options = {})
|
|
32
|
+
def name(options = {}) # rubocop:disable Lint/DuplicateMethods
|
|
31
33
|
options = { apply_generator: true }.merge(options)
|
|
32
34
|
if options[:apply_generator]
|
|
33
35
|
config.name_generator.call(@name, self)
|
|
@@ -50,7 +52,7 @@ module SimpleNavigation
|
|
|
50
52
|
# for this item in the config-file.
|
|
51
53
|
# It also adds the 'selected' class to the list of classes if necessary.
|
|
52
54
|
def html_options
|
|
53
|
-
html_opts = options.fetch(:html) {
|
|
55
|
+
html_opts = options.fetch(:html) { {} }
|
|
54
56
|
html_opts[:id] ||= autogenerated_item_id
|
|
55
57
|
|
|
56
58
|
classes = [html_opts[:class], selected_class, active_leaf_class]
|
|
@@ -63,17 +65,17 @@ module SimpleNavigation
|
|
|
63
65
|
# Returns the configured active_leaf_class if the item is the selected leaf,
|
|
64
66
|
# nil otherwise
|
|
65
67
|
def active_leaf_class
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
return unless !selected_by_subnav? && selected_by_condition?
|
|
69
|
+
|
|
70
|
+
config.active_leaf_class
|
|
69
71
|
end
|
|
70
72
|
|
|
71
73
|
# Returns the configured selected_class if the item is selected,
|
|
72
74
|
# nil otherwise
|
|
73
75
|
def selected_class
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
return unless selected?
|
|
77
|
+
|
|
78
|
+
container.selected_class || config.selected_class
|
|
77
79
|
end
|
|
78
80
|
|
|
79
81
|
# Returns the :highlights_on option as set at initialization
|
|
@@ -89,7 +91,11 @@ module SimpleNavigation
|
|
|
89
91
|
# Returns the html attributes for the link as set with the :link_html option
|
|
90
92
|
# at initialization
|
|
91
93
|
def link_html_options
|
|
92
|
-
@link_html_options ||=
|
|
94
|
+
@link_html_options ||= begin
|
|
95
|
+
link_options = options[:link_html] || {}
|
|
96
|
+
link_options[:'aria-current'] = 'page' if !selected_by_subnav? && selected_by_condition?
|
|
97
|
+
link_options
|
|
98
|
+
end
|
|
93
99
|
end
|
|
94
100
|
|
|
95
101
|
protected
|
|
@@ -97,7 +103,7 @@ module SimpleNavigation
|
|
|
97
103
|
# Returns true if item has a subnavigation and
|
|
98
104
|
# the sub_navigation is selected
|
|
99
105
|
def selected_by_subnav?
|
|
100
|
-
sub_navigation
|
|
106
|
+
sub_navigation&.selected?
|
|
101
107
|
end
|
|
102
108
|
|
|
103
109
|
# Returns true if the item's url matches the request's current url.
|
|
@@ -139,26 +145,26 @@ module SimpleNavigation
|
|
|
139
145
|
end
|
|
140
146
|
|
|
141
147
|
def remove_anchors(url_with_anchors)
|
|
142
|
-
url_with_anchors
|
|
148
|
+
url_with_anchors&.split('#')&.first
|
|
143
149
|
end
|
|
144
150
|
|
|
145
151
|
def remove_query_params(url_with_params)
|
|
146
|
-
url_with_params
|
|
152
|
+
url_with_params&.split('?')&.first
|
|
147
153
|
end
|
|
148
154
|
|
|
149
155
|
def url_for_autohighlight
|
|
150
|
-
relevant_url = remove_anchors(
|
|
156
|
+
relevant_url = remove_anchors(url) if config.ignore_anchors_on_auto_highlight
|
|
151
157
|
relevant_url = remove_query_params(relevant_url) if config.ignore_query_params_on_auto_highlight
|
|
152
158
|
relevant_url
|
|
153
159
|
end
|
|
154
160
|
|
|
155
161
|
def selected_by_autohighlight?
|
|
156
162
|
return false unless auto_highlight?
|
|
157
|
-
return false unless
|
|
163
|
+
return false unless url
|
|
158
164
|
|
|
159
165
|
root_path_match? ||
|
|
160
|
-
|
|
161
|
-
|
|
166
|
+
(url_for_autohighlight && SimpleNavigation.current_page?(url_for_autohighlight)) ||
|
|
167
|
+
autohighlight_by_subpath?
|
|
162
168
|
end
|
|
163
169
|
|
|
164
170
|
def autohighlight_by_subpath?
|
|
@@ -171,13 +177,13 @@ module SimpleNavigation
|
|
|
171
177
|
when Proc then highlights_on.call
|
|
172
178
|
when :subpath then selected_by_subpath?
|
|
173
179
|
else
|
|
174
|
-
|
|
180
|
+
raise ArgumentError, ':highlights_on must be a Regexp, Proc or :subpath'
|
|
175
181
|
end
|
|
176
182
|
end
|
|
177
183
|
|
|
178
184
|
def selected_by_subpath?
|
|
179
185
|
escaped_url = Regexp.escape(url_for_autohighlight)
|
|
180
|
-
!!(request_uri =~
|
|
186
|
+
!!(request_uri =~ %r{^#{escaped_url}(/|$||\?)}i)
|
|
181
187
|
end
|
|
182
188
|
|
|
183
189
|
def setup_sub_navigation(items = nil, &sub_nav_block)
|
|
@@ -186,7 +192,7 @@ module SimpleNavigation
|
|
|
186
192
|
self.sub_navigation = ItemContainer.new(container.level + 1)
|
|
187
193
|
|
|
188
194
|
if sub_nav_block
|
|
189
|
-
|
|
195
|
+
yield sub_navigation
|
|
190
196
|
else
|
|
191
197
|
sub_navigation.items = items
|
|
192
198
|
end
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
require 'ostruct'
|
|
1
|
+
# frozen_string_literal: true
|
|
3
2
|
|
|
4
3
|
module SimpleNavigation
|
|
5
4
|
# This class acts as an adapter to items that are not defined using the DSL
|
|
@@ -30,20 +29,32 @@ module SimpleNavigation
|
|
|
30
29
|
|
|
31
30
|
attr_reader :item
|
|
32
31
|
|
|
32
|
+
class Item
|
|
33
|
+
attr_reader :key, :name, :url, :options, :items
|
|
34
|
+
|
|
35
|
+
def initialize(item)
|
|
36
|
+
@key = item[:key]
|
|
37
|
+
@name = item[:name]
|
|
38
|
+
@url = item[:url]
|
|
39
|
+
@options = item[:options] || {}
|
|
40
|
+
@items = item[:items] || []
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
33
44
|
def initialize(item)
|
|
34
|
-
@item = item.is_a?(Hash) ?
|
|
45
|
+
@item = item.is_a?(Hash) ? Item.new(item) : item
|
|
35
46
|
end
|
|
36
47
|
|
|
37
48
|
# Returns the options for this item. If the wrapped item does not implement
|
|
38
49
|
# an options method, an empty hash is returned.
|
|
39
50
|
def options
|
|
40
|
-
item.
|
|
51
|
+
item.options
|
|
41
52
|
end
|
|
42
53
|
|
|
43
54
|
# Returns the items (subnavigation) for this item if it responds to :items
|
|
44
55
|
# and the items-collection is not empty. Returns nil otherwise.
|
|
45
56
|
def items
|
|
46
|
-
item.items if item.
|
|
57
|
+
item.items if item.items&.any?
|
|
47
58
|
end
|
|
48
59
|
|
|
49
60
|
# Converts this Item into a SimpleNavigation::Item
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module SimpleNavigation
|
|
2
4
|
# Holds the Items for a navigation 'level'.
|
|
3
|
-
class ItemContainer
|
|
5
|
+
class ItemContainer # rubocop:disable Metrics/ClassLength
|
|
4
6
|
attr_accessor :auto_highlight,
|
|
5
7
|
:dom_class,
|
|
6
8
|
:dom_id,
|
|
@@ -11,7 +13,7 @@ module SimpleNavigation
|
|
|
11
13
|
|
|
12
14
|
attr_writer :dom_attributes
|
|
13
15
|
|
|
14
|
-
def initialize(level = 1)
|
|
16
|
+
def initialize(level = 1) # :nodoc:
|
|
15
17
|
@level = level
|
|
16
18
|
@items ||= []
|
|
17
19
|
@renderer = SimpleNavigation.config.renderer
|
|
@@ -24,7 +26,7 @@ module SimpleNavigation
|
|
|
24
26
|
dom_id_and_class = {
|
|
25
27
|
id: dom_id,
|
|
26
28
|
class: dom_class
|
|
27
|
-
}.
|
|
29
|
+
}.compact
|
|
28
30
|
|
|
29
31
|
@dom_attributes.merge(dom_id_and_class)
|
|
30
32
|
end
|
|
@@ -63,6 +65,7 @@ module SimpleNavigation
|
|
|
63
65
|
# The <tt>block</tt> - if specified - will hold the item's sub_navigation.
|
|
64
66
|
def item(key, name, url = nil, options = {}, &block)
|
|
65
67
|
return unless should_add_item?(options)
|
|
68
|
+
|
|
66
69
|
item = Item.new(self, key, name, url, options, &block)
|
|
67
70
|
add_item item, options
|
|
68
71
|
end
|
|
@@ -71,6 +74,7 @@ module SimpleNavigation
|
|
|
71
74
|
new_items.each do |item|
|
|
72
75
|
item_adapter = ItemAdapter.new(item)
|
|
73
76
|
next unless should_add_item?(item_adapter.options)
|
|
77
|
+
|
|
74
78
|
add_item item_adapter.to_simple_navigation_item(self), item_adapter.options
|
|
75
79
|
end
|
|
76
80
|
end
|
|
@@ -91,10 +95,11 @@ module SimpleNavigation
|
|
|
91
95
|
|
|
92
96
|
items.each do |item|
|
|
93
97
|
next unless item.sub_navigation
|
|
98
|
+
|
|
94
99
|
level = item.sub_navigation.level_for_item(navi_key)
|
|
95
100
|
return level if level
|
|
96
101
|
end
|
|
97
|
-
|
|
102
|
+
nil
|
|
98
103
|
end
|
|
99
104
|
|
|
100
105
|
# Renders the items in this ItemContainer using the configured renderer.
|
|
@@ -152,7 +157,8 @@ module SimpleNavigation
|
|
|
152
157
|
end
|
|
153
158
|
|
|
154
159
|
def modify_dom_attributes(options)
|
|
155
|
-
return unless container_options = options[:container]
|
|
160
|
+
return unless (container_options = options[:container])
|
|
161
|
+
|
|
156
162
|
self.dom_attributes = container_options.fetch(:attributes) { dom_attributes }
|
|
157
163
|
self.dom_class = container_options.fetch(:class) { dom_class }
|
|
158
164
|
self.dom_id = container_options.fetch(:id) { dom_id }
|
|
@@ -178,13 +184,13 @@ module SimpleNavigation
|
|
|
178
184
|
|
|
179
185
|
def should_add_item?(options)
|
|
180
186
|
[options[:if]].flatten.compact.all? { |m| evaluate_method(m) } &&
|
|
181
|
-
|
|
187
|
+
[options[:unless]].flatten.compact.none? { |m| evaluate_method(m) }
|
|
182
188
|
end
|
|
183
189
|
|
|
184
190
|
def evaluate_method(method)
|
|
185
191
|
case method
|
|
186
192
|
when Proc, Method then method.call
|
|
187
|
-
else
|
|
193
|
+
else raise(ArgumentError, ':if or :unless must be procs or lambdas')
|
|
188
194
|
end
|
|
189
195
|
end
|
|
190
196
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module SimpleNavigation
|
|
2
4
|
# Acts as a proxy to navigation items that are passed into the
|
|
3
5
|
# SimpleNavigation::Configuration#items method.
|
|
@@ -20,7 +22,7 @@ module SimpleNavigation
|
|
|
20
22
|
end
|
|
21
23
|
|
|
22
24
|
# Returns the navigation items
|
|
23
|
-
def items
|
|
25
|
+
def items # rubocop:disable Metrics/MethodLength
|
|
24
26
|
if provider.is_a?(Symbol)
|
|
25
27
|
SimpleNavigation.context_for_eval.send(provider)
|
|
26
28
|
elsif provider.respond_to?(:items)
|
|
@@ -28,9 +30,9 @@ module SimpleNavigation
|
|
|
28
30
|
elsif provider.respond_to?(:each)
|
|
29
31
|
provider
|
|
30
32
|
else
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
raise('items_provider either must be a symbol specifying the ' \
|
|
34
|
+
'helper-method to call, an object with an items-method defined ' \
|
|
35
|
+
'or an enumerable representing the items')
|
|
34
36
|
end
|
|
35
37
|
end
|
|
36
38
|
end
|