simple-navigation 3.13.0 → 4.0.5
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 +7 -0
- data/.gitignore +3 -0
- data/.rspec +1 -0
- data/.travis.yml +10 -3
- data/CHANGELOG.md +420 -0
- data/Guardfile +4 -2
- data/LICENSE +1 -1
- data/README.md +30 -7
- data/Rakefile +25 -2
- data/gemfiles/.bundle/config +2 -0
- data/gemfiles/rails-3-2-stable.gemfile +11 -0
- data/gemfiles/rails-4-1-stable.gemfile +7 -0
- data/gemfiles/rails-4-2-stable.gemfile +7 -0
- data/generators/navigation_config/navigation_config_generator.rb +0 -1
- data/generators/navigation_config/templates/config/navigation.rb +18 -15
- data/lib/simple_navigation.rb +25 -42
- data/lib/simple_navigation/adapters/padrino.rb +2 -2
- data/lib/simple_navigation/adapters/rails.rb +1 -24
- data/lib/simple_navigation/adapters/sinatra.rb +2 -11
- data/lib/simple_navigation/config_file.rb +36 -0
- data/lib/simple_navigation/config_file_finder.rb +42 -0
- data/lib/simple_navigation/{core/configuration.rb → configuration.rb} +7 -1
- data/lib/simple_navigation/{rendering/helpers.rb → helpers.rb} +0 -4
- data/lib/simple_navigation/{core/item.rb → item.rb} +76 -83
- data/lib/simple_navigation/{core/item_adapter.rb → item_adapter.rb} +3 -17
- data/lib/simple_navigation/{core/item_container.rb → item_container.rb} +23 -14
- data/lib/simple_navigation/{core/items_provider.rb → items_provider.rb} +0 -0
- data/lib/simple_navigation/railtie.rb +7 -0
- data/lib/simple_navigation/renderer.rb +12 -0
- data/lib/simple_navigation/{rendering/renderer → renderer}/base.rb +1 -1
- data/lib/simple_navigation/{rendering/renderer → renderer}/breadcrumbs.rb +0 -0
- data/lib/simple_navigation/{rendering/renderer → renderer}/json.rb +2 -0
- data/lib/simple_navigation/{rendering/renderer → renderer}/links.rb +0 -0
- data/lib/simple_navigation/{rendering/renderer → renderer}/list.rb +0 -0
- data/lib/simple_navigation/{rendering/renderer → renderer}/text.rb +0 -0
- data/lib/simple_navigation/version.rb +1 -1
- data/simple-navigation.gemspec +6 -5
- data/spec/fake_app/config/navigation.rb +6 -0
- data/spec/fake_app/rails_app.rb +35 -0
- data/spec/initializers/coveralls.rb +3 -0
- data/spec/initializers/have_css_matcher.rb +8 -3
- data/spec/initializers/memfs.rb +7 -0
- data/spec/initializers/rails.rb +4 -0
- data/spec/initializers/rspec.rb +7 -0
- data/spec/integration/rendering_navigation_spec.rb +14 -0
- data/spec/{lib/simple_navigation → simple_navigation}/adapters/padrino_spec.rb +0 -2
- data/spec/{lib/simple_navigation → simple_navigation}/adapters/rails_spec.rb +43 -94
- data/spec/{lib/simple_navigation → simple_navigation}/adapters/sinatra_spec.rb +4 -6
- data/spec/simple_navigation/config_file_finder_spec.rb +50 -0
- data/spec/simple_navigation/config_file_spec.rb +25 -0
- data/spec/{lib/simple_navigation/core → simple_navigation}/configuration_spec.rb +29 -19
- data/spec/{lib/simple_navigation/rendering → simple_navigation}/helpers_spec.rb +10 -13
- data/spec/{lib/simple_navigation/core → simple_navigation}/item_adapter_spec.rb +14 -11
- data/spec/{lib/simple_navigation/core → simple_navigation}/item_container_spec.rb +130 -42
- data/spec/simple_navigation/item_spec.rb +475 -0
- data/spec/{lib/simple_navigation/core → simple_navigation}/items_provider_spec.rb +1 -3
- data/spec/{lib/simple_navigation/rendering → simple_navigation}/renderer/base_spec.rb +34 -36
- data/spec/{lib/simple_navigation/rendering → simple_navigation}/renderer/breadcrumbs_spec.rb +4 -7
- data/spec/{lib/simple_navigation/rendering → simple_navigation}/renderer/json_spec.rb +5 -11
- data/spec/{lib/simple_navigation/rendering → simple_navigation}/renderer/links_spec.rb +5 -8
- data/spec/{lib/simple_navigation/rendering → simple_navigation}/renderer/list_spec.rb +4 -7
- data/spec/{lib/simple_navigation/rendering → simple_navigation}/renderer/text_spec.rb +4 -7
- data/spec/simple_navigation_spec.rb +190 -0
- data/spec/spec_helper.rb +29 -35
- metadata +128 -113
- data/CHANGELOG +0 -288
- data/lib/simple_navigation/core.rb +0 -5
- data/lib/simple_navigation/rails_controller_methods.rb +0 -164
- data/lib/simple_navigation/rendering.rb +0 -12
- data/rails/init.rb +0 -1
- data/spec/lib/simple_navigation/core/item_spec.rb +0 -703
- data/spec/lib/simple_navigation/rails_controller_methods_spec.rb +0 -270
- data/spec/lib/simple_navigation_spec.rb +0 -300
@@ -7,7 +7,10 @@ module SimpleNavigation
|
|
7
7
|
|
8
8
|
attr_accessor :autogenerate_item_ids,
|
9
9
|
:auto_highlight,
|
10
|
-
:consider_item_names_as_safe
|
10
|
+
:consider_item_names_as_safe,
|
11
|
+
:highlight_on_subpath,
|
12
|
+
:ignore_query_params_on_auto_highlight,
|
13
|
+
:ignore_anchors_on_auto_highlight
|
11
14
|
|
12
15
|
attr_reader :primary_navigation
|
13
16
|
|
@@ -33,6 +36,9 @@ module SimpleNavigation
|
|
33
36
|
@autogenerate_item_ids = true
|
34
37
|
@auto_highlight = true
|
35
38
|
@consider_item_names_as_safe = false
|
39
|
+
@highlight_on_subpath = false
|
40
|
+
@ignore_anchors_on_auto_highlight = true
|
41
|
+
@ignore_query_params_on_auto_highlight = true
|
36
42
|
end
|
37
43
|
|
38
44
|
def active_leaf_class
|
@@ -34,10 +34,6 @@ module SimpleNavigation
|
|
34
34
|
SimpleNavigation.config.items(options[:items], &block)
|
35
35
|
end
|
36
36
|
|
37
|
-
if SimpleNavigation.respond_to?(:handle_explicit_navigation)
|
38
|
-
SimpleNavigation.handle_explicit_navigation
|
39
|
-
end
|
40
|
-
|
41
37
|
unless SimpleNavigation.primary_navigation
|
42
38
|
fail 'no primary navigation defined, either use a navigation config ' \
|
43
39
|
'file or pass items directly to render_navigation'
|
@@ -2,27 +2,23 @@ module SimpleNavigation
|
|
2
2
|
# Represents an item in your navigation.
|
3
3
|
# Gets generated by the item method in the config-file.
|
4
4
|
class Item
|
5
|
-
attr_reader :
|
6
|
-
:
|
7
|
-
:method,
|
5
|
+
attr_reader :key,
|
6
|
+
:name,
|
8
7
|
:sub_navigation,
|
9
8
|
:url
|
10
9
|
|
11
|
-
attr_writer :html_options
|
12
|
-
|
13
10
|
# see ItemContainer#item
|
14
11
|
#
|
15
12
|
# The subnavigation (if any) is either provided by a block or
|
16
13
|
# passed in directly as <tt>items</tt>
|
17
|
-
def initialize(container, key, name,
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
@container = setup_container(container, options)
|
14
|
+
def initialize(container, key, name, url = nil, opts = {}, &sub_nav_block)
|
15
|
+
self.container = container
|
16
|
+
self.key = key
|
17
|
+
self.name = name.respond_to?(:call) ? name.call : name
|
18
|
+
self.url = url.respond_to?(:call) ? url.call : url
|
19
|
+
self.options = opts
|
24
20
|
|
25
|
-
setup_sub_navigation(items, &sub_nav_block)
|
21
|
+
setup_sub_navigation(options[:items], &sub_nav_block)
|
26
22
|
end
|
27
23
|
|
28
24
|
# Returns the item's name.
|
@@ -32,8 +28,8 @@ module SimpleNavigation
|
|
32
28
|
#
|
33
29
|
def name(options = {})
|
34
30
|
options = { apply_generator: true }.merge(options)
|
35
|
-
if
|
36
|
-
|
31
|
+
if options[:apply_generator]
|
32
|
+
config.name_generator.call(@name, self)
|
37
33
|
else
|
38
34
|
@name
|
39
35
|
end
|
@@ -42,35 +38,32 @@ module SimpleNavigation
|
|
42
38
|
# Returns true if this navigation item should be rendered as 'selected'.
|
43
39
|
# An item is selected if
|
44
40
|
#
|
45
|
-
# * it has been explicitly selected in a controller or
|
46
41
|
# * it has a subnavigation and one of its subnavigation items is selected or
|
47
42
|
# * its url matches the url of the current request (auto highlighting)
|
48
43
|
#
|
49
44
|
def selected?
|
50
|
-
@selected ||=
|
51
|
-
selected_by_subnav? ||
|
52
|
-
selected_by_condition?
|
45
|
+
@selected ||= selected_by_subnav? || selected_by_condition?
|
53
46
|
end
|
54
47
|
|
55
48
|
# Returns the html-options hash for the item, i.e. the options specified
|
56
49
|
# for this item in the config-file.
|
57
50
|
# It also adds the 'selected' class to the list of classes if necessary.
|
58
51
|
def html_options
|
59
|
-
|
60
|
-
|
52
|
+
html_opts = options.fetch(:html) { Hash.new }
|
53
|
+
html_opts[:id] ||= autogenerated_item_id
|
61
54
|
|
62
|
-
classes = [
|
55
|
+
classes = [html_opts[:class], selected_class, active_leaf_class]
|
63
56
|
classes = classes.flatten.compact.join(' ')
|
64
|
-
|
57
|
+
html_opts[:class] = classes if classes && !classes.empty?
|
65
58
|
|
66
|
-
|
59
|
+
html_opts
|
67
60
|
end
|
68
61
|
|
69
62
|
# Returns the configured active_leaf_class if the item is the selected leaf,
|
70
63
|
# nil otherwise
|
71
64
|
def active_leaf_class
|
72
65
|
if !selected_by_subnav? && selected_by_condition?
|
73
|
-
|
66
|
+
config.active_leaf_class
|
74
67
|
end
|
75
68
|
end
|
76
69
|
|
@@ -78,10 +71,26 @@ module SimpleNavigation
|
|
78
71
|
# nil otherwise
|
79
72
|
def selected_class
|
80
73
|
if selected?
|
81
|
-
container.selected_class ||
|
74
|
+
container.selected_class || config.selected_class
|
82
75
|
end
|
83
76
|
end
|
84
77
|
|
78
|
+
# Returns the :highlights_on option as set at initialization
|
79
|
+
def highlights_on
|
80
|
+
@highlights_on ||= options[:highlights_on]
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns the :method option as set at initialization
|
84
|
+
def method
|
85
|
+
@method ||= options[:method]
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns the html attributes for the link as set with the :link_html option
|
89
|
+
# at initialization
|
90
|
+
def link_html_options
|
91
|
+
@link_html_options ||= options[:link_html]
|
92
|
+
end
|
93
|
+
|
85
94
|
protected
|
86
95
|
|
87
96
|
# Returns true if item has a subnavigation and
|
@@ -90,10 +99,6 @@ module SimpleNavigation
|
|
90
99
|
sub_navigation && sub_navigation.selected?
|
91
100
|
end
|
92
101
|
|
93
|
-
def selected_by_config?
|
94
|
-
false
|
95
|
-
end
|
96
|
-
|
97
102
|
# Returns true if the item's url matches the request's current url.
|
98
103
|
def selected_by_condition?
|
99
104
|
highlights_on ? selected_by_highlights_on? : selected_by_autohighlight?
|
@@ -104,86 +109,74 @@ module SimpleNavigation
|
|
104
109
|
url == '/' && SimpleNavigation.request_path == '/'
|
105
110
|
end
|
106
111
|
|
107
|
-
# Returns true if the item's id should be added to the rendered output.
|
108
|
-
def autogenerate_item_ids?
|
109
|
-
SimpleNavigation.config.autogenerate_item_ids
|
110
|
-
end
|
111
|
-
|
112
112
|
# Returns the item's id which is added to the rendered output.
|
113
113
|
def autogenerated_item_id
|
114
|
-
|
114
|
+
config.id_generator.call(key) if config.autogenerate_item_ids
|
115
115
|
end
|
116
116
|
|
117
117
|
# Return true if auto_highlight is on for this item.
|
118
118
|
def auto_highlight?
|
119
|
-
|
120
|
-
end
|
121
|
-
|
122
|
-
def url_without_anchor
|
123
|
-
url && url.split('#').first
|
119
|
+
config.auto_highlight && container.auto_highlight
|
124
120
|
end
|
125
121
|
|
126
122
|
private
|
127
123
|
|
128
|
-
|
124
|
+
attr_accessor :container,
|
125
|
+
:options
|
129
126
|
|
130
|
-
attr_writer :
|
127
|
+
attr_writer :key,
|
128
|
+
:name,
|
131
129
|
:sub_navigation,
|
132
130
|
:url
|
133
131
|
|
134
|
-
def
|
135
|
-
|
136
|
-
(root_path_match? ||
|
137
|
-
(url_without_anchor &&
|
138
|
-
SimpleNavigation.current_page?(url_without_anchor)))
|
132
|
+
def config
|
133
|
+
SimpleNavigation.config
|
139
134
|
end
|
140
135
|
|
141
|
-
def
|
142
|
-
|
136
|
+
def request_uri
|
137
|
+
SimpleNavigation.request_uri
|
138
|
+
end
|
143
139
|
|
144
|
-
|
145
|
-
|
146
|
-
when Proc then highlights_on.call
|
147
|
-
when :subpath
|
148
|
-
escaped_url = Regexp.escape(url_without_anchor)
|
149
|
-
!!(SimpleNavigation.request_uri =~ /^#{escaped_url}(\/|$|\?)/i)
|
150
|
-
else
|
151
|
-
fail ArgumentError, ':highlights_on must be a Regexp, Proc or :subpath'
|
152
|
-
end
|
140
|
+
def remove_anchors(url_with_anchors)
|
141
|
+
url_with_anchors && url_with_anchors.split('#').first
|
153
142
|
end
|
154
143
|
|
155
|
-
def
|
156
|
-
|
157
|
-
|
158
|
-
end
|
144
|
+
def remove_query_params(url_with_params)
|
145
|
+
url_with_params && url_with_params.split('?').first
|
146
|
+
end
|
159
147
|
|
160
|
-
|
161
|
-
|
162
|
-
|
148
|
+
def url_for_autohighlight
|
149
|
+
relevant_url = remove_anchors(self.url) if config.ignore_anchors_on_auto_highlight
|
150
|
+
relevant_url = remove_query_params(relevant_url) if config.ignore_query_params_on_auto_highlight
|
151
|
+
relevant_url
|
152
|
+
end
|
163
153
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
{}
|
168
|
-
end
|
154
|
+
def selected_by_autohighlight?
|
155
|
+
return false unless auto_highlight?
|
156
|
+
return false unless self.url
|
169
157
|
|
170
|
-
|
171
|
-
|
172
|
-
|
158
|
+
root_path_match? ||
|
159
|
+
(url_for_autohighlight && SimpleNavigation.current_page?(url_for_autohighlight)) ||
|
160
|
+
autohighlight_by_subpath?
|
161
|
+
end
|
173
162
|
|
174
|
-
|
163
|
+
def autohighlight_by_subpath?
|
164
|
+
config.highlight_on_subpath && selected_by_subpath?
|
175
165
|
end
|
176
166
|
|
177
|
-
def
|
178
|
-
case
|
179
|
-
when
|
180
|
-
when Proc then
|
181
|
-
|
167
|
+
def selected_by_highlights_on?
|
168
|
+
case highlights_on
|
169
|
+
when Regexp then !!(request_uri =~ highlights_on)
|
170
|
+
when Proc then highlights_on.call
|
171
|
+
when :subpath then selected_by_subpath?
|
172
|
+
else
|
173
|
+
fail ArgumentError, ':highlights_on must be a Regexp, Proc or :subpath'
|
182
174
|
end
|
175
|
+
end
|
183
176
|
|
184
|
-
|
185
|
-
|
186
|
-
|
177
|
+
def selected_by_subpath?
|
178
|
+
escaped_url = Regexp.escape(url_for_autohighlight)
|
179
|
+
!!(request_uri =~ /^#{escaped_url}(\/|$||\?)/i)
|
187
180
|
end
|
188
181
|
|
189
182
|
def setup_sub_navigation(items = nil, &sub_nav_block)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'forwardable'
|
2
|
+
require 'ostruct'
|
2
3
|
|
3
4
|
module SimpleNavigation
|
4
5
|
# This class acts as an adapter to items that are not defined using the DSL
|
@@ -30,7 +31,7 @@ module SimpleNavigation
|
|
30
31
|
attr_reader :item
|
31
32
|
|
32
33
|
def initialize(item)
|
33
|
-
@item = item.is_a?(Hash) ?
|
34
|
+
@item = item.is_a?(Hash) ? OpenStruct.new(item) : item
|
34
35
|
end
|
35
36
|
|
36
37
|
# Returns the options for this item. If the wrapped item does not implement
|
@@ -47,22 +48,7 @@ module SimpleNavigation
|
|
47
48
|
|
48
49
|
# Converts this Item into a SimpleNavigation::Item
|
49
50
|
def to_simple_navigation_item(item_container)
|
50
|
-
SimpleNavigation::Item.new(item_container, key, name, url, options
|
51
|
-
end
|
52
|
-
|
53
|
-
protected
|
54
|
-
|
55
|
-
# Converts the specified hash into an object. Each key will be added
|
56
|
-
# as method.
|
57
|
-
def to_object(hash)
|
58
|
-
mod = Module.new do
|
59
|
-
hash.each_pair do |key, value|
|
60
|
-
define_method key do
|
61
|
-
value
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
Object.new.extend(mod)
|
51
|
+
SimpleNavigation::Item.new(item_container, key, name, url, options)
|
66
52
|
end
|
67
53
|
end
|
68
54
|
end
|
@@ -59,22 +59,18 @@ module SimpleNavigation
|
|
59
59
|
# set a regexp which is matched againstthe current URI.
|
60
60
|
#
|
61
61
|
# The <tt>block</tt> - if specified - will hold the item's sub_navigation.
|
62
|
-
def item(key, name,
|
63
|
-
options = url_or_options.is_a?(Hash) ? url_or_options : options_or_nil
|
62
|
+
def item(key, name, url = nil, options = {}, &block)
|
64
63
|
return unless should_add_item?(options)
|
65
|
-
|
66
|
-
|
67
|
-
name,
|
68
|
-
url_or_options,
|
69
|
-
options_or_nil,
|
70
|
-
nil,
|
71
|
-
&block)
|
64
|
+
item = Item.new(self, key, name, url, options, &block)
|
65
|
+
add_item item, options
|
72
66
|
end
|
73
67
|
|
74
68
|
def items=(new_items)
|
75
|
-
|
76
|
-
|
77
|
-
|
69
|
+
new_items.each do |item|
|
70
|
+
item_adapter = ItemAdapter.new(item)
|
71
|
+
next unless should_add_item?(item_adapter.options)
|
72
|
+
add_item item_adapter.to_simple_navigation_item(self), item_adapter.options
|
73
|
+
end
|
78
74
|
end
|
79
75
|
|
80
76
|
# Returns the Item with the specified key, nil otherwise.
|
@@ -148,6 +144,19 @@ module SimpleNavigation
|
|
148
144
|
|
149
145
|
private
|
150
146
|
|
147
|
+
def add_item(item, options)
|
148
|
+
items << item
|
149
|
+
modify_dom_attributes(options)
|
150
|
+
end
|
151
|
+
|
152
|
+
def modify_dom_attributes(options)
|
153
|
+
return unless container_options = options[:container]
|
154
|
+
self.dom_attributes = container_options.fetch(:attributes) { dom_attributes }
|
155
|
+
self.dom_class = container_options.fetch(:class) { dom_class }
|
156
|
+
self.dom_id = container_options.fetch(:id) { dom_id }
|
157
|
+
self.selected_class = container_options.fetch(:selected_class) { selected_class }
|
158
|
+
end
|
159
|
+
|
151
160
|
# FIXME: raise an exception if :rederer is a symbol and it is not registred
|
152
161
|
# in SimpleNavigation.registered_renderers
|
153
162
|
def renderer_instance(options)
|
@@ -166,8 +175,8 @@ module SimpleNavigation
|
|
166
175
|
end
|
167
176
|
|
168
177
|
def should_add_item?(options)
|
169
|
-
[options
|
170
|
-
[options
|
178
|
+
[options[:if]].flatten.compact.all? { |m| evaluate_method(m) } &&
|
179
|
+
[options[:unless]].flatten.compact.none? { |m| evaluate_method(m) }
|
171
180
|
end
|
172
181
|
|
173
182
|
def evaluate_method(method)
|
File without changes
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'simple_navigation/helpers'
|
2
|
+
require 'simple_navigation/renderer/base'
|
3
|
+
|
4
|
+
module SimpleNavigation
|
5
|
+
module Renderer
|
6
|
+
autoload :List, 'simple_navigation/renderer/list'
|
7
|
+
autoload :Links, 'simple_navigation/renderer/links'
|
8
|
+
autoload :Breadcrumbs, 'simple_navigation/renderer/breadcrumbs'
|
9
|
+
autoload :Text, 'simple_navigation/renderer/text'
|
10
|
+
autoload :Json, 'simple_navigation/renderer/json'
|
11
|
+
end
|
12
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|