fuji 0.1.5 → 0.2.0
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.
- data/Gemfile.lock +7 -1
- data/README.md +53 -15
- data/fuji.gemspec +3 -2
- data/lib/fuji.rb +20 -110
- data/lib/fuji/custom_header.rb +19 -0
- data/lib/fuji/header.rb +61 -0
- data/lib/fuji/helper.rb +9 -0
- data/lib/fuji/link.rb +41 -0
- data/lib/fuji/railtie.rb +11 -0
- data/lib/fuji/renderer.rb +29 -0
- data/lib/fuji/style.rb +7 -0
- data/lib/fuji/version.rb +2 -2
- data/spec/fuji_custom_header_spec.rb +25 -0
- data/spec/fuji_header_spec.rb +52 -0
- data/spec/fuji_helper_spec.rb +12 -0
- data/spec/fuji_link_spec.rb +113 -0
- data/spec/fuji_renderer_spec.rb +39 -0
- data/spec/fuji_style_spec.rb +9 -0
- data/spec/spec_helper.rb +4 -2
- data/stylesheets/_fuji.sass +1 -1
- metadata +44 -7
- data/spec/fuji_spec.rb +0 -90
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
fuji (0.
|
4
|
+
fuji (0.2.0)
|
5
5
|
compass
|
6
6
|
sass
|
7
7
|
|
@@ -15,6 +15,7 @@ GEM
|
|
15
15
|
sass (~> 3.1)
|
16
16
|
diff-lcs (1.1.3)
|
17
17
|
fssm (0.2.10)
|
18
|
+
multi_json (1.7.2)
|
18
19
|
rake (10.0.2)
|
19
20
|
rspec (2.11.0)
|
20
21
|
rspec-core (~> 2.11.0)
|
@@ -25,6 +26,10 @@ GEM
|
|
25
26
|
diff-lcs (~> 1.1.3)
|
26
27
|
rspec-mocks (2.11.2)
|
27
28
|
sass (3.2.7)
|
29
|
+
simplecov (0.7.1)
|
30
|
+
multi_json (~> 1.0)
|
31
|
+
simplecov-html (~> 0.7.1)
|
32
|
+
simplecov-html (0.7.1)
|
28
33
|
|
29
34
|
PLATFORMS
|
30
35
|
ruby
|
@@ -33,3 +38,4 @@ DEPENDENCIES
|
|
33
38
|
fuji!
|
34
39
|
rake
|
35
40
|
rspec
|
41
|
+
simplecov
|
data/README.md
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
Fuji
|
2
2
|
====
|
3
3
|
|
4
|
+
[](https://travis-ci.org/heroku/fuji)
|
5
|
+
[](https://codeclimate.com/github/heroku/fuji)
|
6
|
+
|
4
7
|
Fuji is a ruby gem for rendering and styling Heroku's global header and nav.
|
5
8
|
|
6
9
|
Its only dependencies are Sass and Compass, so you can use it with Rails or Sinatra.
|
@@ -14,45 +17,80 @@ Add fuji to your application's Gemfile:
|
|
14
17
|
gem 'fuji'
|
15
18
|
```
|
16
19
|
|
20
|
+
And render a section by calling `render` and passing it the `Rack::Request` object, and any required options.
|
21
|
+
|
22
|
+
### Heroku Header
|
23
|
+
|
24
|
+

|
25
|
+
|
26
|
+
The Heroku header renders the default Heroku navgation, including checking whether a user is logged in or logged out.
|
27
|
+
|
17
28
|
```erb
|
18
|
-
<%= Fuji::Header.render %>
|
29
|
+
<%= Fuji::Header.render request %>
|
19
30
|
```
|
20
31
|
|
21
|
-
|
32
|
+
### Custom Header
|
33
|
+
|
34
|
+

|
35
|
+
|
36
|
+
The custom header allows you to specify a set of links to render instead of the default Heroku navigation. This header will make use of any information about the user's state.
|
37
|
+
|
38
|
+
```erb
|
39
|
+
<%= Fuji::CustomHeader.render request, [Fuji::Link.new("My Link", "http://example.com")] %>
|
40
|
+
```
|
41
|
+
|
42
|
+
Config
|
43
|
+
------
|
44
|
+
|
45
|
+
You can set global Fuji config options that affect all rendered sections.
|
46
|
+
|
47
|
+
### Rails
|
48
|
+
|
49
|
+
When using Rails, you can specify Fuji's config in your application's environment configuration:
|
22
50
|
|
23
51
|
```ruby
|
24
|
-
{
|
25
|
-
user: nil, # if present, show gravatar
|
26
|
-
logo_text: "heroku",
|
27
|
-
logo_subtext: nil, # e.g 'dashboard' or 'add-ons'
|
28
|
-
logo_url: "https://www.heroku.com",
|
29
|
-
gravatar_fallback_url: "http://assets.heroku.com.s3.amazonaws.com/addons.heroku.com/gravatar_default.png"
|
30
|
-
}
|
52
|
+
config.fuji_options = {logo_text: "heroku", logo_subtext: "dashboard"}
|
31
53
|
```
|
32
54
|
|
55
|
+
### Ruby
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
Fuji.options = {logo_text: "heroku", logo_subtext: "dashboard"}
|
59
|
+
```
|
60
|
+
|
61
|
+
### Default Options
|
62
|
+
|
63
|
+
* `logo_text`: The text output first in the logo (default: "heroku")
|
64
|
+
* `logo_subtext`: Text output second in the logo e.g. 'dashboard' or 'add-ons' (default: "")
|
65
|
+
* `logo_url`: URL linked to from the logo (default: "https://www.heroku.com")
|
66
|
+
* `map`: Optional hash containing keys `:from` and `:to` which substitutes URLs in navigation with the specified `:to` string. For example:
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
# development.rb
|
70
|
+
config.fuji_options = {map: {from: "https://www.heroku.com", to: "http://localhost:5000"}}
|
71
|
+
```
|
72
|
+
|
73
|
+
Will modify all links to www.heroku.com to point to localhost:5000, including correctly tracking active page state on an app running locally.
|
74
|
+
|
75
|
+
## Styles
|
76
|
+
|
33
77
|
Style it up by importing the fuji partial into your Sass/SCSS stylesheet:
|
34
78
|
|
35
79
|
```sass
|
36
80
|
// Override the defaults as desired:
|
37
81
|
$fuji-foreground-color: #8B8BB2
|
38
82
|
$fuji-background-color: transparent
|
39
|
-
|
40
83
|
$fuji-max-width: 1032px
|
41
84
|
$fuji-horizontal-padding: 12px
|
42
85
|
$fuji-vertical-padding: 2em
|
43
|
-
|
44
86
|
$fuji-logo-text-color: $fuji-foreground-color
|
45
87
|
$fuji-logo-subtext-color: rgba($fuji-foreground-color, 0.6)
|
46
|
-
|
47
88
|
$fuji-link-color-inactive: #7C76B8
|
48
89
|
$fuji-link-color-active: #1B1B24
|
49
|
-
|
50
90
|
$fuji-link-background-color-inactive: transparent
|
51
91
|
$fuji-link-background-color-active: $fuji-link-color-inactive
|
52
|
-
|
53
92
|
$fuji-base-font-size: inherit
|
54
93
|
$fuji-logo-font-size: 1.71em
|
55
|
-
|
56
94
|
$fuji-border-radius: 3px
|
57
95
|
|
58
96
|
@import "fuji"
|
data/fuji.gemspec
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
require File.expand_path('../lib/fuji/version', __FILE__)
|
3
3
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
|
-
gem.authors = ["Zeke Sikelianos, Max
|
6
|
-
gem.email = ["zeke@
|
5
|
+
gem.authors = ["Zeke Sikelianos", "Max Shoening", "Dominic Dagradi"]
|
6
|
+
gem.email = ["zeke@heroku.com", "max@heroku.com", "dominic@heroku.com"]
|
7
7
|
gem.description = %q{Heroku's site header}
|
8
8
|
gem.summary = %q{Heroku's site header}
|
9
9
|
gem.homepage = "https://github.com/heroku/fuji"
|
@@ -17,6 +17,7 @@ Gem::Specification.new do |gem|
|
|
17
17
|
|
18
18
|
gem.add_development_dependency 'rspec'
|
19
19
|
gem.add_development_dependency 'rake'
|
20
|
+
gem.add_development_dependency 'simplecov'
|
20
21
|
|
21
22
|
gem.add_dependency "compass"
|
22
23
|
gem.add_dependency "sass"
|
data/lib/fuji.rb
CHANGED
@@ -1,120 +1,30 @@
|
|
1
|
-
require 'fuji/version'
|
2
1
|
require 'digest/md5'
|
3
2
|
require 'uri'
|
4
3
|
require 'compass'
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
base_directory = File.join(File.dirname(__FILE__), '..')
|
16
|
-
Compass::Frameworks.register('fuji', :path => base_directory)
|
17
|
-
|
18
|
-
end
|
19
|
-
|
20
|
-
class Header
|
21
|
-
|
22
|
-
def self.render(options={})
|
23
|
-
|
24
|
-
# Options
|
25
|
-
options[:gravatar_fallback_url] ||= "https://s3.amazonaws.com/assets.heroku.com/addons.heroku.com/gravatar_default.png"
|
26
|
-
options[:logo_text] ||= "heroku"
|
27
|
-
options[:logo_subtext] ||= nil
|
28
|
-
options[:logo_url] ||= "https://www.heroku.com"
|
29
|
-
options[:user] ||= nil
|
30
|
-
options[:links] ||= nil
|
31
|
-
|
32
|
-
# Allow links to be overridden entirely
|
33
|
-
links = options[:links]
|
34
|
-
|
35
|
-
if links.nil?
|
36
|
-
links = [
|
37
|
-
{id: :apps, name: 'Apps', url: 'https://dashboard.heroku.com'},
|
38
|
-
{id: :addons, name: 'Add-ons', url: 'https://addons.heroku.com'},
|
39
|
-
{id: :documentation, name: 'Documentation', url: 'https://devcenter.heroku.com'},
|
40
|
-
{id: :support, name: 'Support', url: 'https://help.heroku.com'},
|
41
|
-
{id: :blog, name: 'Blog', url: 'https://blog.heroku.com'},
|
42
|
-
{id: :account, name: 'Account', url: "https://dashboard.heroku.com/account"}
|
43
|
-
]
|
44
|
-
|
45
|
-
# Gravatar
|
46
|
-
if options[:user] && options[:user].email
|
47
|
-
gravatar_url = [
|
48
|
-
"https://secure.gravatar.com/avatar/",
|
49
|
-
Digest::MD5.hexdigest(options[:user].email),
|
50
|
-
"?default=",
|
51
|
-
URI.escape(options[:gravatar_fallback_url])
|
52
|
-
].join("")
|
53
|
-
links << {
|
54
|
-
id: :gravatar,
|
55
|
-
name: Fuji::Helper.image_tag(gravatar_url),
|
56
|
-
url: 'https://dashboard.heroku.com/account'
|
57
|
-
}
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
# Join links together
|
62
|
-
links = links.map do |link|
|
63
|
-
Fuji::Helper.link_to(link[:name], link[:url], link[:id])
|
64
|
-
end.join("\n")
|
65
|
-
|
66
|
-
# Prepare the HTML output
|
67
|
-
out = "
|
68
|
-
<div id='fuji' class='fuji'>
|
69
|
-
<div class='fuji-container'>
|
70
|
-
<h1 class='fuji-brand'>
|
71
|
-
<a class='fuji-logo' href='#{options[:logo_url]}'>
|
72
|
-
#{options[:logo_text]} <span class='fuji-logo-subtext'>#{options[:logo_subtext]}</span>
|
73
|
-
</a>
|
74
|
-
</h1>
|
75
|
-
|
76
|
-
<ul class='fuji-links'>#{links}</ul>
|
77
|
-
</div>
|
78
|
-
</div>
|
79
|
-
"
|
80
|
-
|
81
|
-
# If we're in Rails, make it HTML safe
|
82
|
-
out.respond_to?(:html_safe) ? out.html_safe : out
|
83
|
-
end
|
84
|
-
|
85
|
-
# def self.default_links(options={})
|
86
|
-
# end
|
87
|
-
|
88
|
-
end
|
89
|
-
|
90
|
-
class Helper
|
91
|
-
|
92
|
-
def self.current_site_matches?(search_string_or_url, request_object=nil)
|
93
|
-
# Allow request object to be mocked, for testing purposes
|
94
|
-
request ||= request_object
|
95
|
-
return false unless request
|
96
|
-
|
97
|
-
# Clean the string up
|
98
|
-
q = extract_domain(search_string_or_url).to_s
|
99
|
-
|
100
|
-
return true if request.url && request.url.include?(q)
|
101
|
-
return true if request.host_with_port && request.host_with_port.include?(q)
|
102
|
-
false
|
103
|
-
end
|
104
|
-
|
105
|
-
def self.extract_domain(string)
|
106
|
-
string =~ (/^(?:\w+:\/\/)?([^\/?]+)(?:\/|\?|$)/) ? $1 : string
|
107
|
-
end
|
5
|
+
require 'fuji/link'
|
6
|
+
require 'fuji/helper'
|
7
|
+
require 'fuji/renderer'
|
8
|
+
require 'fuji/header'
|
9
|
+
require 'fuji/custom_header'
|
10
|
+
require 'fuji/style'
|
11
|
+
require 'fuji/railtie' if defined?(Rails)
|
12
|
+
require 'fuji/version'
|
108
13
|
|
109
|
-
|
110
|
-
|
111
|
-
|
14
|
+
class Fuji
|
15
|
+
DEFAULTS = {
|
16
|
+
logo_text: "heroku",
|
17
|
+
logo_subtext: "",
|
18
|
+
logo_url: "https://www.heroku.com",
|
19
|
+
}
|
20
|
+
|
21
|
+
class << self
|
22
|
+
|
23
|
+
def options= options
|
24
|
+
@options = DEFAULTS.merge(options)
|
112
25
|
end
|
113
26
|
|
114
|
-
def
|
115
|
-
"<img src='#{url}'>"
|
116
|
-
end
|
27
|
+
def options; @options || DEFAULTS; end
|
117
28
|
|
118
29
|
end
|
119
|
-
|
120
30
|
end
|
data/lib/fuji/header.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
class Fuji
|
2
|
+
class Header < Renderer
|
3
|
+
|
4
|
+
ADDONS = Link.new("Add-ons", "https://addons.heroku.com")
|
5
|
+
DOCUMENTATION = Link.new("Documentation", "https://devcenter.heroku.com")
|
6
|
+
HELP = Link.new("Help & Support", "https://help.heroku.com", {css: "help"})
|
7
|
+
|
8
|
+
LOGGED_IN = [
|
9
|
+
Link.new("Apps", "https://dashboard.heroku.com"),
|
10
|
+
ADDONS,
|
11
|
+
DOCUMENTATION,
|
12
|
+
HELP,
|
13
|
+
Link.new("Account", "https://dashboard.heroku.com/account"),
|
14
|
+
Link.new("Log Out", "https://id.heroku.com/logout")
|
15
|
+
]
|
16
|
+
|
17
|
+
LOGGED_OUT = [
|
18
|
+
Link.new("Sign Up", "https://www.heroku.com/signup"),
|
19
|
+
Link.new("Pricing", "https://www.heroku.com/pricing"),
|
20
|
+
Link.new("How it Works", "https://www.heroku.com/how"),
|
21
|
+
ADDONS,
|
22
|
+
DOCUMENTATION,
|
23
|
+
HELP,
|
24
|
+
Link.new("Login", "https://id.heroku.com/login")
|
25
|
+
]
|
26
|
+
|
27
|
+
def render
|
28
|
+
# Build HTML from link objects
|
29
|
+
link_html = links.map{|l| l.html(current_page) }.join("\n")
|
30
|
+
|
31
|
+
# Build HTML wrapper
|
32
|
+
out = "
|
33
|
+
<div class='fuji #{css_class}'>
|
34
|
+
<div class='fuji-container'>
|
35
|
+
<h1 class='fuji-brand'>
|
36
|
+
<a class='fuji-logo' href='#{Fuji.options[:logo_url]}'>
|
37
|
+
#{Fuji.options[:logo_text]} <span class='fuji-logo-subtext'>#{Fuji.options[:logo_subtext]}</span>
|
38
|
+
</a>
|
39
|
+
</h1>
|
40
|
+
|
41
|
+
<ul class='fuji-links'>#{link_html}</ul>
|
42
|
+
</div>
|
43
|
+
</div>
|
44
|
+
"
|
45
|
+
|
46
|
+
# If we're in Rails, make it HTML safe
|
47
|
+
out.respond_to?(:html_safe) ? out.html_safe : out
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def css_class
|
53
|
+
"fuji-header"
|
54
|
+
end
|
55
|
+
|
56
|
+
def links
|
57
|
+
logged_in? ? LOGGED_IN : LOGGED_OUT
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
data/lib/fuji/helper.rb
ADDED
data/lib/fuji/link.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
class Fuji
|
2
|
+
class Link
|
3
|
+
|
4
|
+
def initialize label, url, options = {}
|
5
|
+
@label = label
|
6
|
+
@url = url
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
def html current_page = nil
|
11
|
+
local = nil
|
12
|
+
url = mapping @url
|
13
|
+
|
14
|
+
@options[:css] ||= Fuji::Helper.dehumanize(@label)
|
15
|
+
css_class = [@options[:css]]
|
16
|
+
css_class << "active" if current_page && current_page?(url, current_page)
|
17
|
+
"<li><a href='#{url}' class='#{css_class.join(" ")}'>#{@label}</a></li>"
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def mapping url
|
23
|
+
if mapping = Fuji.options[:map]
|
24
|
+
url.sub(mapping[:from], mapping[:to])
|
25
|
+
else
|
26
|
+
url
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def current_page?(url, current)
|
31
|
+
link = URI.parse(url.to_s)
|
32
|
+
request = URI.parse(current)
|
33
|
+
|
34
|
+
request.query = nil unless link.query
|
35
|
+
request.path = link.path if ["", "/"].include? link.path
|
36
|
+
|
37
|
+
link == request
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
data/lib/fuji/railtie.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
class Fuji
|
2
|
+
class Renderer
|
3
|
+
|
4
|
+
def self.render request, options = {}
|
5
|
+
self.new(request, options).render
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize request, options = {}
|
9
|
+
@request = request
|
10
|
+
@options = options
|
11
|
+
end
|
12
|
+
|
13
|
+
def render
|
14
|
+
raise Exception.new("Unimplemented")
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def logged_in?
|
20
|
+
cookies = @request.cookies
|
21
|
+
cookies ? cookies.fetch("heroku_session", false) : false
|
22
|
+
end
|
23
|
+
|
24
|
+
def current_page
|
25
|
+
@request.url
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
data/lib/fuji/style.rb
ADDED
data/lib/fuji/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
VERSION = "0.
|
1
|
+
class Fuji
|
2
|
+
VERSION = "0.2.0"
|
3
3
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Fuji::CustomHeader do
|
4
|
+
before do
|
5
|
+
@request = OpenStruct.new()
|
6
|
+
@links = [Fuji::Link.new("My Custom Link", "http://example.com")]
|
7
|
+
end
|
8
|
+
|
9
|
+
it "renders a custom set of links from an options hash" do
|
10
|
+
html = Fuji::CustomHeader.render @request, {links: @links}
|
11
|
+
|
12
|
+
html.should match "fuji-custom-header"
|
13
|
+
html.should match "My Custom Link"
|
14
|
+
html.should_not match "Sign Up"
|
15
|
+
end
|
16
|
+
|
17
|
+
it "renders a custom set of links from an array" do
|
18
|
+
html = Fuji::CustomHeader.render @request, @links
|
19
|
+
|
20
|
+
html.should match "fuji-custom-header"
|
21
|
+
html.should match "My Custom Link"
|
22
|
+
html.should_not match "Sign Up"
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Fuji::Header do
|
4
|
+
describe "chooses the correct link set when" do
|
5
|
+
it "is logged out" do
|
6
|
+
request = OpenStruct.new(cookies: {})
|
7
|
+
html = Fuji::Header.render request
|
8
|
+
|
9
|
+
html.should match "Sign Up"
|
10
|
+
html.should_not match "Apps"
|
11
|
+
end
|
12
|
+
|
13
|
+
it "is logged in" do
|
14
|
+
request = OpenStruct.new(cookies: {"heroku_session" => 1})
|
15
|
+
html = Fuji::Header.render request
|
16
|
+
|
17
|
+
html.should_not match "Sign Up"
|
18
|
+
html.should match "Apps"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "passes the current page to the links" do
|
23
|
+
request = OpenStruct.new(url: "https://www.heroku.com/pricing")
|
24
|
+
html = Fuji::Header.render request
|
25
|
+
|
26
|
+
html.should match "a href='https://www.heroku.com/pricing' class='pricing active'"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "renders the logo url from options" do
|
30
|
+
link = "http://fujiheader.com"
|
31
|
+
Fuji.options = {logo_url: link}
|
32
|
+
|
33
|
+
html = Fuji::Header.render OpenStruct.new
|
34
|
+
html.should match "a class='fuji-logo' href='#{link}'"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "renders the logo text from options" do
|
38
|
+
text = "My Title"
|
39
|
+
Fuji.options = {logo_text: text}
|
40
|
+
|
41
|
+
html = Fuji::Header.render OpenStruct.new
|
42
|
+
html.should match text
|
43
|
+
end
|
44
|
+
|
45
|
+
it "renders the logo subtext from options" do
|
46
|
+
text = "My Subtitle"
|
47
|
+
Fuji.options = {logo_subtext: text}
|
48
|
+
|
49
|
+
html = Fuji::Header.render OpenStruct.new
|
50
|
+
html.should match "heroku <span class='fuji-logo-subtext'>#{text}"
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Fuji::Helper do
|
4
|
+
it "converts strings to CSS classes" do
|
5
|
+
Fuji::Helper.dehumanize("My Class").should == "my-class"
|
6
|
+
end
|
7
|
+
|
8
|
+
it "reduces all non-word characters to a single dash" do
|
9
|
+
Fuji::Helper.dehumanize("Help & Support").should == "help-support"
|
10
|
+
Fuji::Helper.dehumanize("Help Support").should == "help-support"
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Fuji::Link do
|
4
|
+
|
5
|
+
describe "#html" do
|
6
|
+
it "builds a link tag with default options" do
|
7
|
+
link = Fuji::Link.new("My Link", "http://example.com")
|
8
|
+
link.html.should match "a href='http://example.com'"
|
9
|
+
end
|
10
|
+
|
11
|
+
it "defaults to a dasherized css class based on the link title" do
|
12
|
+
link = Fuji::Link.new("My Link", "http://example.com")
|
13
|
+
link.html.should match "a href='http://example.com' class='my-link'"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "accepts a custom css class string" do
|
17
|
+
link = Fuji::Link.new("My Link", "http://example.com", css: "custom")
|
18
|
+
link.html.should match "a href='http://example.com' class='custom'"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#current_page" do
|
23
|
+
it "sets no class when the link doesn't match the current URL" do
|
24
|
+
link = Fuji::Link.new("My Link", "http://example.com")
|
25
|
+
html = link.html("http://notamatch.com")
|
26
|
+
|
27
|
+
html.should_not match /active/
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "url is domain only" do
|
31
|
+
before do
|
32
|
+
@link = Fuji::Link.new("My Link", "http://example.com")
|
33
|
+
end
|
34
|
+
|
35
|
+
it "matches the current url when it is domain only" do
|
36
|
+
html = @link.html("http://example.com")
|
37
|
+
html.should match /active/
|
38
|
+
end
|
39
|
+
|
40
|
+
it "matches the current url when it includes a path" do
|
41
|
+
html = @link.html("http://example.com/path")
|
42
|
+
html.should match /active/
|
43
|
+
end
|
44
|
+
|
45
|
+
it "matches the current url when it includes a query" do
|
46
|
+
html = @link.html("http://example.com/path?query")
|
47
|
+
html.should match /active/
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "url includes a path" do
|
52
|
+
before do
|
53
|
+
@link = Fuji::Link.new("My Link", "http://example.com/path")
|
54
|
+
end
|
55
|
+
|
56
|
+
it "does not match the current url when it is domain only" do
|
57
|
+
html = @link.html("http://example.com")
|
58
|
+
html.should_not match /active/
|
59
|
+
end
|
60
|
+
|
61
|
+
it "matches the current url when it includes a path" do
|
62
|
+
html = @link.html("http://example.com/path")
|
63
|
+
html.should match /active/
|
64
|
+
end
|
65
|
+
|
66
|
+
it "matches the current url when it includes a query" do
|
67
|
+
html = @link.html("http://example.com/path?query")
|
68
|
+
html.should match /active/
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "url includes a query" do
|
73
|
+
before do
|
74
|
+
@link = Fuji::Link.new("My Link", "http://example.com/path?query")
|
75
|
+
end
|
76
|
+
|
77
|
+
it "does not match the current url when it is domain only" do
|
78
|
+
html = @link.html("http://example.com")
|
79
|
+
html.should_not match /active/
|
80
|
+
end
|
81
|
+
|
82
|
+
it "does not match the current url when it includes a path" do
|
83
|
+
html = @link.html("http://example.com/path")
|
84
|
+
html.should_not match /active/
|
85
|
+
end
|
86
|
+
|
87
|
+
it "matches the current url when it includes a query" do
|
88
|
+
html = @link.html("http://example.com/path?query")
|
89
|
+
html.should match /active/
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "#mapping" do
|
95
|
+
it "does nothing :map option is not set" do
|
96
|
+
link = Fuji::Link.new("My Link", "http://example.com")
|
97
|
+
html = link.html
|
98
|
+
|
99
|
+
html.should match "http://example.com"
|
100
|
+
html.should_not match "http://mapexample.com"
|
101
|
+
end
|
102
|
+
|
103
|
+
it "substitutes the requested URL when :map option set" do
|
104
|
+
Fuji.options = {map: {from: "example.com", to: "mapexample.com"}}
|
105
|
+
link = Fuji::Link.new("My Link", "http://example.com")
|
106
|
+
html = link.html
|
107
|
+
|
108
|
+
html.should_not match "http://example.com"
|
109
|
+
html.should match "http://mapexample.com"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Fuji::Renderer do
|
4
|
+
# Private method
|
5
|
+
describe "#render" do
|
6
|
+
it "should raise an exception" do
|
7
|
+
expect { Fuji::Renderer.render(OpenStruct.new) }.to raise_error("Unimplemented")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# Private method
|
12
|
+
describe "#logged_in" do
|
13
|
+
it "returns false when there is no heroku session" do
|
14
|
+
request = OpenStruct.new(cookies: {})
|
15
|
+
renderer = Fuji::Renderer.new(request)
|
16
|
+
|
17
|
+
renderer.send(:logged_in?).should == false
|
18
|
+
end
|
19
|
+
|
20
|
+
it "returns a truthy value when heroku session present" do
|
21
|
+
request = OpenStruct.new(cookies: {"heroku_session" => 1})
|
22
|
+
renderer = Fuji::Renderer.new(request)
|
23
|
+
|
24
|
+
renderer.send(:logged_in?).should_not == false
|
25
|
+
renderer.send(:logged_in?).should_not == nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Private method
|
30
|
+
describe "#current_page" do
|
31
|
+
it "returns the current url from the request object" do
|
32
|
+
url = "http://example.com"
|
33
|
+
request = OpenStruct.new(url: url)
|
34
|
+
renderer = Fuji::Renderer.new(request)
|
35
|
+
|
36
|
+
renderer.send(:current_page).should == url
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/spec/spec_helper.rb
CHANGED
data/stylesheets/_fuji.sass
CHANGED
metadata
CHANGED
@@ -1,15 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fuji
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
|
-
- Zeke Sikelianos
|
8
|
+
- Zeke Sikelianos
|
9
|
+
- Max Shoening
|
10
|
+
- Dominic Dagradi
|
9
11
|
autorequire:
|
10
12
|
bindir: bin
|
11
13
|
cert_chain: []
|
12
|
-
date: 2013-04-
|
14
|
+
date: 2013-04-22 00:00:00.000000000 Z
|
13
15
|
dependencies:
|
14
16
|
- !ruby/object:Gem::Dependency
|
15
17
|
name: rspec
|
@@ -43,6 +45,22 @@ dependencies:
|
|
43
45
|
- - ! '>='
|
44
46
|
- !ruby/object:Gem::Version
|
45
47
|
version: '0'
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: simplecov
|
50
|
+
requirement: !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
type: :development
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ! '>='
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
46
64
|
- !ruby/object:Gem::Dependency
|
47
65
|
name: compass
|
48
66
|
requirement: !ruby/object:Gem::Requirement
|
@@ -77,7 +95,9 @@ dependencies:
|
|
77
95
|
version: '0'
|
78
96
|
description: Heroku's site header
|
79
97
|
email:
|
80
|
-
- zeke@
|
98
|
+
- zeke@heroku.com
|
99
|
+
- max@heroku.com
|
100
|
+
- dominic@heroku.com
|
81
101
|
executables: []
|
82
102
|
extensions: []
|
83
103
|
extra_rdoc_files: []
|
@@ -91,8 +111,20 @@ files:
|
|
91
111
|
- Rakefile
|
92
112
|
- fuji.gemspec
|
93
113
|
- lib/fuji.rb
|
114
|
+
- lib/fuji/custom_header.rb
|
115
|
+
- lib/fuji/header.rb
|
116
|
+
- lib/fuji/helper.rb
|
117
|
+
- lib/fuji/link.rb
|
118
|
+
- lib/fuji/railtie.rb
|
119
|
+
- lib/fuji/renderer.rb
|
120
|
+
- lib/fuji/style.rb
|
94
121
|
- lib/fuji/version.rb
|
95
|
-
- spec/
|
122
|
+
- spec/fuji_custom_header_spec.rb
|
123
|
+
- spec/fuji_header_spec.rb
|
124
|
+
- spec/fuji_helper_spec.rb
|
125
|
+
- spec/fuji_link_spec.rb
|
126
|
+
- spec/fuji_renderer_spec.rb
|
127
|
+
- spec/fuji_style_spec.rb
|
96
128
|
- spec/spec.opts
|
97
129
|
- spec/spec_helper.rb
|
98
130
|
- stylesheets/_fuji.sass
|
@@ -116,11 +148,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
116
148
|
version: '0'
|
117
149
|
requirements: []
|
118
150
|
rubyforge_project:
|
119
|
-
rubygems_version: 1.8.
|
151
|
+
rubygems_version: 1.8.25
|
120
152
|
signing_key:
|
121
153
|
specification_version: 3
|
122
154
|
summary: Heroku's site header
|
123
155
|
test_files:
|
124
|
-
- spec/
|
156
|
+
- spec/fuji_custom_header_spec.rb
|
157
|
+
- spec/fuji_header_spec.rb
|
158
|
+
- spec/fuji_helper_spec.rb
|
159
|
+
- spec/fuji_link_spec.rb
|
160
|
+
- spec/fuji_renderer_spec.rb
|
161
|
+
- spec/fuji_style_spec.rb
|
125
162
|
- spec/spec.opts
|
126
163
|
- spec/spec_helper.rb
|
data/spec/fuji_spec.rb
DELETED
@@ -1,90 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'digest/md5'
|
3
|
-
|
4
|
-
describe Fuji::Header do
|
5
|
-
|
6
|
-
describe "#render" do
|
7
|
-
before do
|
8
|
-
@user = OpenStruct.new(email: "bob@heroku.com")
|
9
|
-
end
|
10
|
-
|
11
|
-
it "outputs an HTML string" do
|
12
|
-
Fuji::Header.render.should match /div id='fuji'/
|
13
|
-
end
|
14
|
-
|
15
|
-
it "renders the user's avatar" do
|
16
|
-
h = Fuji::Header.render(user: @user)
|
17
|
-
hash = Digest::MD5.hexdigest(@user.email)
|
18
|
-
h.should match /#{hash}/
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
describe "Fuji::Helper.current_site_matches?" do
|
24
|
-
|
25
|
-
describe "inside a rails app" do
|
26
|
-
before do
|
27
|
-
@request = OpenStruct.new(protocol: "https://", host_with_port: "dhh.com", fullpath: "/foo")
|
28
|
-
end
|
29
|
-
|
30
|
-
it "detects search string" do
|
31
|
-
Fuji::Helper.current_site_matches?('dhh.com/foo', @request).should == true
|
32
|
-
end
|
33
|
-
|
34
|
-
it "doesn't detect search string" do
|
35
|
-
Fuji::Helper.current_site_matches?('some other shit', @request).should == false
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
|
40
|
-
describe "inside a sinatra app" do
|
41
|
-
|
42
|
-
before do
|
43
|
-
@request = OpenStruct.new(url: "https://mizerany.com")
|
44
|
-
end
|
45
|
-
|
46
|
-
it "detects search string" do
|
47
|
-
Fuji::Helper.current_site_matches?('mizerany', @request).should == true
|
48
|
-
end
|
49
|
-
|
50
|
-
it "doesn't detect search string" do
|
51
|
-
Fuji::Helper.current_site_matches?('some other blake', @request).should == false
|
52
|
-
end
|
53
|
-
|
54
|
-
end
|
55
|
-
|
56
|
-
describe "in any kind of ruby app" do
|
57
|
-
|
58
|
-
before do
|
59
|
-
@request = OpenStruct.new(url: "https://the-rest.com")
|
60
|
-
end
|
61
|
-
|
62
|
-
it "allows a symbol as a search string" do
|
63
|
-
Fuji::Helper.current_site_matches?(:rest, @request).should == true
|
64
|
-
end
|
65
|
-
|
66
|
-
it "matches against domain name when given a full URL" do
|
67
|
-
Fuji::Helper.current_site_matches?("http://the-rest.com/extra/mojo", @request).should == true
|
68
|
-
end
|
69
|
-
|
70
|
-
it "returns false if request object is nil" do
|
71
|
-
Fuji::Helper.current_site_matches?('foo').should == false
|
72
|
-
end
|
73
|
-
|
74
|
-
end
|
75
|
-
|
76
|
-
end
|
77
|
-
|
78
|
-
describe "extract_domain" do
|
79
|
-
|
80
|
-
it "pulls the domain out of a URL string" do
|
81
|
-
Fuji::Helper.extract_domain("https://dweeb-fest.example.com/sho/biz").should == "dweeb-fest.example.com"
|
82
|
-
end
|
83
|
-
|
84
|
-
it "returns the original string if it doesn't contain a domain" do
|
85
|
-
Fuji::Helper.extract_domain("turkey jerky").should == "turkey jerky"
|
86
|
-
end
|
87
|
-
|
88
|
-
end
|
89
|
-
|
90
|
-
end
|