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.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +84 -0
  3. data/.rspec +1 -2
  4. data/.rubocop.yml +49 -0
  5. data/.rubocop_todo.yml +38 -0
  6. data/Appraisals +55 -0
  7. data/CHANGELOG.md +7 -0
  8. data/Gemfile +21 -0
  9. data/Guardfile +4 -2
  10. data/README.md +11 -23
  11. data/Rakefile +2 -27
  12. data/bin/_guard-core +16 -0
  13. data/bin/appraisal +16 -0
  14. data/bin/guard +16 -0
  15. data/bin/rake +16 -0
  16. data/bin/rspec +16 -0
  17. data/bin/rubocop +16 -0
  18. data/gemfiles/rails_6.1.gemfile +35 -0
  19. data/gemfiles/rails_7.0.gemfile +23 -0
  20. data/gemfiles/rails_7.1.gemfile +23 -0
  21. data/gemfiles/rails_7.2.gemfile +23 -0
  22. data/gemfiles/rails_8.0.gemfile +23 -0
  23. data/gemfiles/rails_8.1.gemfile +23 -0
  24. data/generators/navigation_config/navigation_config_generator.rb +2 -0
  25. data/generators/navigation_config/templates/config/navigation.rb +30 -26
  26. data/lib/generators/navigation_config/navigation_config_generator.rb +2 -0
  27. data/lib/simple-navigation.rb +3 -1
  28. data/lib/simple_navigation/adapters/base.rb +2 -0
  29. data/lib/simple_navigation/adapters/nanoc.rb +8 -3
  30. data/lib/simple_navigation/adapters/padrino.rb +3 -1
  31. data/lib/simple_navigation/adapters/rails.rb +12 -14
  32. data/lib/simple_navigation/adapters/sinatra.rb +4 -6
  33. data/lib/simple_navigation/config_file.rb +1 -1
  34. data/lib/simple_navigation/config_file_finder.rb +3 -3
  35. data/lib/simple_navigation/configuration.rb +5 -5
  36. data/lib/simple_navigation/helpers.rb +9 -11
  37. data/lib/simple_navigation/item.rb +26 -20
  38. data/lib/simple_navigation/item_adapter.rb +16 -5
  39. data/lib/simple_navigation/item_container.rb +13 -7
  40. data/lib/simple_navigation/items_provider.rb +6 -4
  41. data/lib/simple_navigation/railtie.rb +3 -1
  42. data/lib/simple_navigation/renderer/base.rb +5 -5
  43. data/lib/simple_navigation/renderer/breadcrumbs.rb +4 -3
  44. data/lib/simple_navigation/renderer/json.rb +1 -1
  45. data/lib/simple_navigation/renderer/links.rb +2 -0
  46. data/lib/simple_navigation/renderer/list.rb +5 -5
  47. data/lib/simple_navigation/renderer/text.rb +3 -1
  48. data/lib/simple_navigation/version.rb +3 -1
  49. data/lib/simple_navigation.rb +32 -24
  50. data/simple-navigation.gemspec +16 -27
  51. data/spec/fake_app/config/navigation.rb +4 -2
  52. data/spec/fake_app/rails_app.rb +5 -3
  53. data/spec/integration/rendering_navigation_spec.rb +7 -5
  54. data/spec/simple_navigation/adapters/nanoc_spec.rb +97 -0
  55. data/spec/simple_navigation/adapters/padrino_spec.rb +41 -22
  56. data/spec/simple_navigation/adapters/rails_spec.rb +199 -206
  57. data/spec/simple_navigation/adapters/sinatra_spec.rb +21 -5
  58. data/spec/simple_navigation/config_file_finder_spec.rb +32 -28
  59. data/spec/simple_navigation/config_file_spec.rb +14 -14
  60. data/spec/simple_navigation/configuration_spec.rb +128 -121
  61. data/spec/simple_navigation/helpers_spec.rb +282 -284
  62. data/spec/simple_navigation/item_adapter_spec.rb +109 -122
  63. data/spec/simple_navigation/item_container_spec.rb +407 -408
  64. data/spec/simple_navigation/item_spec.rb +333 -301
  65. data/spec/simple_navigation/items_provider_spec.rb +30 -27
  66. data/spec/simple_navigation/renderer/base_spec.rb +166 -168
  67. data/spec/simple_navigation/renderer/breadcrumbs_spec.rb +81 -83
  68. data/spec/simple_navigation/renderer/json_spec.rb +49 -56
  69. data/spec/simple_navigation/renderer/links_spec.rb +81 -83
  70. data/spec/simple_navigation/renderer/list_spec.rb +111 -91
  71. data/spec/simple_navigation/renderer/text_spec.rb +37 -39
  72. data/spec/simple_navigation_spec.rb +54 -47
  73. data/spec/spec_helper.rb +146 -53
  74. metadata +25 -164
  75. data/.travis.yml +0 -23
  76. data/gemfiles/rails-3-2-stable.gemfile +0 -11
  77. data/gemfiles/rails-4-1-stable.gemfile +0 -7
  78. data/gemfiles/rails-4-2-stable.gemfile +0 -7
  79. data/gemfiles/rails-5-2-stable.gemfile +0 -7
  80. data/gemfiles/rails-6-0-stable.gemfile +0 -9
  81. data/gemfiles/rails-6-1-stable.gemfile +0 -9
  82. data/init.rb +0 -1
  83. data/install.rb +0 -5
  84. data/lib/simple_navigation/adapters.rb +0 -10
  85. data/lib/simple_navigation/renderer.rb +0 -12
  86. data/spec/initializers/coveralls.rb +0 -3
  87. data/spec/initializers/have_css_matcher.rb +0 -19
  88. data/spec/initializers/memfs.rb +0 -7
  89. data/spec/initializers/rails.rb +0 -4
  90. data/spec/initializers/rspec.rb +0 -7
  91. data/uninstall.rb +0 -1
