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
@@ -0,0 +1,55 @@
|
|
1
|
+
<%
|
2
|
+
Navtastic.configure do |config|
|
3
|
+
config.renderer = Navtastic::Renderer::Bootstrap4
|
4
|
+
end
|
5
|
+
|
6
|
+
Navtastic.define :main_menu do |menu|
|
7
|
+
menu.item "General" do |generalmenu|
|
8
|
+
generalmenu.item "Dashboard", '/'
|
9
|
+
generalmenu.item "Customers", '/customers'
|
10
|
+
end
|
11
|
+
|
12
|
+
menu.item "Administration" do |adminmenu|
|
13
|
+
adminmenu.item "Team Settings", '/team'
|
14
|
+
adminmenu.item "Manage Your Team", '/manage' do |teammenu|
|
15
|
+
teammenu.item "Members", '/manage/members/'
|
16
|
+
teammenu.item "Plugins", '/manage/plugins'
|
17
|
+
teammenu.item "Add a member", '/manage/members/new'
|
18
|
+
end
|
19
|
+
adminmenu.item "Invitations", '/invitations'
|
20
|
+
adminmenu.item "Cloud Storage Environment Settings", '/cloud'
|
21
|
+
adminmenu.item "Authentication", '/authentication'
|
22
|
+
end
|
23
|
+
|
24
|
+
menu.item "Other renderers" do |rendermenu|
|
25
|
+
rendermenu.item "Overview", '/', root: true
|
26
|
+
rendermenu.item "Simple", '/simple', root: true
|
27
|
+
rendermenu.item "Bulma", '/bulma', root: true
|
28
|
+
rendermenu.item "Foundation6", '/foundation6', root: true
|
29
|
+
end
|
30
|
+
|
31
|
+
menu.config.base_url = '/bootstrap4'
|
32
|
+
end
|
33
|
+
%>
|
34
|
+
|
35
|
+
<html>
|
36
|
+
<head>
|
37
|
+
<title>Navtastic Bootstrap4 Renderer</title>
|
38
|
+
|
39
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta/css/bootstrap.min.css">
|
40
|
+
|
41
|
+
<style>
|
42
|
+
a.active {
|
43
|
+
font-weight: bold;
|
44
|
+
}
|
45
|
+
|
46
|
+
ul.nav ul {
|
47
|
+
margin-left: 2rem;
|
48
|
+
}
|
49
|
+
</style>
|
50
|
+
</head>
|
51
|
+
|
52
|
+
<body>
|
53
|
+
<%= Navtastic.render :main_menu, current_url %>
|
54
|
+
</body>
|
55
|
+
</html>
|
@@ -0,0 +1,70 @@
|
|
1
|
+
<%
|
2
|
+
Navtastic.configure do |config|
|
3
|
+
config.renderer = Navtastic::Renderer::Bulma
|
4
|
+
end
|
5
|
+
|
6
|
+
Navtastic.define :main_menu do |menu|
|
7
|
+
menu.item "General" do |generalmenu|
|
8
|
+
generalmenu.item "Dashboard", '/'
|
9
|
+
generalmenu.item "Customers", '/customers'
|
10
|
+
end
|
11
|
+
|
12
|
+
menu.item "Administration" do |adminmenu|
|
13
|
+
adminmenu.item "Team Settings", '/team'
|
14
|
+
adminmenu.item "Manage Your Team", '/manage' do |teammenu|
|
15
|
+
teammenu.item "Members", '/manage/members'
|
16
|
+
teammenu.item "Plugins", '/manage/plugins'
|
17
|
+
teammenu.item "Add a member", '/manage/members/new'
|
18
|
+
end
|
19
|
+
adminmenu.item "Invitations", '/invitations'
|
20
|
+
adminmenu.item "Cloud Storage Environment Settings", '/cloud'
|
21
|
+
adminmenu.item "Authentication", '/authentication'
|
22
|
+
end
|
23
|
+
|
24
|
+
menu.item "Other renderers" do |rendermenu|
|
25
|
+
rendermenu.item "Overview", '/', root: true
|
26
|
+
rendermenu.item "Simple", '/simple', root: true
|
27
|
+
rendermenu.item "Bootstrap4", '/bootstrap4', root: true
|
28
|
+
rendermenu.item "Foundation6", '/foundation6', root: true
|
29
|
+
end
|
30
|
+
|
31
|
+
menu.config.base_url = '/bulma'
|
32
|
+
end
|
33
|
+
%>
|
34
|
+
|
35
|
+
<html>
|
36
|
+
<head>
|
37
|
+
<title>Navtastic Bulma Renderer</title>
|
38
|
+
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.5.1/css/bulma.css">
|
39
|
+
</head>
|
40
|
+
|
41
|
+
<body>
|
42
|
+
<div class="container">
|
43
|
+
<div class="content">
|
44
|
+
Menu example is taken directly from <a href="http://bulma.io/documentation/components/menu/">the Bulma documentation</a>.
|
45
|
+
</div>
|
46
|
+
<div class="columns">
|
47
|
+
<div class="column">
|
48
|
+
<div class="content">
|
49
|
+
<h1 class="title">Without headers option</h1>
|
50
|
+
<code>Navtastic.render :main_menu, current_url</code>
|
51
|
+
</div>
|
52
|
+
<div style="max-width: 300px">
|
53
|
+
<%= Navtastic.render :main_menu, current_url %>
|
54
|
+
</div>
|
55
|
+
</div>
|
56
|
+
|
57
|
+
<div class="column">
|
58
|
+
<div class="content">
|
59
|
+
<h1 class="title">With headers option</h1>
|
60
|
+
<code>Navtastic.render :main_menu, current_url, renderer: { headers: true }</code>
|
61
|
+
</div>
|
62
|
+
<div style="max-width: 300px">
|
63
|
+
<%= Navtastic.render :main_menu, current_url, renderer: { headers: true } %>
|
64
|
+
</div>
|
65
|
+
</div>
|
66
|
+
</div>
|
67
|
+
|
68
|
+
<pre>current_url: <%= current_url %></pre>
|
69
|
+
</body>
|
70
|
+
</html>
|
@@ -0,0 +1,81 @@
|
|
1
|
+
<%
|
2
|
+
Navtastic.configure do |config|
|
3
|
+
config.renderer = Navtastic::Renderer::Foundation6
|
4
|
+
end
|
5
|
+
|
6
|
+
Navtastic.define :main_menu do |menu|
|
7
|
+
menu.item "General" do |generalmenu|
|
8
|
+
generalmenu.item "Dashboard", ''
|
9
|
+
generalmenu.item "Customers", '/customers'
|
10
|
+
end
|
11
|
+
|
12
|
+
menu.item "Administration" do |adminmenu|
|
13
|
+
adminmenu.item "Team Settings", '/team'
|
14
|
+
adminmenu.item "Manage Your Team", '/manage' do |teammenu|
|
15
|
+
teammenu.item "Members", '/manage/members'
|
16
|
+
teammenu.item "Plugins", '/manage/plugins'
|
17
|
+
teammenu.item "Add a member", '/manage/members/new'
|
18
|
+
end
|
19
|
+
adminmenu.item "Invitations", '/invitations'
|
20
|
+
adminmenu.item "Cloud Storage Environment Settings", '/cloud'
|
21
|
+
adminmenu.item "Authentication", '/authentication'
|
22
|
+
end
|
23
|
+
|
24
|
+
menu.item "Other renderers" do |rendermenu|
|
25
|
+
rendermenu.item "Overview", '/', root: true
|
26
|
+
rendermenu.item "Simple", '/simple', root: true
|
27
|
+
rendermenu.item "Bootstrap4", '/bootstrap4', root: true
|
28
|
+
rendermenu.item "Bulma", '/bulma', root: true
|
29
|
+
end
|
30
|
+
|
31
|
+
menu.config.base_url = '/foundation6'
|
32
|
+
end
|
33
|
+
%>
|
34
|
+
|
35
|
+
<html>
|
36
|
+
<head>
|
37
|
+
<title>Navtastic Foundation6 Renderer</title>
|
38
|
+
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.0/css/foundation.min.css">
|
39
|
+
|
40
|
+
<style>
|
41
|
+
.is-selected {
|
42
|
+
font-weight: bold;
|
43
|
+
}
|
44
|
+
</style>
|
45
|
+
</head>
|
46
|
+
|
47
|
+
<body>
|
48
|
+
<div class="grid-container">
|
49
|
+
<p>Menu example is taken directly from <a href="http://bulma.io/documentation/components/menu/">the Bulma documentation</a>.</p>
|
50
|
+
|
51
|
+
<div class="grid-x">
|
52
|
+
<div class="auto cell">
|
53
|
+
<h1>Default style</h1>
|
54
|
+
<code>{}</code>
|
55
|
+
|
56
|
+
<div style="width: 300px">
|
57
|
+
<%= Navtastic.render :main_menu, current_url %>
|
58
|
+
</div>
|
59
|
+
</div>
|
60
|
+
|
61
|
+
<div class="auto cell">
|
62
|
+
<h1>Drilldown style</h1>
|
63
|
+
<code>{ style: :drilldown, active_class: 'is-selected' }</code>
|
64
|
+
|
65
|
+
<div style="width: 300px">
|
66
|
+
<%= Navtastic.render :main_menu, current_url, renderer: { style: :drilldown, active_class: 'is-selected' } %>
|
67
|
+
</div>
|
68
|
+
</div>
|
69
|
+
</div>
|
70
|
+
</div>
|
71
|
+
|
72
|
+
<pre>current_url: <%= current_url %></pre>
|
73
|
+
|
74
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
|
75
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/js/foundation.min.js"></script>
|
76
|
+
|
77
|
+
<script>
|
78
|
+
$(document).foundation();
|
79
|
+
</script>
|
80
|
+
</body>
|
81
|
+
</html>
|
@@ -0,0 +1,41 @@
|
|
1
|
+
<%
|
2
|
+
Navtastic.configure do |config|
|
3
|
+
config.renderer = Navtastic::Renderer::Simple
|
4
|
+
end
|
5
|
+
|
6
|
+
Navtastic.define :main_menu do |menu|
|
7
|
+
menu.item "Home", '/' do |submenu|
|
8
|
+
submenu.item "Posts", '/posts'
|
9
|
+
submenu.item "About", '/about'
|
10
|
+
end
|
11
|
+
|
12
|
+
menu.item "Settings" do |submenu|
|
13
|
+
submenu.item "General", '/settings'
|
14
|
+
submenu.item "Profile", '/settings/profile'
|
15
|
+
end
|
16
|
+
|
17
|
+
menu.item "Other Renderers", '/' do |submenu|
|
18
|
+
submenu.item "Bootstrap4", '/bootstrap4', root: true
|
19
|
+
submenu.item "Bulma", '/bulma', root: true
|
20
|
+
submenu.item "Foundation6", '/foundation6', root: true
|
21
|
+
end
|
22
|
+
|
23
|
+
menu.config.base_url = '/simple'
|
24
|
+
end
|
25
|
+
%>
|
26
|
+
|
27
|
+
<html>
|
28
|
+
<head>
|
29
|
+
<title>Navtastic Simple Renderer</title>
|
30
|
+
<style type="text/css">
|
31
|
+
.current { font-weight: bold }
|
32
|
+
.current ul { font-weight: normal }
|
33
|
+
</style>
|
34
|
+
</head>
|
35
|
+
|
36
|
+
<body>
|
37
|
+
<%= Navtastic.render :main_menu, current_url %>
|
38
|
+
|
39
|
+
<pre>current_url: <%= current_url %></pre>
|
40
|
+
</body>
|
41
|
+
</html>
|
data/spec/demo/server.rb
CHANGED
@@ -14,7 +14,7 @@ class DemoServer
|
|
14
14
|
# A poor man's hot reload. Just reload everything on every request.
|
15
15
|
Object.send(:remove_const, :Navtastic) if Object.constants.include?(:Navtastic)
|
16
16
|
|
17
|
-
Dir.glob('lib/**/*.rb').each do |file|
|
17
|
+
Dir.glob('lib/**/*.rb').sort_by(&:length).each do |file|
|
18
18
|
load file
|
19
19
|
end
|
20
20
|
end
|
@@ -23,12 +23,15 @@ class DemoServer
|
|
23
23
|
WEBrick::HTTPUtils::DefaultMimeTypes.store('rhtml', 'text/html')
|
24
24
|
|
25
25
|
# Mount servlets
|
26
|
-
|
27
|
-
s.mount '/',
|
26
|
+
s.mount '/', WEBrick::HTTPServlet::ERBHandler, File.expand_path('../index.rhtml', __FILE__)
|
27
|
+
s.mount '/simple', RendererServlet, :simple
|
28
|
+
s.mount '/bootstrap4', RendererServlet, :bootstrap4
|
29
|
+
s.mount '/bulma', RendererServlet, :bulma
|
30
|
+
s.mount '/foundation6', RendererServlet, :foundation6
|
28
31
|
|
29
32
|
# Trap signals so as to shutdown cleanly.
|
30
33
|
['TERM', 'INT'].each do |signal|
|
31
|
-
trap(signal){ s.shutdown }
|
34
|
+
trap(signal) { s.shutdown }
|
32
35
|
end
|
33
36
|
|
34
37
|
# Start the server and block on input.
|
@@ -36,19 +39,27 @@ class DemoServer
|
|
36
39
|
end
|
37
40
|
end
|
38
41
|
|
39
|
-
class
|
42
|
+
class RendererServlet < WEBrick::HTTPServlet::AbstractServlet
|
43
|
+
def initialize(server, renderer)
|
44
|
+
@renderer = renderer
|
45
|
+
end
|
46
|
+
|
40
47
|
def do_GET(request, response)
|
48
|
+
@request = request
|
49
|
+
|
41
50
|
response.status = 200
|
42
51
|
response['Content-Type'] = 'text/html'
|
43
|
-
response.body = render_page
|
52
|
+
response.body = render_page
|
44
53
|
end
|
45
54
|
|
46
|
-
def render_page
|
47
|
-
template_file = File.expand_path(
|
55
|
+
def render_page
|
56
|
+
template_file = File.expand_path("../renderer/#{@renderer}.rhtml", __FILE__)
|
48
57
|
template_string = File.read template_file
|
49
58
|
|
50
|
-
current_url = request.path
|
51
|
-
|
52
59
|
ERB.new(template_string).result(binding)
|
53
60
|
end
|
61
|
+
|
62
|
+
def current_url
|
63
|
+
@request.path
|
64
|
+
end
|
54
65
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Navtastic::Configuration do
|
4
|
+
describe '.new' do
|
5
|
+
subject(:configuration) { described_class.new }
|
6
|
+
|
7
|
+
expected_defaults = {
|
8
|
+
base_url: nil,
|
9
|
+
renderer: Navtastic::Renderer::Simple,
|
10
|
+
renderer_options: {},
|
11
|
+
}
|
12
|
+
|
13
|
+
expected_defaults.each do |key, value|
|
14
|
+
context "##{key}" do
|
15
|
+
it "defaults to #{value}" do
|
16
|
+
expect(configuration.send(key)).to eq value
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '.reset_configuration' do
|
23
|
+
before { set_configuration renderer: :bulma }
|
24
|
+
|
25
|
+
it "sets the configuration values back to default" do
|
26
|
+
expect { Navtastic.reset_configuration }
|
27
|
+
.to change { Navtastic.configuration.renderer }
|
28
|
+
.from(Navtastic::Renderer::Bulma)
|
29
|
+
.to(Navtastic::Renderer::Simple)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '.configure' do
|
34
|
+
specify do
|
35
|
+
expect { |b| Navtastic.configure(&b) }.to yield_with_args(described_class)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#renderer=' do
|
40
|
+
subject(:renderer_config) do
|
41
|
+
configuration.renderer = renderer
|
42
|
+
configuration.renderer
|
43
|
+
end
|
44
|
+
|
45
|
+
let(:configuration) { described_class.new }
|
46
|
+
|
47
|
+
context "when the renderer parameter is a class" do
|
48
|
+
let(:renderer) { Navtastic::Renderer::Simple }
|
49
|
+
|
50
|
+
it "sets the renderer to that class" do
|
51
|
+
expect(renderer_config).to eq renderer
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "when the renderer is a known symbol" do
|
56
|
+
let(:renderer) { :bulma }
|
57
|
+
|
58
|
+
it "sets the renderer to the class for that symbol" do
|
59
|
+
expect(renderer_config).to eq Navtastic::Renderer::Bulma
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "when the renderer is not a known symbol" do
|
64
|
+
let(:renderer) { :foo }
|
65
|
+
|
66
|
+
it "raises an argument error" do
|
67
|
+
expect { renderer_config }.to raise_error ArgumentError
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/spec/navtastic/item_spec.rb
CHANGED
@@ -11,4 +11,86 @@ RSpec.describe Navtastic::Item do
|
|
11
11
|
expect(menu).to have_received :current_item
|
12
12
|
end
|
13
13
|
end
|
14
|
+
|
15
|
+
describe '#active?' do
|
16
|
+
subject { item.active? }
|
17
|
+
|
18
|
+
let(:menu) do
|
19
|
+
menu = Navtastic::Menu.new
|
20
|
+
menu.item "Root", '/' do |submenu|
|
21
|
+
submenu.item "Sub", '/sub'
|
22
|
+
end
|
23
|
+
menu.item "Foo", '/foo'
|
24
|
+
menu.current_url = current_url
|
25
|
+
menu
|
26
|
+
end
|
27
|
+
|
28
|
+
context "when the item has an active child" do
|
29
|
+
let(:item) { menu['/'] }
|
30
|
+
let(:current_url) { '/sub' }
|
31
|
+
|
32
|
+
it { is_expected.to eq true }
|
33
|
+
end
|
34
|
+
|
35
|
+
context "when the item does not have an active child" do
|
36
|
+
let(:item) { menu['/'] }
|
37
|
+
let(:current_url) { '/foo' }
|
38
|
+
|
39
|
+
it { is_expected.to eq false }
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when the item has no submenu" do
|
43
|
+
let(:item) { menu['/sub'] }
|
44
|
+
let(:current_url) { '/' }
|
45
|
+
|
46
|
+
it { is_expected.to eq false }
|
47
|
+
end
|
48
|
+
|
49
|
+
context "when the item is the current item" do
|
50
|
+
let(:item) { menu[current_url] }
|
51
|
+
let(:current_url) { '/' }
|
52
|
+
|
53
|
+
it { is_expected.to eq true }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '#url' do
|
58
|
+
subject(:url) { item.url }
|
59
|
+
|
60
|
+
let(:menu) { Navtastic::Menu.new }
|
61
|
+
|
62
|
+
context "when the item has a url" do
|
63
|
+
let(:item) { menu.item "A", '/a' }
|
64
|
+
|
65
|
+
it "returns that url" do
|
66
|
+
expect(url).to eq '/a'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "when the item doesn't have a url" do
|
71
|
+
let(:item) { menu.item "A" }
|
72
|
+
|
73
|
+
it { is_expected.to eq nil }
|
74
|
+
end
|
75
|
+
|
76
|
+
context "when the the menu has a base_url" do
|
77
|
+
before { menu.config.base_url = '/admin' }
|
78
|
+
|
79
|
+
let(:item) { menu.item "Settings", '/settings' }
|
80
|
+
|
81
|
+
it "prepends the base url to the item" do
|
82
|
+
expect(url).to eq '/admin/settings'
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context "when the item is set to be as root" do
|
87
|
+
before { menu.config.base_url = '/admin' }
|
88
|
+
|
89
|
+
let(:item) { menu.item "Home", '/home', root: true }
|
90
|
+
|
91
|
+
it "doesn't prepend the base url to the item" do
|
92
|
+
expect(url).to eq '/home'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
14
96
|
end
|