snipp 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/config/locales/snipp.yml +1 -1
- data/lib/snipp/config.rb +2 -2
- data/lib/snipp/markups/html.rb +48 -57
- data/lib/snipp/version.rb +1 -1
- data/spec/snipp/markups/html_spec.rb +164 -35
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 465823834c0c140c8671238c418ca36b48e9ec9b
|
4
|
+
data.tar.gz: c8b1abe51f22938ff64b7797427823a3ddf6bfac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d4b3efb494b9c37fbde22e170cc29b5e582c7fa22775b73680ec572d94a369343c59c5894b6e6a195fad38ed75cfb1ecd767face7178eb90223a0ad951d7854
|
7
|
+
data.tar.gz: 0c5a136614681a4908db3be3cc1fd7896b56ecbdeba44d694d21dc8e30f4b5360d455427aaf7595caf9ef1a4ec577e95ec715682568d8e99bf6de1cf51fa023f
|
data/.travis.yml
CHANGED
data/config/locales/snipp.yml
CHANGED
data/lib/snipp/config.rb
CHANGED
@@ -12,7 +12,7 @@ module Snipp
|
|
12
12
|
|
13
13
|
class Configuration #:nodoc:
|
14
14
|
include ActiveSupport::Configurable
|
15
|
-
config_accessor :root_url, :markup, :
|
15
|
+
config_accessor :root_url, :markup, :html_meta
|
16
16
|
|
17
17
|
def param_name
|
18
18
|
config.param_name.respond_to?(:call) ? config.param_name.call : config.param_name
|
@@ -26,7 +26,7 @@ module Snipp
|
|
26
26
|
|
27
27
|
configure do |config|
|
28
28
|
config.markup = :microdata
|
29
|
-
config.
|
29
|
+
config.html_meta = {
|
30
30
|
title: '',
|
31
31
|
description: '',
|
32
32
|
keywords: '',
|
data/lib/snipp/markups/html.rb
CHANGED
@@ -3,49 +3,30 @@ module Snipp
|
|
3
3
|
module Html
|
4
4
|
|
5
5
|
def set_html_meta args, options = {}
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
}.merge(options)
|
10
|
-
|
11
|
-
link = args.delete(:link)
|
12
|
-
html_meta.merge!(link: link) if link
|
13
|
-
|
14
|
-
Snipp.config.html_meta_tags.each do |name, content|
|
15
|
-
value = html_meta_contents(name, content, args[name], i18n_options)
|
16
|
-
html_meta[name] = value unless value.blank?
|
17
|
-
end
|
6
|
+
merger = lambda {|key, old, new| Hash === old && Hash === new ? old.merge(new, &merger) : new }
|
7
|
+
html_meta.merge!(args, &merger)
|
8
|
+
meta_options.merge!(options)
|
18
9
|
end
|
19
10
|
|
20
11
|
def set_html_meta! args
|
21
|
-
@html_meta =
|
22
|
-
link = args.delete(:link)
|
23
|
-
html_meta.merge!(link: link) if link
|
24
|
-
|
25
|
-
args.each do |name, content|
|
26
|
-
html_meta[name] = html_meta_contents(name, content, content, {}) if content
|
27
|
-
end
|
12
|
+
@html_meta = args
|
28
13
|
end
|
29
14
|
|
30
15
|
def html_meta_tags
|
31
16
|
result = ''
|
32
|
-
|
17
|
+
|
33
18
|
meta_link = html_meta.delete(:link)||{}
|
34
19
|
|
35
|
-
#
|
20
|
+
# Title
|
36
21
|
title = html_meta.delete(:title)
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
if content.is_a?(Hash)
|
44
|
-
result << build_meta_property_tags(name, content)
|
22
|
+
title = select_content(:title) if title.empty?
|
23
|
+
result << content_tag(:title, title) unless title.blank?
|
24
|
+
|
25
|
+
html_meta.each do |name, value|
|
26
|
+
if value.is_a?(Hash)
|
27
|
+
result << build_property_contents(value, name, name)
|
45
28
|
else
|
46
|
-
|
47
|
-
result << tag(:meta, name: name, content: c) unless c.blank?
|
48
|
-
end
|
29
|
+
result << build_contents(name, value)
|
49
30
|
end
|
50
31
|
end
|
51
32
|
|
@@ -57,45 +38,55 @@ module Snipp
|
|
57
38
|
end
|
58
39
|
|
59
40
|
private
|
60
|
-
def
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
41
|
+
def html_meta
|
42
|
+
@html_meta ||= Snipp.config.html_meta.dup
|
43
|
+
end
|
44
|
+
|
45
|
+
def meta_options
|
46
|
+
@meta_options ||= { default: '' }
|
47
|
+
end
|
48
|
+
|
49
|
+
def select_content key, options = {}
|
50
|
+
#puts key
|
51
|
+
options[:scope] ||= "views.#{params[:controller].gsub(%r{/}, '.')}.#{params[:action]}.meta"
|
52
|
+
options[:default] ||= 'default.meta'
|
53
|
+
content = I18n.t("#{options[:scope]}.#{key}" ,meta_options)
|
54
|
+
content = I18n.t("#{options[:default]}.#{key}" ,default: '') if content.empty?
|
55
|
+
content
|
56
|
+
end
|
57
|
+
|
58
|
+
# <meta name="xxx" content="yyy" />
|
59
|
+
def build_contents name, content
|
60
|
+
result = ''
|
61
|
+
Array(content).each do |content|
|
62
|
+
#puts "#{name} => #{content}"
|
63
|
+
content = select_content(name) if content.empty?
|
64
|
+
result << tag(:meta, name: name, content: content) unless content.empty?
|
73
65
|
end
|
74
66
|
result
|
75
67
|
end
|
76
68
|
|
77
|
-
|
69
|
+
# <meta property="xxx:yyy" content="zzz" />
|
70
|
+
def build_property_contents values, property, key
|
78
71
|
result = ''
|
79
|
-
if
|
80
|
-
|
81
|
-
result <<
|
72
|
+
if values.is_a?(Hash)
|
73
|
+
values.each do |k, v|
|
74
|
+
result << build_property_contents(v, "#{property}:#{k}", "#{key}.#{k}")
|
82
75
|
end
|
83
76
|
else
|
84
|
-
Array(
|
85
|
-
if
|
86
|
-
result <<
|
77
|
+
Array(values).each do |content|
|
78
|
+
if content.is_a?(Hash)
|
79
|
+
result << build_contents(content, property, key)
|
87
80
|
else
|
88
|
-
|
81
|
+
#puts "#{key} => #{content}"
|
82
|
+
content = select_content(key) if content.empty?
|
83
|
+
result << tag(:meta, property: "#{property}", content: content) unless content.empty?
|
89
84
|
end
|
90
85
|
end
|
91
86
|
end
|
92
87
|
result
|
93
88
|
end
|
94
89
|
|
95
|
-
def html_meta
|
96
|
-
@html_meta ||= {}
|
97
|
-
end
|
98
|
-
|
99
90
|
end
|
100
91
|
end
|
101
92
|
end
|
data/lib/snipp/version.rb
CHANGED
@@ -1,51 +1,180 @@
|
|
1
1
|
# coding: UTF-8
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
|
-
class Snipp::Markup::Html::Spec
|
5
|
-
|
6
|
-
DEFAULT_SCOPE = [:default, :meta]
|
7
|
-
PAGE_SCOPE = [:views, :snipp, :html, :meta]
|
8
|
-
|
9
|
-
META = {
|
10
|
-
title: I18n.t(:title ,scope: PAGE_SCOPE, value: "Embedding Values"),
|
11
|
-
description: I18n.t(:description ,scope: PAGE_SCOPE),
|
12
|
-
keywords: I18n.t(:keywords ,scope: DEFAULT_SCOPE)
|
13
|
-
}
|
14
|
-
OG = {
|
15
|
-
site_name: I18n.t("og.site_name" ,scope: DEFAULT_SCOPE),
|
16
|
-
title: I18n.t("og.title" ,scope: PAGE_SCOPE ,text: "Insert"),
|
17
|
-
description: I18n.t("og.description" ,scope: DEFAULT_SCOPE),
|
18
|
-
type: "article"
|
19
|
-
}
|
20
|
-
LINK = {
|
21
|
-
canonical: 'http://127.0.0.1/canonical'
|
22
|
-
}
|
23
|
-
end
|
24
|
-
|
25
4
|
describe Snipp::Markup::Html do
|
26
5
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
6
|
+
let(:view) do
|
7
|
+
clazz = Class.new do
|
8
|
+
include ActionView::Helpers
|
9
|
+
include Snipp::Markup::Html
|
10
|
+
end
|
11
|
+
view = clazz.new
|
12
|
+
view.stub(:params).and_return(params)
|
13
|
+
view
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:params) { { controller: "snipp", action: "html" } }
|
17
|
+
|
18
|
+
describe "#set_html_meta" do
|
19
|
+
let(:args) do
|
20
|
+
{
|
21
|
+
title: "Spec Title",
|
22
|
+
description: "Spec Description",
|
23
|
+
keywords: "Spec Keywords",
|
24
|
+
og: {
|
25
|
+
site_name: "Spec OG Site Name",
|
26
|
+
title: "Spec OG Title",
|
27
|
+
description: "Spec OG Description",
|
28
|
+
type: "article",
|
29
|
+
image: "https://github.com/yulii/snipp"
|
30
|
+
},
|
31
|
+
link: {
|
32
|
+
canonical: "https://github.com/yulii/snipp"
|
33
|
+
}
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
let(:object) do
|
38
|
+
view.set_html_meta(args.dup)
|
39
|
+
view.send(:html_meta)
|
40
|
+
end
|
41
|
+
|
42
|
+
it do
|
43
|
+
expect(object).to include(args)
|
44
|
+
end
|
45
|
+
|
46
|
+
context "when do nothing" do
|
47
|
+
let(:params) { { controller: "nothing", action: "undefined" } }
|
48
|
+
let(:args) do
|
49
|
+
Snipp.config.html_meta.select {|k, v| not v.nil? and not v.empty? }
|
50
|
+
end
|
51
|
+
|
52
|
+
it do
|
53
|
+
expect(object).to include(args)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "#html_meta_tags" do
|
59
|
+
let(:args) do
|
60
|
+
{
|
61
|
+
title: "Spec Title",
|
62
|
+
description: "Spec Description",
|
63
|
+
keywords: "Spec Keywords",
|
64
|
+
og: {
|
65
|
+
site_name: "Spec OG Site Name",
|
66
|
+
title: "Spec OG Title",
|
67
|
+
description: "Spec OG Description",
|
68
|
+
type: "article",
|
69
|
+
url: "https://github.com/yulii/snipp",
|
70
|
+
image: "https://github.com/yulii/snipp"
|
71
|
+
},
|
72
|
+
link: {
|
73
|
+
canonical: "https://github.com/yulii/snipp"
|
74
|
+
}
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
let(:object) do
|
79
|
+
view.set_html_meta(args.dup)
|
80
|
+
view.send(:html_meta_tags)
|
81
|
+
end
|
82
|
+
|
83
|
+
it { expect(object).to include(view.content_tag(:title, args[:title])) }
|
84
|
+
[:description, :keywords].each do |name|
|
85
|
+
it { expect(object).to include(view.tag(:meta, name: name, content: args[name])) }
|
86
|
+
end
|
87
|
+
[:site_name, :title, :description, :type, :url, :image].each do |property|
|
88
|
+
it { expect(object).to include(view.tag(:meta, property: "og:#{property}", content: args[:og][property])) }
|
89
|
+
end
|
90
|
+
[:canonical].each do |rel|
|
91
|
+
it { expect(object).to include(view.tag(:link, rel: rel, href: args[:link][rel])) }
|
92
|
+
end
|
93
|
+
|
31
94
|
end
|
32
95
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
96
|
+
describe "#select_content" do
|
97
|
+
let(:options) do
|
98
|
+
{ value: 'Value', default: '' }
|
99
|
+
end
|
100
|
+
|
101
|
+
let(:object) do
|
102
|
+
view.stub(:meta_options).and_return(options)
|
103
|
+
view
|
104
|
+
end
|
105
|
+
|
106
|
+
context "when there is I18n dictionary of controller/action" do
|
107
|
+
[:title, :description].each do |key|
|
108
|
+
it { expect(object.send(:select_content, key)).to eq(I18n.t("views.snipp.html.meta.#{key}", options)) }
|
37
109
|
end
|
38
110
|
end
|
39
|
-
|
40
|
-
|
41
|
-
|
111
|
+
|
112
|
+
context "when there is NOT I18n dictionary of controller/action" do
|
113
|
+
let(:params) { { controller: "nothing", action: "undefined" } }
|
114
|
+
|
115
|
+
[:title, :description, :keywords].each do |key|
|
116
|
+
it { expect(object.send(:select_content, key)).to eq(I18n.t("default.meta.#{key}")) }
|
117
|
+
end
|
118
|
+
[:site_name, :title, :description, :type].each do |property|
|
119
|
+
it { expect(object.send(:select_content, "og.#{property}")).to eq(I18n.t("default.meta.og.#{property}")) }
|
42
120
|
end
|
43
121
|
end
|
44
|
-
|
45
|
-
|
46
|
-
|
122
|
+
|
123
|
+
context "when there is no I18n dictionaries" do
|
124
|
+
[:nothing, :undefined].each do |key|
|
125
|
+
it { expect(view.send(:select_content, key)).to be_empty }
|
47
126
|
end
|
48
127
|
end
|
49
128
|
end
|
50
129
|
|
130
|
+
describe "#build_contents" do
|
131
|
+
context "when content is Scalar" do
|
132
|
+
it do
|
133
|
+
expect(
|
134
|
+
view.send(:build_contents, :name, 'content')
|
135
|
+
).to eq(
|
136
|
+
view.tag(:meta, name: :name, content: 'content')
|
137
|
+
)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
context "when content is Array" do
|
141
|
+
it do
|
142
|
+
expect(
|
143
|
+
view.send(:build_contents, 'robots', ['index', 'follow'])
|
144
|
+
).to eq(
|
145
|
+
view.tag(:meta, name: 'robots', content: 'index') +
|
146
|
+
view.tag(:meta, name: 'robots', content: 'follow')
|
147
|
+
)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
context "when content is empty string" do
|
151
|
+
it { expect(view.send(:build_contents, :name, '')).to be_empty }
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context "when HTML document has rendered" do
|
156
|
+
before(:all) do
|
157
|
+
Snipp::Hooks.init
|
158
|
+
visit "/html"
|
159
|
+
end
|
160
|
+
|
161
|
+
let(:scope) { 'views.snipp.html.meta' }
|
162
|
+
let(:default) { 'default.meta' }
|
163
|
+
let(:url) { 'http://127.0.0.1/canonical' }
|
164
|
+
|
165
|
+
# HTML Meta
|
166
|
+
it { expect(page).to have_selector("title", count: 1, text: I18n.t("#{scope}.title" ,value: "Embedding Values")) }
|
167
|
+
it { expect(page).to have_selector("meta[name=\"description\"][content=\"#{I18n.t("#{scope}.description")}\"]", count: 1) }
|
168
|
+
it { expect(page).to have_selector("meta[name=\"keywords\"][content=\"#{I18n.t("#{default}.keywords")}\"]", count: 1) }
|
169
|
+
|
170
|
+
# Open Graph
|
171
|
+
it { expect(page).to have_selector("meta[property=\"og:site_name\"][content=\"#{I18n.t("#{default}.og.site_name")}\"]", count: 1) }
|
172
|
+
it { expect(page).to have_selector("meta[property=\"og:type\"][content=\"#{I18n.t("#{default}.og.type")}\"]", count: 1) }
|
173
|
+
it { expect(page).to have_selector("meta[property=\"og:title\"][content=\"#{I18n.t("#{scope}.og.title" ,text: "Insert")}\"]", count: 1) }
|
174
|
+
it { expect(page).to have_selector("meta[property=\"og:description\"][content=\"#{I18n.t("#{default}.og.description")}\"]", count: 1) }
|
175
|
+
|
176
|
+
# Link Tags
|
177
|
+
it { expect(page).to have_selector("link[rel=\"canonical\"][href=\"#{url}\"]", count: 1) }
|
178
|
+
end
|
179
|
+
|
51
180
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: snipp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- yulii
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-09-
|
11
|
+
date: 2013-09-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|