@@ -1,49 +1,53 @@
1
- # -*- coding: utf-8 -*-
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 (passed through html_safe). Defaults to false.
38
- #navigation.consider_item_names_as_safe = false
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 (named routes, restful routes helper, url_for etc.)
46
- # options - can be used to specify attributes that will be included in the rendered navigation item (e.g. id, class etc.)
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 :key_1, 'name', url, options
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 :key_2, 'name', url, options do |sub_nav|
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 :key_2_1, 'name', url, options
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 :key_3, 'Admin', url, html: { class: 'special' }, if: -> { current_user.admin? }
72
- primary.item :key_4, 'Account', url, unless: -> { logged_in? }
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class NavigationConfigGenerator < Rails::Generators::Base
2
4
  def self.source_root
3
5
  @source_root ||= begin
@@ -1 +1,3 @@
1
- require 'simple_navigation'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'simple_navigation'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SimpleNavigation
2
4
  module Adapters
3
5
  # This is the base class for all adapters.
@@ -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.send(:include, SimpleNavigation::Helpers)
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.map { |k, v| v.nil? ? nil : "#{k}='#{v}'" }.compact.join(' ')
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(app)
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
- if ::Rails::VERSION::MAJOR >= 6
14
- ActiveSupport.on_load(:action_controller_base) do
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.send(:include, SimpleNavigation::Helpers)
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
- controller ||
52
- fail('no context set for evaluation the config file')
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 && template.current_page?(url)
54
+ template&.current_page?(url)
57
55
  end
58
56
 
59
57
  def link_to(name, url, options = {})
60
- template && template.link_to(link_title(name), url, options)
58
+ template&.link_to(link_title(name), url, options)
61
59
  end
62
60
 
63
61
  def content_tag(type, content, options = {})
64
- template && template.content_tag(type, html_safe(content), options)
62
+ template&.content_tag(type, html_safe(content), options)
65
63
  end
66
64
 
67
65
  protected
@@ -1,4 +1,4 @@
1
- require 'cgi'
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 || fail('no context set for evaluation the config file')
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
- if url_string =~ %r(^\w+://)
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
- require 'active_support/core_ext/string'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module SimpleNavigation
4
4
  # Internal: Encapsulates the config file naming knowledge.
@@ -1,4 +1,4 @@
1
- require 'simple_navigation/config_file'
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
- fail("Config file '#{config_file_name}' not found in " \
26
- "path(s) #{paths.join(', ')}!")
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
- require 'singleton'
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(&block)
31
- block.call Configuration.instance
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
- fail('please specify either items_provider or block, but not both')
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
- block.call primary_navigation
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
- unless SimpleNavigation.primary_navigation
38
- fail 'no primary navigation defined, either use a navigation config ' \
39
- 'file or pass items directly to render_navigation'
40
- end
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 && container.render(options)
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) { Hash.new }
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
- if !selected_by_subnav? && selected_by_condition?
67
- config.active_leaf_class
68
- end
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
- if selected?
75
- container.selected_class || config.selected_class
76
- end
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 ||= options[:link_html]
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 && sub_navigation.selected?
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 && url_with_anchors.split('#').first
148
+ url_with_anchors&.split('#')&.first
143
149
  end
144
150
 
145
151
  def remove_query_params(url_with_params)
146
- url_with_params && url_with_params.split('?').first
152
+ url_with_params&.split('?')&.first
147
153
  end
148
154
 
149
155
  def url_for_autohighlight
150
- relevant_url = remove_anchors(self.url) if config.ignore_anchors_on_auto_highlight
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 self.url
163
+ return false unless url
158
164
 
159
165
  root_path_match? ||
160
- (url_for_autohighlight && SimpleNavigation.current_page?(url_for_autohighlight)) ||
161
- autohighlight_by_subpath?
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
- fail ArgumentError, ':highlights_on must be a Regexp, Proc or :subpath'
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 =~ /^#{escaped_url}(\/|$||\?)/i)
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
- sub_nav_block.call sub_navigation
195
+ yield sub_navigation
190
196
  else
191
197
  sub_navigation.items = items
192
198
  end
@@ -1,5 +1,4 @@
1
- require 'forwardable'
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) ? OpenStruct.new(item) : item
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.respond_to?(:options) ? item.options : {}
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.respond_to?(:items) && item.items && item.items.any?
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) #:nodoc:
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
- }.reject { |_, v| v.nil? }
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
- return nil
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
- [options[:unless]].flatten.compact.none? { |m| evaluate_method(m) }
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 fail(ArgumentError, ':if or :unless must be procs or lambdas')
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
- fail('items_provider either must be a symbol specifying the ' \
32
- 'helper-method to call, an object with an items-method defined ' \
33
- 'or an enumerable representing the items')
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
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SimpleNavigation
2
4
  class Railtie < ::Rails::Railtie
3
- initializer 'simple_navigation.register' do |app|
5
+ initializer 'simple_navigation.register' do |_app|
4
6
  SimpleNavigation.register
5
7
  end
6
8
  end