simple-navigation 3.13.0 → 4.0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|