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.
@@ -1,3 +1,4 @@
1
+ require 'English'
1
2
  require 'action_controller'
2
3
  require 'action_view'
3
4
 
@@ -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) === true
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) === true
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] === false
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.is_a?(HashWithIndifferentAccess) ? meta_tags.dup : meta_tags.with_indifferent_access
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] === false ? '' : (meta_tags[name] || default)
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 === noindex ? noindex : 'robots'
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 ]
@@ -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
- if charset = meta_tags.extract(:charset)
52
- tags << Tag.new(:meta, charset: charset) if charset.present?
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
- if icon = meta_tags.extract(:icon)
72
- if String === icon
73
- tags << Tag.new(:link, rel: 'icon', href: icon, type: 'image/x-icon')
74
- else
75
- icon = [icon] if Hash === icon
76
- icon.each do |icon_params|
77
- icon_params = { rel: 'icon', type: 'image/x-icon' }.with_indifferent_access.merge(icon_params)
78
- tags << Tag.new(:link, icon_params)
79
- end
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
- if refresh = meta_tags.extract(:refresh)
112
- tags << Tag.new(:meta, 'http-equiv' => 'refresh', content: refresh.to_s) if refresh.present?
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
- if alternate = meta_tags.extract(:alternate)
122
- if Hash === alternate
123
- alternate.each do |hreflang, href|
124
- tags << Tag.new(:link, rel: 'alternate', href: href, hreflang: hreflang) if href.present?
125
- end
126
- elsif Array === alternate
127
- alternate.each do |link_params|
128
- tags << Tag.new(:link, { rel: 'alternate' }.with_indifferent_access.merge(link_params))
129
- end
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
- if open_search = meta_tags.extract(:open_search)
140
- href = open_search[:href]
141
- title = open_search[:title]
142
- if href.present?
143
- type = "application/opensearchdescription+xml"
144
- tags << Tag.new(:link, rel: 'search', type: type, href: href, title: title)
145
- end
146
- end
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, data|
169
- if data.is_a?(Hash)
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
- if data.is_a?(Hash)
183
- process_hash(tags, key, data, options)
184
- meta_tags.extract(key)
185
- end
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: name, content: val)
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.is_a?(Symbol)
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, :name)
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 = if site_title.present?
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 == 0
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 - length - (result.any? ? separator.length : 0)
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
@@ -1,4 +1,4 @@
1
1
  module MetaTags
2
2
  # Gem version.
3
- VERSION = '2.4.1'
3
+ VERSION = '2.5.0'
4
4
  end
@@ -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 $0 =~ /gem\z/
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.1
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-05-15 00:00:00.000000000 Z
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