navtastic 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f71489809ad37489fff943b48ecc3c00224a7d5d
4
+ data.tar.gz: 8d52c7216084c2e84d620ae1f94b7464fc4c68ad
5
+ SHA512:
6
+ metadata.gz: c9a022d6a93b60adbc98dfed4d8fe26b9a9b4d35c6ac1e37a83e9a6c511cd4c021ed15e5fd4cc6871d40c585b032b13e6062c503550d11892fdccf7802d69015
7
+ data.tar.gz: 6b3678f6e320f10eab9f158845ec34cdb634f0b3babe35fa9c7649dfd907148a348438b6a7febb60bfef866fe185e76fe8225ff3b0b1cf0dc1b251750a9c7b85
@@ -0,0 +1,70 @@
1
+ # Ruby CircleCI 2.0 configuration file
2
+ #
3
+ # Check https://circleci.com/docs/2.0/language-ruby/ for more details
4
+ #
5
+ version: 2
6
+ jobs:
7
+ build:
8
+ docker:
9
+ # specify the version you desire here
10
+ - image: circleci/ruby:2.4.1
11
+
12
+ # Specify service dependencies here if necessary
13
+ # CircleCI maintains a library of pre-built images
14
+ # documented at https://circleci.com/docs/2.0/circleci-images/
15
+ # - image: circleci/postgres:9.4
16
+
17
+ working_directory: ~/navtastic
18
+
19
+ steps:
20
+ - checkout
21
+
22
+ - run:
23
+ name: install dependencies
24
+ command: |
25
+ echo "gem 'rspec_junit_formatter'" >> Gemfile
26
+ echo "gem 'rubocop-junit-formatter'" >> Gemfile
27
+ echo "gem 'simplecov', require: false" >> Gemfile
28
+
29
+ bundle install --jobs=4 --retry=3 --path vendor/bundle
30
+
31
+ - run:
32
+ name: install code climate test reporter
33
+ command: |
34
+ curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
35
+ chmod +x ./cc-test-reporter
36
+ sudo mkdir -p $CIRCLE_TEST_REPORTS/phpunit
37
+
38
+ # run tests!
39
+ - run:
40
+ name: run tests
41
+ command: |
42
+ mkdir /tmp/test-results
43
+
44
+ ./cc-test-reporter before-build
45
+
46
+ COVERAGE=true bundle exec rspec --format progress \
47
+ --format RspecJunitFormatter \
48
+ --out /tmp/test-results/rspec.xml \
49
+ --format progress
50
+
51
+ bundle exec rubocop \
52
+ --require $(bundle show rubocop-junit-formatter)/lib/rubocop/formatter/junit_formatter.rb \
53
+ --format RuboCop::Formatter::JUnitFormatter \
54
+ --out /tmp/test-results/rubocop.xml \
55
+ --format progress \
56
+ --parallel
57
+
58
+ - run:
59
+ name: upload reports to code climate
60
+ when: "always"
61
+ command: |
62
+ ./cc-test-reporter format-coverage -t simplecov $CIRCLE_ARTIFACTS/coverage/.resultset.json
63
+ ./cc-test-reporter upload-coverage
64
+
65
+ # collect reports
66
+ - store_test_results:
67
+ path: /tmp/test-results
68
+ - store_artifacts:
69
+ path: /tmp/test-results
70
+ destination: test-results
@@ -0,0 +1,13 @@
1
+ engines:
2
+ duplication:
3
+ enabled: true
4
+ config:
5
+ languages:
6
+ - ruby:
7
+ exclude_paths:
8
+ - "spec/"
9
+ fixme:
10
+ enabled: true
11
+ rubocop:
12
+ enabled: true
13
+ channel: rubocop-0-48
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ /spec/reports/
4
+ /spec/examples.txt
5
+
6
+ ## Documentation cache and generated files:
7
+ /.yardoc/
8
+ /_yardoc/
9
+ /doc/
10
+ /rdoc/
11
+ /coverage/
12
+
13
+ # for a library or gem, you might want to ignore these files since the code is
14
+ # intended to run in multiple environments; otherwise, check them in:
15
+ Gemfile.lock
16
+ .ruby-version
17
+ .ruby-gemset
18
+
@@ -0,0 +1,21 @@
1
+ require: rubocop-rspec
2
+
3
+ AllCops:
4
+ Include:
5
+ - '**/Gemfile'
6
+ - '**/Rakefile'
7
+ Exclude:
8
+ - 'spec/demo/**/*'
9
+ - 'vendor/**/*'
10
+ TargetRubyVersion: 2.4
11
+
12
+ Metrics/BlockLength:
13
+ Exclude:
14
+ - 'spec/**/*_spec.rb'
15
+ - 'spec/support/matchers/**/*'
16
+
17
+ Style/FrozenStringLiteralComment:
18
+ Enabled: false
19
+
20
+ Style/StringLiterals:
21
+ Enabled: false
@@ -0,0 +1,4 @@
1
+ --markup=markdown
2
+ --no-private
3
+ -
4
+ LICENSE
@@ -0,0 +1,14 @@
1
+ # Changelog
2
+
3
+ ## [Unreleased]
4
+
5
+ ## 0.0.1 - 2017-08-21
6
+
7
+ ### Added
8
+
9
+ - Defining menu's and submenus
10
+ - Rendering a simple menu
11
+ - Highlighting current menu item
12
+ - Runtime parameters
13
+
14
+ [Unreleased]: https://github.com/aramvisser/navtastic/compare/v0.0.1...HEAD
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 Aram Visser
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,143 @@
1
+ # Navtastic
2
+
3
+ [![Build Status](https://img.shields.io/circleci/project/github/aramvisser/navtastic.svg)](https://circleci.com/gh/aramvisser/navtastic)
4
+ [![Code Coverage](https://img.shields.io/codeclimate/coverage/github/aramvisser/navtastic.svg)](https://codeclimate.com/github/aramvisser/navtastic)
5
+ [![Inline docs](https://inch-ci.org/github/aramvisser/navtastic.svg?branch=master)](https://inch-ci.org/github/aramvisser/navtastic)
6
+ [![MIT License](https://img.shields.io/github/license/aramvisser/navtastic.svg)](https://github.com/aramvisser/navtastic/blob/master/LICENSE)
7
+
8
+ Navtastic is way to create and render complex navigation menus. It allows for runtime configurations
9
+ of menus.
10
+
11
+ - Keep menu content and rendering logic separate
12
+ - Automatically highlight the current page
13
+
14
+ ## Table of Contents
15
+
16
+ - [Installation](#installation)
17
+ - [Example](#example)
18
+ - [Documentation](#documentation)
19
+ - [Submenus](#submenus)
20
+ - [Current item](#current-item)
21
+ - [Runtime parameters](#runtime-parameters)
22
+
23
+ ## Installation
24
+
25
+ Add it to your Gemfile:
26
+
27
+ ```ruby
28
+ gem 'navtastic'
29
+ ```
30
+
31
+ Run the following command to install it:
32
+
33
+ ```console
34
+ bundle install
35
+ ```
36
+
37
+ ## Example
38
+
39
+ Define a menu somwhere:
40
+
41
+ ```ruby
42
+ Navtastic.define :main_menu do |menu|
43
+ menu.item "Home", '/'
44
+ menu.item "Posts", '/posts'
45
+ menu.item "About", '/about'
46
+ end
47
+ ```
48
+
49
+ Render it in your partials:
50
+
51
+ ```erb
52
+ <%= Navtastic.render :main_menu, current_url %>
53
+ ```
54
+
55
+ Using the default renderer, assuming that the current url starts with `/posts`, will result in:
56
+
57
+ ```html
58
+ <ul>
59
+ <li>
60
+ <a href="/">Home</a>
61
+ </li>
62
+ <li class="current">
63
+ <a href="/posts">Posts</a>
64
+ </li>
65
+ <li>
66
+ <a href="/about">About</a>
67
+ </li>
68
+ </ul>
69
+ ```
70
+
71
+ ## Documentation
72
+
73
+ ## Submenus
74
+
75
+ Every item can have a submenu. They can be nested as deeply as you want (or at least until Ruby starts complaining).
76
+
77
+ ```ruby
78
+ Navtastic.define :main_menu do |menu|
79
+ menu.item "Home", '/' do |submenu|
80
+ submenu.item "Posts", '/posts'
81
+ submenu.item "About", '/about'
82
+ end
83
+
84
+ menu.item "Settings" do |submenu|
85
+ submenu.item "General", '/settings'
86
+ submenu.item "Profile", '/settings/profile'
87
+ end
88
+ end
89
+ ```
90
+
91
+ By default, submenus will be rendered inside the `<li>` tag of the parent item.
92
+
93
+ ```html
94
+ <ul>
95
+ <li>
96
+ <a href="/">Parent</a>
97
+ <ul>
98
+ <li>
99
+ <a href="/child">Child</a>
100
+ </li>
101
+ </ul>
102
+ </li>
103
+ </ul>
104
+ ```
105
+
106
+ ### Current item
107
+
108
+ The current active item is decided by the `current_url` parameter when rendering a menu. It is the
109
+ item with the longest url that starts with the current_url.
110
+
111
+ For example, if there is a menu containing these urls:
112
+
113
+ - `/`
114
+ - `/posts`
115
+ - `/posts/featured`
116
+
117
+ If the current_url is `/posts/featured/2017`, the `/posts/featured` item will be highlighted. If the
118
+ current_url is `/posts/123`, then `/posts` is highlighted.
119
+
120
+ The root url `/` will always match, if no other items match the current _url. If there is no item
121
+ with `/` as url in the menu and no other urls match, nothing will be highlighted.
122
+
123
+ ### Runtime parameters
124
+
125
+ You can pass runtime parameters when defining a menu. For example, passing the current user and
126
+ change the menu accordingly.
127
+
128
+ ```ruby
129
+ # Define the menu
130
+ Navtastic.define :main_menu do |menu, params|
131
+ menu.item "Home", "/"
132
+
133
+ if params[:current_user]
134
+ menu.item "Profile", "/users/#{params[:current_user].id}"
135
+ menu.item "Logout", "/logout"
136
+ else
137
+ menu.item "Login", "/login"
138
+ end
139
+ end
140
+
141
+ # Render it with the current user as a parameter
142
+ Navtastic.render :main_menu, current_url, current_user: User.current
143
+ ```
@@ -0,0 +1,19 @@
1
+ require 'rspec/core/rake_task'
2
+ require 'rubocop/rake_task'
3
+ require 'yard'
4
+ require './spec/demo/server'
5
+
6
+ RSpec::Core::RakeTask.new(:spec) do |t|
7
+ t.rspec_opts = "--order rand"
8
+ end
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ YARD::Rake::YardocTask.new
13
+
14
+ desc "Run the demo server"
15
+ task :demo do
16
+ DemoServer.new(9090).start
17
+ end
18
+
19
+ task default: %i[spec rubocop]
@@ -0,0 +1,61 @@
1
+ require 'navtastic/item'
2
+ require 'navtastic/menu'
3
+ require 'navtastic/renderer'
4
+ require 'navtastic/version'
5
+
6
+ # Main module containing some convenience methods
7
+ module Navtastic
8
+ # @private
9
+ #
10
+ # @return [Hash<Object,Block>] all stored menus
11
+ @menu_store = {}
12
+
13
+ # Define a new menu to be rendered later
14
+ #
15
+ # @example Define a new menu
16
+ # Navtastic.define :main do |menu, params|
17
+ # menu.item "Home", "/"
18
+ # end
19
+ #
20
+ # @param name the name of the menu
21
+ #
22
+ # @yield [menu, params] block to generate a new menu
23
+ # @yieldparam menu [Menu] the menu to be initialized
24
+ # @yieldparam params [Hash] runtime parameters
25
+ #
26
+ # @raise [ArgumentError] if no block was given
27
+ def self.define(name, &block)
28
+ raise ArgumentError, "no block given" unless block_given?
29
+
30
+ name = name.to_sym if name.is_a? String
31
+ @menu_store[name] = block
32
+ end
33
+
34
+ # Render a stored menu
35
+ #
36
+ # @param name the name of the defined menu
37
+ # @param current_url [String] the url of the current page
38
+ # @param params [Hash] runtime parameters
39
+ #
40
+ # @raise [KeyError] if the menu was not defined
41
+ #
42
+ # @return [Renderer] the renderer for the menu
43
+ def self.render(name, current_url, params = {})
44
+ name = name.to_sym if name.is_a? String
45
+ block = @menu_store[name]
46
+
47
+ raise KeyError, "menu not defined: #{name.inspect}" if block.nil?
48
+
49
+ menu = Menu.new
50
+ block.call(menu, params)
51
+ menu.current_url = current_url
52
+ Renderer.render(menu)
53
+ end
54
+
55
+ # A list of all defined menus
56
+ #
57
+ # @return [Array]
58
+ def self.all_menus
59
+ @menu_store.keys
60
+ end
61
+ end
@@ -0,0 +1,49 @@
1
+ module Navtastic
2
+ # A single menu item
3
+ class Item
4
+ # @return [String] the name to be displayed in the menu
5
+ attr_reader :name
6
+
7
+ # @return [String,nil] the url to link to if item is a link, nil otherwise
8
+ attr_reader :url
9
+
10
+ # @return [Menu,nil] the submenu of this item, if defined
11
+ attr_accessor :submenu
12
+
13
+ # Create a new item
14
+ #
15
+ # This should not be used directly. Use the {Menu#item} method instead.
16
+ #
17
+ # @private
18
+ #
19
+ # @param menu [Menu] the menu this items belongs to
20
+ # @param name [String] the name to display when rendering
21
+ # @param url [String] the url to link to, if the item is a link
22
+ def initialize(menu, name, url = nil)
23
+ @menu = menu
24
+ @name = name
25
+ @url = url
26
+
27
+ @submenu = nil
28
+ end
29
+
30
+ # Check if this item is the current item in the menu
31
+ #
32
+ # @see file:README.md#Current_item documentation on how the current item is
33
+ # selected
34
+ #
35
+ # @return [Bool] if the item is the current item
36
+ def current?
37
+ @menu.current_item == self
38
+ end
39
+
40
+ # @return [Bool] true if the item has a submenu, false other
41
+ def submenu?
42
+ !@submenu.nil?
43
+ end
44
+
45
+ def inspect
46
+ "#<Item \"#{name}\" [#{url}] current?:#{current?}>"
47
+ end
48
+ end
49
+ end