navtastic 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +11 -1
- data/.yardopts +1 -0
- data/CHANGELOG.md +11 -1
- data/README.md +146 -6
- data/docs/bulma_headers_preview.png +0 -0
- data/docs/foundation_styles_preview.png +0 -0
- data/lib/navtastic.rb +17 -1
- data/lib/navtastic/configuration.rb +84 -0
- data/lib/navtastic/item.rb +44 -3
- data/lib/navtastic/menu.rb +52 -9
- data/lib/navtastic/renderer.rb +61 -38
- data/lib/navtastic/renderer/bootstrap4.rb +35 -0
- data/lib/navtastic/renderer/bulma.rb +44 -0
- data/lib/navtastic/renderer/foundation6.rb +58 -0
- data/lib/navtastic/renderer/simple.rb +18 -0
- data/lib/navtastic/version.rb +1 -1
- data/spec/demo/index.rhtml +7 -20
- data/spec/demo/renderer/bootstrap4.rhtml +55 -0
- data/spec/demo/renderer/bulma.rhtml +70 -0
- data/spec/demo/renderer/foundation6.rhtml +81 -0
- data/spec/demo/renderer/simple.rhtml +41 -0
- data/spec/demo/server.rb +21 -10
- data/spec/navtastic/configuration_spec.rb +71 -0
- data/spec/navtastic/item_spec.rb +82 -0
- data/spec/navtastic/menu_spec.rb +107 -3
- data/spec/navtastic/renderer/simple_spec.rb +19 -0
- data/spec/navtastic/renderer_spec.rb +49 -7
- data/spec/navtastic_spec.rb +41 -4
- data/spec/spec_helper.rb +2 -1
- data/spec/support/navtastic_helpers.rb +17 -0
- data/spec/support/{navtastic_store.rb → navtastic_reset.rb} +2 -1
- metadata +25 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f1310ede0cecc3da85ea235b10c6bd7b6413d823
|
4
|
+
data.tar.gz: 7507adc0d81b1e381463fabc7f0a912b24e8b586
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fab8bbf0725908f60ecdd76c50709ea4cff88ccbf43ba30f4cd1d6085b03b4e3baeae5bd18ebec37ba19f8dec5e77a5e4a77c78395ec0a44621c0c049ce1749b
|
7
|
+
data.tar.gz: d315fb9dc68df9e0d827b231421684d9b211611b249a69163fa65b95055c797062286a6935144af2246c33e011ff1d9aef3d75e67c6961c48063c312149eb297
|
data/.rubocop.yml
CHANGED
@@ -6,16 +6,26 @@ AllCops:
|
|
6
6
|
- '**/Rakefile'
|
7
7
|
Exclude:
|
8
8
|
- 'spec/demo/**/*'
|
9
|
+
- 'spec/support/**/*'
|
9
10
|
- 'vendor/**/*'
|
10
11
|
TargetRubyVersion: 2.4
|
11
12
|
|
13
|
+
Metrics/AbcSize:
|
14
|
+
Max: 20
|
15
|
+
|
12
16
|
Metrics/BlockLength:
|
13
17
|
Exclude:
|
14
18
|
- 'spec/**/*_spec.rb'
|
15
|
-
|
19
|
+
|
20
|
+
Metrics/MethodLength:
|
21
|
+
Max: 15
|
16
22
|
|
17
23
|
Style/FrozenStringLiteralComment:
|
18
24
|
Enabled: false
|
19
25
|
|
20
26
|
Style/StringLiterals:
|
21
27
|
Enabled: false
|
28
|
+
|
29
|
+
Style/TrailingCommaInLiteral:
|
30
|
+
EnforcedStyleForMultiline: consistent_comma
|
31
|
+
|
data/.yardopts
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
## [Unreleased]
|
4
4
|
|
5
|
+
## [0.1.0] - 2017-09-05
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
- Configuration options
|
10
|
+
- Base urls
|
11
|
+
- New Renderers: Bootstrap4, Bulma, Foundation 6
|
12
|
+
- Only vertical menus are supported for now
|
13
|
+
|
5
14
|
## 0.0.1 - 2017-08-21
|
6
15
|
|
7
16
|
### Added
|
@@ -11,4 +20,5 @@
|
|
11
20
|
- Highlighting current menu item
|
12
21
|
- Runtime parameters
|
13
22
|
|
14
|
-
[Unreleased]: https://github.com/aramvisser/navtastic/compare/v0.0
|
23
|
+
[Unreleased]: https://github.com/aramvisser/navtastic/compare/v0.1.0...HEAD
|
24
|
+
[0.1.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.1...v0.1.0
|
data/README.md
CHANGED
@@ -3,13 +3,19 @@
|
|
3
3
|
[![Build Status](https://img.shields.io/circleci/project/github/aramvisser/navtastic.svg)](https://circleci.com/gh/aramvisser/navtastic)
|
4
4
|
[![Code Coverage](https://img.shields.io/codeclimate/coverage/github/aramvisser/navtastic.svg)](https://codeclimate.com/github/aramvisser/navtastic)
|
5
5
|
[![Inline docs](https://inch-ci.org/github/aramvisser/navtastic.svg?branch=master)](https://inch-ci.org/github/aramvisser/navtastic)
|
6
|
+
[![Gem](https://img.shields.io/gem/v/navtastic.svg)](https://rubygems.org/gems/navtastic)
|
6
7
|
[![MIT License](https://img.shields.io/github/license/aramvisser/navtastic.svg)](https://github.com/aramvisser/navtastic/blob/master/LICENSE)
|
7
8
|
|
8
|
-
Navtastic is way to create and
|
9
|
-
of menus.
|
9
|
+
Navtastic is way to create and display complex navigation menus for websites. It allows for runtime
|
10
|
+
configurations of menus, depending on context.
|
10
11
|
|
11
12
|
- Keep menu content and rendering logic separate
|
12
13
|
- Automatically highlight the current page
|
14
|
+
- Different output structures supported (Simple, Bootstrap4, Bulma, Foundation6)
|
15
|
+
- HTML structure only, bring your own CSS.
|
16
|
+
- Easily create your own renderer to fit your style.
|
17
|
+
|
18
|
+
_The current renderers only support vertical menus. Horizontal (navbar) menus are planned._
|
13
19
|
|
14
20
|
## Table of Contents
|
15
21
|
|
@@ -18,7 +24,13 @@ of menus.
|
|
18
24
|
- [Documentation](#documentation)
|
19
25
|
- [Submenus](#submenus)
|
20
26
|
- [Current item](#current-item)
|
27
|
+
- [Custom classes](#custom-classes)
|
21
28
|
- [Runtime parameters](#runtime-parameters)
|
29
|
+
- [Global Configuration](#global-configuration)
|
30
|
+
- [Menu Configuration](#menu-configuration)
|
31
|
+
- [Item Configuration](#item-configuration)
|
32
|
+
- [Renderers](#renderers)
|
33
|
+
- [Development](#development)
|
22
34
|
|
23
35
|
## Installation
|
24
36
|
|
@@ -36,7 +48,7 @@ bundle install
|
|
36
48
|
|
37
49
|
## Example
|
38
50
|
|
39
|
-
Define a menu
|
51
|
+
Define a menu somewhere:
|
40
52
|
|
41
53
|
```ruby
|
42
54
|
Navtastic.define :main_menu do |menu|
|
@@ -70,9 +82,9 @@ Using the default renderer, assuming that the current url starts with `/posts`,
|
|
70
82
|
|
71
83
|
## Documentation
|
72
84
|
|
73
|
-
|
85
|
+
### Submenus
|
74
86
|
|
75
|
-
Every item can have a submenu. They can be nested as deeply as you want
|
87
|
+
Every item can have a submenu. They can be nested as deeply as you want.
|
76
88
|
|
77
89
|
```ruby
|
78
90
|
Navtastic.define :main_menu do |menu|
|
@@ -117,7 +129,7 @@ For example, if there is a menu containing these urls:
|
|
117
129
|
If the current_url is `/posts/featured/2017`, the `/posts/featured` item will be highlighted. If the
|
118
130
|
current_url is `/posts/123`, then `/posts` is highlighted.
|
119
131
|
|
120
|
-
The root url `/` will always match, if no other items match the current
|
132
|
+
The root url `/` will always match, if no other items match the current url. If there is no item
|
121
133
|
with `/` as url in the menu and no other urls match, nothing will be highlighted.
|
122
134
|
|
123
135
|
### Runtime parameters
|
@@ -141,3 +153,131 @@ end
|
|
141
153
|
# Render it with the current user as a parameter
|
142
154
|
Navtastic.render :main_menu, current_url, current_user: User.current
|
143
155
|
```
|
156
|
+
|
157
|
+
### Global Configuration
|
158
|
+
|
159
|
+
Some global settings that Navtastic uses can be configured. Make sure the configuration happens
|
160
|
+
before defining any menu (e.g. when using rails, add it to `config/initializers/navtastic.rb`).
|
161
|
+
|
162
|
+
These are the defaults values:
|
163
|
+
|
164
|
+
```ruby
|
165
|
+
Navtastic.configure do |config|
|
166
|
+
# This url to prepend before every item url
|
167
|
+
config.base_url = nil
|
168
|
+
|
169
|
+
# Set the renderer to use, can be one of :simple, :bootstrap4, :bulma, :foundation6
|
170
|
+
# Can also be a class if you want to use a custom renderer
|
171
|
+
config.renderer = :simple
|
172
|
+
|
173
|
+
# Options that are passed to the renderer
|
174
|
+
config.renderer_options = {}
|
175
|
+
end
|
176
|
+
```
|
177
|
+
|
178
|
+
### Menu Configuration
|
179
|
+
|
180
|
+
Each individual menu can also be configured in some way:
|
181
|
+
|
182
|
+
```ruby
|
183
|
+
Navtastic.define :user_menu do |menu, params|
|
184
|
+
# The url to put before every item
|
185
|
+
menu.config.base_url = '/users/' + params[:user_id]
|
186
|
+
|
187
|
+
menu.item "Profile", '/profile' # will link to: /users/123/profile
|
188
|
+
end
|
189
|
+
```
|
190
|
+
|
191
|
+
### Item Configuration
|
192
|
+
|
193
|
+
Every item can have options passed to it:
|
194
|
+
|
195
|
+
```ruby
|
196
|
+
Navtastic.define :menu do |menu|
|
197
|
+
# Add a css class to the container (e.g. <li> tag)
|
198
|
+
menu.item "Home", "/", class: 'highlight'
|
199
|
+
|
200
|
+
# Add a css class the content inside the container (e.g. <a> tag)
|
201
|
+
menu.item "Posts", "/posts", content_class: 'important'
|
202
|
+
|
203
|
+
# If `root` is true, this item will ignore any base urls
|
204
|
+
menu.item "Somewhere", '/', root: true
|
205
|
+
|
206
|
+
# Use the item url as the base_url for the submenu
|
207
|
+
menu.item "Settings", '/settings', base_url: true do |submenu|
|
208
|
+
# submenu.config.base_url is now set to '/settings'
|
209
|
+
end
|
210
|
+
end
|
211
|
+
```
|
212
|
+
|
213
|
+
### Renderers
|
214
|
+
|
215
|
+
The following renders are currently available:
|
216
|
+
|
217
|
+
- **Simple** adds a `current` class to the basic list structure
|
218
|
+
- **Bootstrap4** is used with the [Bootstrap 4](https://getbootstrap.com) framework.
|
219
|
+
- **Bulma** is used with the [Bulma.io](http://bulma.io) framework.
|
220
|
+
- **Foundation6** is used with the [Foundation 6](http://foundation.zurb.com/sites.html) framework.
|
221
|
+
|
222
|
+
Some renderers also support extra options. You can set them globally in the configuration or pass
|
223
|
+
them at runtime when rendering a menu:
|
224
|
+
|
225
|
+
```ruby
|
226
|
+
# Global options
|
227
|
+
Navtastic.configure do |config|
|
228
|
+
config.renderer_options = { option: value }
|
229
|
+
end
|
230
|
+
```
|
231
|
+
|
232
|
+
```erb
|
233
|
+
# Runtime options
|
234
|
+
<%= Navtastic.render :menu, current_url, renderer: { option: value } %>
|
235
|
+
```
|
236
|
+
|
237
|
+
Globally defined options and options given at runtime are merged together, with those at runtime
|
238
|
+
taking precedence.
|
239
|
+
|
240
|
+
#### Bulma Configuration
|
241
|
+
|
242
|
+
- **headers** (default: `false`)
|
243
|
+
|
244
|
+
Top level items are styled differently. Works best if they are only text, not
|
245
|
+
links.
|
246
|
+
|
247
|
+
<div align="center">
|
248
|
+
<figure>
|
249
|
+
<img src="docs/bulma_headers_preview.png"><br>
|
250
|
+
<figcaption>left: <code>headers: false</code>, right: <code>headers: true</code></legend>
|
251
|
+
</figure>
|
252
|
+
</div>
|
253
|
+
|
254
|
+
#### Foundation Configuration
|
255
|
+
|
256
|
+
- **active_class** (default: `nil`)
|
257
|
+
|
258
|
+
CSS class to use for active items. Active items are items that have a child that is the current
|
259
|
+
item. Useful to highlight the current item in a drilldown menu.
|
260
|
+
|
261
|
+
- **style** (default: `nil`)
|
262
|
+
|
263
|
+
Set to `:drilldown` to generate [a drilldown
|
264
|
+
menu](http://foundation.zurb.com/sites/docs/drilldown-menu.html). Make sure you include the
|
265
|
+
required javascript files.
|
266
|
+
|
267
|
+
<div align="center">
|
268
|
+
<figure>
|
269
|
+
<img src="docs/foundation_styles_preview.png"><br>
|
270
|
+
<figcaption>left: default style, right: drilldown style</figcaption>
|
271
|
+
</figure>
|
272
|
+
</div>
|
273
|
+
|
274
|
+
## Development
|
275
|
+
|
276
|
+
1. Checkout Repository: `git clone https://github.com/aramvisser/navtastic.git`
|
277
|
+
2. Install Bundler: `gem install bundler`
|
278
|
+
3. Run `bundle install` inside the project root to install the gem dependencies
|
279
|
+
4. Run test cases: `bundle exec rake`
|
280
|
+
|
281
|
+
For testing visual changes, a test server is provided by running `bundle exec rake demo`. It's
|
282
|
+
accessibly on http://localhost:9090.
|
283
|
+
|
Binary file
|
Binary file
|
data/lib/navtastic.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
|
+
require 'navtastic/configuration'
|
1
2
|
require 'navtastic/item'
|
2
3
|
require 'navtastic/menu'
|
3
4
|
require 'navtastic/renderer'
|
5
|
+
require 'navtastic/renderer/bootstrap4'
|
6
|
+
require 'navtastic/renderer/bulma'
|
7
|
+
require 'navtastic/renderer/foundation6'
|
8
|
+
require 'navtastic/renderer/simple'
|
4
9
|
require 'navtastic/version'
|
5
10
|
|
6
11
|
# Main module containing some convenience methods
|
@@ -33,9 +38,16 @@ module Navtastic
|
|
33
38
|
|
34
39
|
# Render a stored menu
|
35
40
|
#
|
41
|
+
# The `params` parameter is passed along to the block in {Navtastic.define}.
|
42
|
+
#
|
43
|
+
# If `params` contains a `:renderer` key, it's removed from the hash and
|
44
|
+
# passed to the renderer instead. Look at the renderer documentation to see
|
45
|
+
# which options are supported.
|
46
|
+
#
|
36
47
|
# @param name the name of the defined menu
|
37
48
|
# @param current_url [String] the url of the current page
|
38
49
|
# @param params [Hash] runtime parameters
|
50
|
+
# @option params [Hash] :renderer Options passed to the renderer
|
39
51
|
#
|
40
52
|
# @raise [KeyError] if the menu was not defined
|
41
53
|
#
|
@@ -46,10 +58,14 @@ module Navtastic
|
|
46
58
|
|
47
59
|
raise KeyError, "menu not defined: #{name.inspect}" if block.nil?
|
48
60
|
|
61
|
+
# Merge renderer options globally with those passed at runtime
|
62
|
+
renderer_options = configuration.renderer_options
|
63
|
+
renderer_options.merge!(params.delete(:renderer) || {})
|
64
|
+
|
49
65
|
menu = Menu.new
|
50
66
|
block.call(menu, params)
|
51
67
|
menu.current_url = current_url
|
52
|
-
|
68
|
+
Navtastic.configuration.renderer.render(menu, renderer_options)
|
53
69
|
end
|
54
70
|
|
55
71
|
# A list of all defined menus
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Navtastic # :nodoc:
|
2
|
+
# Configuration settings
|
3
|
+
class Configuration
|
4
|
+
# The base url will be prepended to every item url
|
5
|
+
#
|
6
|
+
# Defaults to nil.
|
7
|
+
#
|
8
|
+
# @return [String,nil]
|
9
|
+
|
10
|
+
attr_accessor :base_url
|
11
|
+
# The default renderer to use when displaying a menu
|
12
|
+
#
|
13
|
+
# Defaults to {Navtastic::Renderer::Simple}.
|
14
|
+
#
|
15
|
+
# @return any class that responds to the `.render` method
|
16
|
+
attr_reader :renderer
|
17
|
+
|
18
|
+
# Default options passed to the current renderer
|
19
|
+
#
|
20
|
+
# Defaults to empty Hash.
|
21
|
+
#
|
22
|
+
# @return [Hash]
|
23
|
+
attr_accessor :renderer_options
|
24
|
+
|
25
|
+
def initialize
|
26
|
+
@renderer = Navtastic::Renderer::Simple
|
27
|
+
@renderer_options = {}
|
28
|
+
@base_url = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
# Set the renderer to use for displaying a menu
|
32
|
+
#
|
33
|
+
# @param value [Symbol,Class]
|
34
|
+
def renderer=(value)
|
35
|
+
if value.is_a? Symbol
|
36
|
+
renderers = available_renderers
|
37
|
+
|
38
|
+
unless renderers.key? value
|
39
|
+
raise ArgumentError, "Unknown renderer: #{value}"
|
40
|
+
end
|
41
|
+
|
42
|
+
@renderer = renderers[value]
|
43
|
+
else
|
44
|
+
@renderer = value
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
# Built in renderers
|
51
|
+
#
|
52
|
+
# @return Hash
|
53
|
+
def available_renderers
|
54
|
+
{
|
55
|
+
bootstrap4: Renderer::Bootstrap4,
|
56
|
+
bulma: Renderer::Bulma,
|
57
|
+
foundation6: Renderer::Foundation6,
|
58
|
+
simple: Renderer::Simple,
|
59
|
+
}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [Navtastic::Configuration] current configuration
|
64
|
+
def self.configuration
|
65
|
+
@configuration ||= Configuration.new
|
66
|
+
end
|
67
|
+
|
68
|
+
# This will reset the configuration back to defaults
|
69
|
+
def self.reset_configuration
|
70
|
+
@configuration = nil
|
71
|
+
end
|
72
|
+
|
73
|
+
# Modify Navtastic's current configuration
|
74
|
+
#
|
75
|
+
# @example Modify the current configuration
|
76
|
+
# Navtastic.configure do |config|
|
77
|
+
# config.setting = :updated
|
78
|
+
# end
|
79
|
+
#
|
80
|
+
# @yieldparam [Navtastic::Configuration] current Navtastic configuration
|
81
|
+
def self.configure
|
82
|
+
yield configuration
|
83
|
+
end
|
84
|
+
end
|
data/lib/navtastic/item.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
module Navtastic
|
2
2
|
# A single menu item
|
3
3
|
class Item
|
4
|
+
# @return [Menu] the containing menu
|
5
|
+
attr_reader :menu
|
6
|
+
|
4
7
|
# @return [String] the name to be displayed in the menu
|
5
8
|
attr_reader :name
|
6
9
|
|
7
|
-
# @return [
|
8
|
-
attr_reader :
|
10
|
+
# @return [Hash] extra options to configure individual items
|
11
|
+
attr_reader :options
|
9
12
|
|
10
13
|
# @return [Menu,nil] the submenu of this item, if defined
|
11
14
|
attr_accessor :submenu
|
@@ -19,10 +22,12 @@ module Navtastic
|
|
19
22
|
# @param menu [Menu] the menu this items belongs to
|
20
23
|
# @param name [String] the name to display when rendering
|
21
24
|
# @param url [String] the url to link to, if the item is a link
|
22
|
-
|
25
|
+
# @param options [Hash] extra configuration options
|
26
|
+
def initialize(menu, name, url = nil, options = {})
|
23
27
|
@menu = menu
|
24
28
|
@name = name
|
25
29
|
@url = url
|
30
|
+
@options = options
|
26
31
|
|
27
32
|
@submenu = nil
|
28
33
|
end
|
@@ -37,6 +42,21 @@ module Navtastic
|
|
37
42
|
@menu.current_item == self
|
38
43
|
end
|
39
44
|
|
45
|
+
# Check if the item has a current child in its submenu (or deeper)
|
46
|
+
#
|
47
|
+
# Also returns true if this is the current item.
|
48
|
+
#
|
49
|
+
# @see file:README.md#Current_item documentation on how the current item is
|
50
|
+
# selected
|
51
|
+
#
|
52
|
+
# @return [Bool] if the item is the current item
|
53
|
+
def active?
|
54
|
+
return true if current?
|
55
|
+
return false unless submenu
|
56
|
+
|
57
|
+
submenu.items.any?(&:active?)
|
58
|
+
end
|
59
|
+
|
40
60
|
# @return [Bool] true if the item has a submenu, false other
|
41
61
|
def submenu?
|
42
62
|
!@submenu.nil?
|
@@ -45,5 +65,26 @@ module Navtastic
|
|
45
65
|
def inspect
|
46
66
|
"#<Item \"#{name}\" [#{url}] current?:#{current?}>"
|
47
67
|
end
|
68
|
+
|
69
|
+
# Check if item has a link or not
|
70
|
+
#
|
71
|
+
# @return [Bool]
|
72
|
+
def url?
|
73
|
+
!@url.nil?
|
74
|
+
end
|
75
|
+
|
76
|
+
# The url for this item, if the item has a url
|
77
|
+
#
|
78
|
+
# Will prepend the `base_url` for the menu if it is present
|
79
|
+
#
|
80
|
+
# @return [String,nil]
|
81
|
+
def url
|
82
|
+
return nil unless url?
|
83
|
+
return @url if options[:root]
|
84
|
+
|
85
|
+
url = "#{@menu.base_url}#{@url}"
|
86
|
+
url.chomp!('/') unless url == '/'
|
87
|
+
url
|
88
|
+
end
|
48
89
|
end
|
49
90
|
end
|