snipp 0.0.2 → 0.0.3
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/README.md +5 -0
- data/app/views/snipp/breadcrumb.html.erb +23 -0
- data/app/views/snipp/index.html.erb +3 -1
- data/config/locales/snipp.yml +4 -4
- data/lib/snipp/config.rb +30 -0
- data/lib/snipp/helpers/action_view_extension.rb +5 -29
- data/lib/snipp/markups/microdata.rb +38 -0
- data/lib/snipp/version.rb +1 -1
- data/lib/snipp.rb +2 -0
- data/spec/fake_rails.rb +6 -9
- data/spec/snipp/helpers/action_view_extension_spec.rb +89 -0
- data/spec/snipp_spec.rb +3 -5
- metadata +6 -1
data/README.md
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
# Snipp
|
2
|
+
[](http://badge.fury.io/rb/snipp)
|
3
|
+
[](https://coveralls.io/r/yulii/snipp)
|
4
|
+
[](https://travis-ci.org/yulii/snipp)
|
2
5
|
|
3
6
|
TODO: Write a gem description
|
4
7
|
|
@@ -38,6 +41,8 @@ en:
|
|
38
41
|
food_fruit_red_apple: "Apple"
|
39
42
|
```
|
40
43
|
|
44
|
+
more https://github.com/yulii/snipp/blob/master/app/views/snipp/index.html.erb
|
45
|
+
|
41
46
|
## Contributing
|
42
47
|
|
43
48
|
1. Fork it
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<h1>Breadcumbs - Rich Snippets Sample</h1>
|
2
|
+
<h2>Basic</h2>
|
3
|
+
<section id="case-A-1">
|
4
|
+
<h3>Simple Breadcumb</h3>
|
5
|
+
<%= breadcrumb [:root, :foods, :fruits] %>
|
6
|
+
</section>
|
7
|
+
<section id="case-A-2">
|
8
|
+
<h3>Designate separator</h3>
|
9
|
+
<%= breadcrumb [:root, :foods, :fruits], s: "/" %>
|
10
|
+
</section>
|
11
|
+
<h2>Advanced</h2>
|
12
|
+
<section id="case-B-1">
|
13
|
+
<h3>Specify Parameters for URL (path) and i18n</h3>
|
14
|
+
<%= breadcrumb [:root, :foods, :fruits, :fruits_color, :food], s: "/", params: [:color, :name] %>
|
15
|
+
</section>
|
16
|
+
<section id="case-B-2">
|
17
|
+
<h3>Customize Variables</h3>
|
18
|
+
<%= breadcrumb [:root, :foods, :fruits, { path: fruits_color_path('Red'), label: 'Red' }, { path: food_path(color: 'Red', name: 'Apple'), label: 'Apple' }], s: "/" %>
|
19
|
+
</section>
|
20
|
+
<section id="case-B-3">
|
21
|
+
<h3>Customize Variables and Specify Parameters</h3>
|
22
|
+
<%= breadcrumb [:root, :foods, :fruits, { path: fruits_color_path, label: :fruits_color }, { path: food_path, label: :food }], s: "/", params: [:color, :name] %>
|
23
|
+
</section>
|
@@ -1,3 +1,5 @@
|
|
1
1
|
<h1>Rich Snippets Sample</h1>
|
2
2
|
<h2>Breadcumb</h2>
|
3
|
-
|
3
|
+
<% = breadcrumb [:root, :foods, :fruits, :fruits_color, :food], s: "/", params: [:color, :name] %>
|
4
|
+
|
5
|
+
<% = breadcrumb [:root, :foods, :fruits, { path: fruits_color_path(:red), label: 'Red' }, { path: food_path(color: :red, name: :apple), label: 'Apple' }], s: "/" %>
|
data/config/locales/snipp.yml
CHANGED
data/lib/snipp/config.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'active_support/configurable'
|
2
|
+
|
3
|
+
module Snipp
|
4
|
+
|
5
|
+
def self.configure(&block)
|
6
|
+
yield @config ||= Snipp::Configuration.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.config
|
10
|
+
@config
|
11
|
+
end
|
12
|
+
|
13
|
+
class Configuration #:nodoc:
|
14
|
+
include ActiveSupport::Configurable
|
15
|
+
config_accessor :markup
|
16
|
+
|
17
|
+
def param_name
|
18
|
+
config.param_name.respond_to?(:call) ? config.param_name.call : config.param_name
|
19
|
+
end
|
20
|
+
|
21
|
+
# define param_name writer (copied from AS::Configurable)
|
22
|
+
writer, line = 'def param_name=(value); config.param_name = value; end', __LINE__
|
23
|
+
singleton_class.class_eval writer, __FILE__, line
|
24
|
+
class_eval writer, __FILE__, line
|
25
|
+
end
|
26
|
+
|
27
|
+
configure do |config|
|
28
|
+
config.markup = :microdata
|
29
|
+
end
|
30
|
+
end
|
@@ -1,35 +1,11 @@
|
|
1
1
|
module Snipp
|
2
2
|
module ActionViewExtension
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
sepalator << '<div itemprop="child" itemscope itemtype="http://data-vocabulary.org/Breadcrumb">'
|
10
|
-
|
11
|
-
i18n_options = options.merge({ scope: [:views, :breadcrumb] })
|
12
|
-
|
13
|
-
bc = []
|
14
|
-
paths.each do |e|
|
15
|
-
if e.is_a?(Hash)
|
16
|
-
body = content_tag :span, e[:label], itemprop: :title
|
17
|
-
bc.push link_to body, e[:path], itemprop: :url
|
18
|
-
else
|
19
|
-
body = content_tag :span, I18n.t(e, i18n_options), itemprop: :title
|
20
|
-
bc.push link_to body, send("#{e}_path", options), itemprop: :url
|
21
|
-
end
|
22
|
-
end
|
23
|
-
code = '<nav class="breadcrumb" itemscope itemtype="http://data-vocabulary.org/Breadcrumb">'
|
24
|
-
code << bc.join(sepalator)
|
25
|
-
|
26
|
-
(paths.size - 1).times do
|
27
|
-
code << '</div>'
|
28
|
-
end
|
29
|
-
code << '</nav>'
|
30
|
-
|
31
|
-
return code.html_safe
|
32
|
-
end
|
4
|
+
def self.included(base)
|
5
|
+
name = "#{Snipp.config.markup}".camelize
|
6
|
+
raise NotImplementedError, "#{name} is invalid. Specify correct Snipp.config.markup." unless Snipp::Markup.const_defined? name
|
7
|
+
base.send :include, Snipp::Markup.const_get(name)
|
8
|
+
end
|
33
9
|
|
34
10
|
end
|
35
11
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Snipp
|
2
|
+
module Markup
|
3
|
+
module Microdata
|
4
|
+
|
5
|
+
def breadcrumb paths, options = {}
|
6
|
+
sepalator = " #{options.delete(:sepalator)||options.delete(:s)||'>'} "
|
7
|
+
sepalator << '<div itemprop="child" itemscope itemtype="http://data-vocabulary.org/Breadcrumb">'
|
8
|
+
|
9
|
+
# options for i18n
|
10
|
+
i18n_options = { scope: [:views, :breadcrumb] }
|
11
|
+
(options[:params]||[]).each do |e|
|
12
|
+
i18n_options[e] = params[e]
|
13
|
+
end
|
14
|
+
|
15
|
+
bc = []
|
16
|
+
paths.each do |e|
|
17
|
+
if e.is_a?(Hash)
|
18
|
+
body = content_tag :span, I18n.t(e[:label], i18n_options.merge(default: e[:label])), itemprop: :title
|
19
|
+
bc.push link_to body, e[:path], itemprop: :url
|
20
|
+
else
|
21
|
+
body = content_tag :span, I18n.t(e, i18n_options), itemprop: :title
|
22
|
+
bc.push link_to body, send("#{e}_path"), itemprop: :url
|
23
|
+
end
|
24
|
+
end
|
25
|
+
output = '<nav class="breadcrumb" itemscope itemtype="http://data-vocabulary.org/Breadcrumb">'
|
26
|
+
output << bc.join(sepalator)
|
27
|
+
|
28
|
+
(paths.size - 1).times do
|
29
|
+
output << '</div>'
|
30
|
+
end
|
31
|
+
output << '</nav>'
|
32
|
+
|
33
|
+
return output.html_safe
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/snipp/version.rb
CHANGED
data/lib/snipp.rb
CHANGED
data/spec/fake_rails.rb
CHANGED
@@ -11,19 +11,14 @@ end
|
|
11
11
|
app.initialize!
|
12
12
|
|
13
13
|
# routing
|
14
|
-
SNIPP_TYPES = [:breadcumb]
|
15
14
|
app.routes.draw do
|
16
15
|
get "/" =>"snipp#index" ,as: :root
|
17
16
|
|
18
|
-
SNIPP_TYPES.each do |e|
|
19
|
-
get "/e" => "index##{e}" ,as: e
|
20
|
-
end
|
21
|
-
|
22
17
|
# for Breadcumb
|
23
|
-
get "/
|
24
|
-
get "/
|
25
|
-
get "/
|
26
|
-
get "/
|
18
|
+
get "/foods" => "snipp#breadcrumb", as: :foods
|
19
|
+
get "/foods/fruits" => "snipp#breadcrumb", as: :fruits
|
20
|
+
get "/foods/fruits/:color" => "snipp#breadcrumb", as: :fruits_color
|
21
|
+
get "/foods/fruits/:color/:name" => "snipp#breadcrumb", as: :food
|
27
22
|
end
|
28
23
|
|
29
24
|
# controllers
|
@@ -33,6 +28,8 @@ class SnippController < ApplicationController
|
|
33
28
|
|
34
29
|
def index ; end
|
35
30
|
|
31
|
+
def breadcrumb ; end
|
32
|
+
|
36
33
|
end
|
37
34
|
|
38
35
|
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
class Snipp::ActionViewExtension::Spec
|
5
|
+
|
6
|
+
BREADCRUMBS = [
|
7
|
+
{ id: "#case-A-1", path: [:root, :foods, :fruits], separator: '>' },
|
8
|
+
{ id: "#case-A-2", path: [:root, :foods, :fruits], separator: '/' },
|
9
|
+
{ id: "#case-B-1", path: [:root, :foods, :fruits, :fruits_color, :food], separator: '/', params: [:color, :name] },
|
10
|
+
# { id: "#case-B-2", path: [:root, :foods, :fruits, { path: app.fruits_color_path('Red'), label: 'Red' }, { path: app.food_path(color: 'Red', name: 'Apple'), label: 'Apple' }], separator: '/' },
|
11
|
+
# { id: "#case-B-3", path: [:root, :foods, :fruits, { path: app.fruits_color_path, label: :fruits_color }, { path: app.food_path, label: :food }], separator: '/', params: [:color, :name] },
|
12
|
+
]
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
describe Snipp::ActionViewExtension do
|
17
|
+
|
18
|
+
before do
|
19
|
+
Snipp::Hooks.init
|
20
|
+
visit "/foods/fruits/Red/Apple"
|
21
|
+
end
|
22
|
+
|
23
|
+
# <nav class="breadcrumb" itemscope itemtype="http://data-vocabulary.org/Breadcrumb">
|
24
|
+
# <a href="/" itemprop="url">
|
25
|
+
# <span itemprop="title">Top</span>
|
26
|
+
# </a> /
|
27
|
+
# <div itemprop="child" itemscope itemtype="http://data-vocabulary.org/Breadcrumb">
|
28
|
+
# <a href="/foods" itemprop="url">
|
29
|
+
# <span itemprop="title">Foods</span>
|
30
|
+
# </a> /
|
31
|
+
# <div itemprop="child" itemscope itemtype="http://data-vocabulary.org/Breadcrumb">
|
32
|
+
# <a href="/foods/fruits" itemprop="url">
|
33
|
+
# <span itemprop="title">Fruits</span>
|
34
|
+
# </a> /
|
35
|
+
# <div itemprop="child" itemscope itemtype="http://data-vocabulary.org/Breadcrumb">
|
36
|
+
# <a href="/foods/fruits/Red" itemprop="url">
|
37
|
+
# <span itemprop="title">Red</span>
|
38
|
+
# </a> /
|
39
|
+
# <div itemprop="child" itemscope itemtype="http://data-vocabulary.org/Breadcrumb">
|
40
|
+
# <a href="/foods/fruits/Red/Apple" itemprop="url">
|
41
|
+
# <span itemprop="title">Apple</span>
|
42
|
+
# </a>
|
43
|
+
# </div>
|
44
|
+
# </div>
|
45
|
+
# </div>
|
46
|
+
# </div>
|
47
|
+
# </nav>
|
48
|
+
|
49
|
+
|
50
|
+
let(:itemtype) { "http://data-vocabulary.org/Breadcrumb" }
|
51
|
+
|
52
|
+
describe "breadcrumbs" do
|
53
|
+
|
54
|
+
Snipp::ActionViewExtension::Spec::BREADCRUMBS.each do |e|
|
55
|
+
context e[:id] do
|
56
|
+
it "should have a `nav[itemscope]` tag" do
|
57
|
+
within(e[:id]) { expect(page).to have_selector("nav[itemtype=\"#{itemtype}\"][itemscope]", count: 1) }
|
58
|
+
end
|
59
|
+
it "should have correct number of `div[itemscope]` tags" do
|
60
|
+
within(e[:id]) { expect(page).to have_selector("div[itemtype=\"#{itemtype}\"][itemscope]", count: (e[:path].size - 1)) }
|
61
|
+
end
|
62
|
+
it "should have correct number of `itemprop` attribute that equals `child`" do
|
63
|
+
within(e[:id]) { expect(page).to have_selector('[itemprop="child"][itemscope]', count: (e[:path].size - 1)) }
|
64
|
+
end
|
65
|
+
it "should have correct number of `a[itemprop\"url\"]` tags" do
|
66
|
+
within(e[:id]) { expect(page).to have_selector('a[itemprop="url"]', count: e[:path].size) }
|
67
|
+
end
|
68
|
+
it "should have correct number of `span[itemprop\"title\"]` tags" do
|
69
|
+
within(e[:id]) { expect(page).to have_selector('span[itemprop="title"]', count: e[:path].size) }
|
70
|
+
end
|
71
|
+
it "should have correct number of separators" do
|
72
|
+
within(e[:id]) { expect(page).to have_content(e[:separator], count: (e[:path].size - 1)) }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "a variety of ways to define breadcrumbs" do
|
78
|
+
let(:html) { page.find("#case-B-1 nav").native.to_s }
|
79
|
+
|
80
|
+
it "should be equivalent" do
|
81
|
+
expect(page.find("#case-B-2 nav").native.to_s).to eq html
|
82
|
+
end
|
83
|
+
it "should be equivalent" do
|
84
|
+
expect(page.find("#case-B-3 nav").native.to_s).to eq html
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
data/spec/snipp_spec.rb
CHANGED
@@ -5,12 +5,10 @@ describe Snipp do
|
|
5
5
|
|
6
6
|
before do
|
7
7
|
Snipp::Hooks.init
|
8
|
-
visit "/"
|
9
|
-
puts page.html
|
8
|
+
visit "/foods/fruits/Red/Apple"
|
10
9
|
end
|
11
10
|
|
12
|
-
|
13
|
-
|
11
|
+
it "should be no error" do
|
12
|
+
expect(page).to have_content("Breadcumbs - Rich Snippets Sample")
|
14
13
|
end
|
15
|
-
|
16
14
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: snipp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -41,17 +41,21 @@ files:
|
|
41
41
|
- README.md
|
42
42
|
- Rakefile
|
43
43
|
- app/views/layouts/application.html.erb
|
44
|
+
- app/views/snipp/breadcrumb.html.erb
|
44
45
|
- app/views/snipp/index.html.erb
|
45
46
|
- config/locales/snipp.yml
|
46
47
|
- deploy_gem.sh
|
47
48
|
- lib/snipp.rb
|
49
|
+
- lib/snipp/config.rb
|
48
50
|
- lib/snipp/engine.rb
|
49
51
|
- lib/snipp/helpers/action_view_extension.rb
|
50
52
|
- lib/snipp/hooks.rb
|
53
|
+
- lib/snipp/markups/microdata.rb
|
51
54
|
- lib/snipp/railtie.rb
|
52
55
|
- lib/snipp/version.rb
|
53
56
|
- snipp.gemspec
|
54
57
|
- spec/fake_rails.rb
|
58
|
+
- spec/snipp/helpers/action_view_extension_spec.rb
|
55
59
|
- spec/snipp_spec.rb
|
56
60
|
- spec/spec_helper.rb
|
57
61
|
homepage: https://github.com/yulii/snipp
|
@@ -80,5 +84,6 @@ specification_version: 3
|
|
80
84
|
summary: Let search engines understand the content on your website
|
81
85
|
test_files:
|
82
86
|
- spec/fake_rails.rb
|
87
|
+
- spec/snipp/helpers/action_view_extension_spec.rb
|
83
88
|
- spec/snipp_spec.rb
|
84
89
|
- spec/spec_helper.rb
|