meta-tags 2.4.1 → 2.5.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.codeclimate.yml +2 -3
- data/.rubocop.yml +110 -107
- data/.travis.yml +16 -28
- data/CHANGELOG.md +27 -19
- data/Gemfile +0 -1
- data/README.md +237 -214
- data/lib/meta_tags.rb +1 -0
- data/lib/meta_tags/configuration.rb +44 -0
- data/lib/meta_tags/meta_tags_collection.rb +7 -7
- data/lib/meta_tags/renderer.rb +54 -50
- data/lib/meta_tags/text_normalizer.rb +21 -11
- data/lib/meta_tags/version.rb +1 -1
- data/meta-tags.gemspec +1 -1
- metadata +2 -2
- metadata.gz.sig +0 -0
data/lib/meta_tags.rb
CHANGED
@@ -9,13 +9,57 @@ module MetaTags
|
|
9
9
|
attr_accessor :keywords_limit
|
10
10
|
# Keywords separator - a string to join keywords with.
|
11
11
|
attr_accessor :keywords_separator
|
12
|
+
# Custom meta tags that should use `property` attribute instead of `name`
|
13
|
+
# - an array of strings or symbols representing their names or name-prefixes.
|
14
|
+
attr_accessor :property_tags
|
12
15
|
|
13
16
|
# Initializes a new instance of Configuration class.
|
14
17
|
def initialize
|
18
|
+
reset_defaults!
|
19
|
+
end
|
20
|
+
|
21
|
+
def default_property_tags
|
22
|
+
[
|
23
|
+
# App Link metadata https://developers.facebook.com/docs/applinks/metadata-reference
|
24
|
+
'al',
|
25
|
+
# Open Graph Markup https://developers.facebook.com/docs/sharing/webmasters#markup
|
26
|
+
'fb',
|
27
|
+
'og',
|
28
|
+
# Facebook OpenGraph Object Types https://developers.facebook.com/docs/reference/opengraph
|
29
|
+
'article',
|
30
|
+
'book',
|
31
|
+
'books:author',
|
32
|
+
'books:book',
|
33
|
+
'books:genre',
|
34
|
+
'business:business',
|
35
|
+
'fitness:course',
|
36
|
+
'game:achievement',
|
37
|
+
'music:album',
|
38
|
+
'music:playlist',
|
39
|
+
'music:radio_station',
|
40
|
+
'music:song',
|
41
|
+
'place',
|
42
|
+
'product',
|
43
|
+
'product:group',
|
44
|
+
'product:item',
|
45
|
+
'profile',
|
46
|
+
'restaurant:menu',
|
47
|
+
'restaurant:menu_item',
|
48
|
+
'restaurant:menu_section',
|
49
|
+
'restaurant:restaurant',
|
50
|
+
'video:episode',
|
51
|
+
'video:movie',
|
52
|
+
'video:other',
|
53
|
+
'video:tv_show',
|
54
|
+
].freeze
|
55
|
+
end
|
56
|
+
|
57
|
+
def reset_defaults!
|
15
58
|
@title_limit = 70
|
16
59
|
@description_limit = 160
|
17
60
|
@keywords_limit = 255
|
18
61
|
@keywords_separator = ', '
|
62
|
+
@property_tags = default_property_tags.dup
|
19
63
|
end
|
20
64
|
end
|
21
65
|
end
|
@@ -57,7 +57,7 @@ module MetaTags
|
|
57
57
|
# @return [String] page title.
|
58
58
|
#
|
59
59
|
def full_title(defaults = {})
|
60
|
-
with_defaults(defaults) { extract_full_title
|
60
|
+
with_defaults(defaults) { extract_full_title }
|
61
61
|
end
|
62
62
|
|
63
63
|
# Deletes and returns a meta tag value by name.
|
@@ -85,7 +85,7 @@ module MetaTags
|
|
85
85
|
site_title = extract(:site) || ''
|
86
86
|
title = extract_title || []
|
87
87
|
separator = extract_separator
|
88
|
-
reverse = extract(:reverse)
|
88
|
+
reverse = extract(:reverse) == true
|
89
89
|
|
90
90
|
TextNormalizer.normalize_title(site_title, title, separator, reverse)
|
91
91
|
end
|
@@ -99,7 +99,7 @@ module MetaTags
|
|
99
99
|
return unless title
|
100
100
|
|
101
101
|
title = Array(title)
|
102
|
-
title.each(&:downcase!) if extract(:lowercase)
|
102
|
+
title.each(&:downcase!) if extract(:lowercase) == true
|
103
103
|
title
|
104
104
|
end
|
105
105
|
|
@@ -108,7 +108,7 @@ module MetaTags
|
|
108
108
|
# @return [String] page title separator.
|
109
109
|
#
|
110
110
|
def extract_separator
|
111
|
-
if meta_tags[:separator]
|
111
|
+
if meta_tags[:separator] == false
|
112
112
|
# Special case: if separator is hidden, do not display suffix/prefix
|
113
113
|
prefix = separator = suffix = ''
|
114
114
|
else
|
@@ -147,7 +147,7 @@ module MetaTags
|
|
147
147
|
# @return [HashWithIndifferentAccess] normalized meta tags list.
|
148
148
|
#
|
149
149
|
def normalize_open_graph(meta_tags)
|
150
|
-
meta_tags = meta_tags.
|
150
|
+
meta_tags = meta_tags.kind_of?(HashWithIndifferentAccess) ? meta_tags.dup : meta_tags.with_indifferent_access
|
151
151
|
meta_tags[:og] = meta_tags.delete(:open_graph) if meta_tags.key?(:open_graph)
|
152
152
|
meta_tags
|
153
153
|
end
|
@@ -160,7 +160,7 @@ module MetaTags
|
|
160
160
|
# @return [String] separator segment value.
|
161
161
|
#
|
162
162
|
def extract_separator_section(name, default)
|
163
|
-
meta_tags[name]
|
163
|
+
meta_tags[name] == false ? '' : (meta_tags[name] || default)
|
164
164
|
end
|
165
165
|
|
166
166
|
# Extracts noindex attribute name and value without deleting it from meta tags list.
|
@@ -170,7 +170,7 @@ module MetaTags
|
|
170
170
|
#
|
171
171
|
def extract_noindex_attribute(name)
|
172
172
|
noindex = extract(name)
|
173
|
-
noindex_name = String
|
173
|
+
noindex_name = noindex.kind_of?(String) ? noindex : 'robots'
|
174
174
|
noindex_value = noindex ? name.to_s : nil
|
175
175
|
|
176
176
|
[ noindex_name, noindex_value ]
|
data/lib/meta_tags/renderer.rb
CHANGED
@@ -29,11 +29,6 @@ module MetaTags
|
|
29
29
|
render_open_search(tags)
|
30
30
|
render_links(tags)
|
31
31
|
|
32
|
-
render_hash(tags, :og, name_key: :property)
|
33
|
-
render_hash(tags, :al, name_key: :property)
|
34
|
-
render_hash(tags, :fb, name_key: :property)
|
35
|
-
render_hash(tags, :article, name_key: :property)
|
36
|
-
render_hash(tags, :place, name_key: :property)
|
37
32
|
render_hashes(tags)
|
38
33
|
render_custom(tags)
|
39
34
|
|
@@ -42,15 +37,13 @@ module MetaTags
|
|
42
37
|
|
43
38
|
protected
|
44
39
|
|
45
|
-
|
46
40
|
# Renders charset tag.
|
47
41
|
#
|
48
42
|
# @param [Array<Tag>] tags a buffer object to store tag in.
|
49
43
|
#
|
50
44
|
def render_charset(tags)
|
51
|
-
|
52
|
-
|
53
|
-
end
|
45
|
+
charset = meta_tags.extract(:charset)
|
46
|
+
tags << Tag.new(:meta, charset: charset) if charset.present?
|
54
47
|
end
|
55
48
|
|
56
49
|
# Renders title tag.
|
@@ -68,15 +61,16 @@ module MetaTags
|
|
68
61
|
# @param [Array<Tag>] tags a buffer object to store tag in.
|
69
62
|
#
|
70
63
|
def render_icon(tags)
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
64
|
+
icon = meta_tags.extract(:icon)
|
65
|
+
return unless icon
|
66
|
+
|
67
|
+
if icon.kind_of?(String)
|
68
|
+
tags << Tag.new(:link, rel: 'icon', href: icon, type: 'image/x-icon')
|
69
|
+
else
|
70
|
+
icon = [icon] if icon.kind_of?(Hash)
|
71
|
+
icon.each do |icon_params|
|
72
|
+
icon_params = { rel: 'icon', type: 'image/x-icon' }.with_indifferent_access.merge(icon_params)
|
73
|
+
tags << Tag.new(:link, icon_params)
|
80
74
|
end
|
81
75
|
end
|
82
76
|
end
|
@@ -108,9 +102,8 @@ module MetaTags
|
|
108
102
|
# @param [Array<Tag>] tags a buffer object to store tag in.
|
109
103
|
#
|
110
104
|
def render_refresh(tags)
|
111
|
-
|
112
|
-
|
113
|
-
end
|
105
|
+
refresh = meta_tags.extract(:refresh)
|
106
|
+
tags << Tag.new(:meta, 'http-equiv' => 'refresh', content: refresh.to_s) if refresh.present?
|
114
107
|
end
|
115
108
|
|
116
109
|
# Renders alternate link tags.
|
@@ -118,15 +111,16 @@ module MetaTags
|
|
118
111
|
# @param [Array<Tag>] tags a buffer object to store tag in.
|
119
112
|
#
|
120
113
|
def render_alternate(tags)
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
114
|
+
alternate = meta_tags.extract(:alternate)
|
115
|
+
return unless alternate
|
116
|
+
|
117
|
+
if alternate.kind_of?(Hash)
|
118
|
+
alternate.each do |hreflang, href|
|
119
|
+
tags << Tag.new(:link, rel: 'alternate', href: href, hreflang: hreflang) if href.present?
|
120
|
+
end
|
121
|
+
elsif alternate.kind_of?(Array)
|
122
|
+
alternate.each do |link_params|
|
123
|
+
tags << Tag.new(:link, { rel: 'alternate' }.with_indifferent_access.merge(link_params))
|
130
124
|
end
|
131
125
|
end
|
132
126
|
end
|
@@ -136,14 +130,14 @@ module MetaTags
|
|
136
130
|
# @param [Array<Tag>] tags a buffer object to store tag in.
|
137
131
|
#
|
138
132
|
def render_open_search(tags)
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
133
|
+
open_search = meta_tags.extract(:open_search)
|
134
|
+
return unless open_search
|
135
|
+
|
136
|
+
href = open_search[:href]
|
137
|
+
title = open_search[:title]
|
138
|
+
|
139
|
+
type = "application/opensearchdescription+xml"
|
140
|
+
tags << Tag.new(:link, rel: 'search', type: type, href: href, title: title) if href.present?
|
147
141
|
end
|
148
142
|
|
149
143
|
# Renders links.
|
@@ -165,11 +159,8 @@ module MetaTags
|
|
165
159
|
# @param [Array<Tag>] tags a buffer object to store tag in.
|
166
160
|
#
|
167
161
|
def render_hashes(tags, options = {})
|
168
|
-
meta_tags.meta_tags.each do |property
|
169
|
-
|
170
|
-
process_hash(tags, property, data, options)
|
171
|
-
meta_tags.extract(property)
|
172
|
-
end
|
162
|
+
meta_tags.meta_tags.keys.each do |property|
|
163
|
+
render_hash(tags, property, options)
|
173
164
|
end
|
174
165
|
end
|
175
166
|
|
@@ -179,10 +170,10 @@ module MetaTags
|
|
179
170
|
#
|
180
171
|
def render_hash(tags, key, options = {})
|
181
172
|
data = meta_tags.meta_tags[key]
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
173
|
+
return unless data.kind_of?(Hash)
|
174
|
+
|
175
|
+
process_hash(tags, key, data, options)
|
176
|
+
meta_tags.extract(key)
|
186
177
|
end
|
187
178
|
|
188
179
|
# Renders custom meta tags.
|
@@ -192,7 +183,7 @@ module MetaTags
|
|
192
183
|
def render_custom(tags)
|
193
184
|
meta_tags.meta_tags.each do |name, data|
|
194
185
|
Array(data).each do |val|
|
195
|
-
tags << Tag.new(:meta, name
|
186
|
+
tags << Tag.new(:meta, configured_name_key(name) => name, content: val)
|
196
187
|
end
|
197
188
|
meta_tags.extract(name)
|
198
189
|
end
|
@@ -226,7 +217,7 @@ module MetaTags
|
|
226
217
|
def process_hash(tags, property, content, options = {})
|
227
218
|
content.each do |key, value|
|
228
219
|
key = key.to_s == '_' ? property : "#{property}:#{key}"
|
229
|
-
value = normalized_meta_tags[value] if value.
|
220
|
+
value = normalized_meta_tags[value] if value.kind_of?(Symbol)
|
230
221
|
process_tree(tags, key, value, options)
|
231
222
|
end
|
232
223
|
end
|
@@ -249,9 +240,22 @@ module MetaTags
|
|
249
240
|
# top-level meta tag.
|
250
241
|
#
|
251
242
|
def render_tag(tags, name, value, options = {})
|
252
|
-
name_key = options.fetch(:name_key,
|
243
|
+
name_key = options.fetch(:name_key, configured_name_key(name))
|
253
244
|
value_key = options.fetch(:value_key, :content)
|
254
245
|
tags << Tag.new(:meta, name_key => name.to_s, value_key => value) unless value.blank?
|
255
246
|
end
|
247
|
+
|
248
|
+
# Returns meta tag property name for a give meta tag based on the
|
249
|
+
# configured list of property tags in MetaTags::Configuration#property_tags.
|
250
|
+
#
|
251
|
+
# @param [String, Symbol] meta tag key.
|
252
|
+
# @return [String] meta tag attribute name ("property" or "name").
|
253
|
+
#
|
254
|
+
def configured_name_key(name)
|
255
|
+
is_property_tag = MetaTags.config.property_tags.any? do |tag_name|
|
256
|
+
name.to_s.match(/^#{Regexp.escape(tag_name.to_s)}\b/)
|
257
|
+
end
|
258
|
+
is_property_tag ? :property : :name
|
259
|
+
end
|
256
260
|
end
|
257
261
|
end
|
@@ -10,18 +10,12 @@ module MetaTags
|
|
10
10
|
# @return [Array<String>] array of title parts with tags removed.
|
11
11
|
#
|
12
12
|
def self.normalize_title(site_title, title, separator, reverse = false)
|
13
|
-
title = Array(title).flatten.map(&method(:strip_tags))
|
14
|
-
title.reject!(&:blank?)
|
13
|
+
title = Array(title).flatten.map(&method(:strip_tags)).reject(&:blank?)
|
15
14
|
site_title = strip_tags(site_title)
|
16
15
|
separator = strip_tags(separator)
|
17
16
|
|
18
17
|
if MetaTags.config.title_limit
|
19
|
-
limit =
|
20
|
-
MetaTags.config.title_limit - separator.length
|
21
|
-
else
|
22
|
-
# separtor won't be used: ignore its length
|
23
|
-
MetaTags.config.title_limit
|
24
|
-
end
|
18
|
+
limit = calculate_limit(site_title, separator)
|
25
19
|
|
26
20
|
if limit > site_title.length
|
27
21
|
title = truncate_array(title, limit - site_title.length, separator)
|
@@ -95,7 +89,7 @@ module MetaTags
|
|
95
89
|
# @param [String] sep separator to join strings with.
|
96
90
|
# @return [String] input strings joined together using a given separator.
|
97
91
|
#
|
98
|
-
def self.safe_join(array, sep =
|
92
|
+
def self.safe_join(array, sep = $OFS)
|
99
93
|
helpers.safe_join(array, sep)
|
100
94
|
end
|
101
95
|
|
@@ -140,21 +134,37 @@ module MetaTags
|
|
140
134
|
# @return [String] truncated string.
|
141
135
|
#
|
142
136
|
def self.truncate_array(string_array, limit = nil, separator = '', natural_separator = ' ')
|
143
|
-
return string_array if limit.nil? || limit
|
137
|
+
return string_array if limit.nil? || limit.zero?
|
138
|
+
|
144
139
|
length = 0
|
145
140
|
result = []
|
141
|
+
|
146
142
|
string_array.each do |string|
|
147
|
-
limit_left = limit
|
143
|
+
limit_left = calculate_limit_left(limit, length, result, separator)
|
144
|
+
|
148
145
|
if string.length > limit_left
|
149
146
|
result << truncate(string, limit_left, natural_separator)
|
150
147
|
break
|
151
148
|
end
|
149
|
+
|
152
150
|
length += (result.any? ? separator.length : 0) + string.length
|
153
151
|
result << string
|
152
|
+
|
154
153
|
# No more strings will fit
|
155
154
|
break if length + separator.length >= limit
|
156
155
|
end
|
156
|
+
|
157
157
|
result
|
158
158
|
end
|
159
|
+
|
160
|
+
def self.calculate_limit_left(limit, length, result, separator)
|
161
|
+
limit - length - (result.any? ? separator.length : 0)
|
162
|
+
end
|
163
|
+
|
164
|
+
def self.calculate_limit(site_title, separator)
|
165
|
+
return MetaTags.config.title_limit unless site_title.present?
|
166
|
+
|
167
|
+
MetaTags.config.title_limit - separator.length
|
168
|
+
end
|
159
169
|
end
|
160
170
|
end
|
data/lib/meta_tags/version.rb
CHANGED
data/meta-tags.gemspec
CHANGED
@@ -27,5 +27,5 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.add_development_dependency "rspec-html-matchers", "~> 0.8.0"
|
28
28
|
|
29
29
|
spec.cert_chain = ["certs/kpumuk.pem"]
|
30
|
-
spec.signing_key = File.expand_path("~/.ssh/gem-kpumuk.pem") if $
|
30
|
+
spec.signing_key = File.expand_path("~/.ssh/gem-kpumuk.pem") if $PROGRAM_NAME =~ /gem\z/
|
31
31
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: meta-tags
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dmytro Shteflyuk
|
@@ -30,7 +30,7 @@ cert_chain:
|
|
30
30
|
He5T3dBG5WWdIclQcE+JgohBpQ78TcVs1pFNjFmW9pC/P7Rm2GlYqOPHBQG1/Qx9
|
31
31
|
ySbbrGHRLVz8DCxQbhKw+mdT5bg=
|
32
32
|
-----END CERTIFICATE-----
|
33
|
-
date: 2017-
|
33
|
+
date: 2017-08-23 00:00:00.000000000 Z
|
34
34
|
dependencies:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: actionpack
|
metadata.gz.sig
CHANGED
Binary file
|