meta-tags 2.1.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1 +1 @@
1
- ruby-2.2
1
+ 2.3.1
@@ -1,16 +1,25 @@
1
+ sudo: false
2
+ cache: bundler
3
+
1
4
  rvm:
2
5
  - 2.0.0
3
6
  - 2.1.7
4
- - 2.2.3
7
+ - 2.2.4
8
+ - 2.3.1
5
9
 
6
10
  env:
7
- - "RAILS_VERSION=3.1.0"
8
11
  - "RAILS_VERSION=3.2.0"
9
12
  - "RAILS_VERSION=4.0.0"
10
13
  - "RAILS_VERSION=4.1.0"
11
14
  - "RAILS_VERSION=4.2.0"
15
+ - "RAILS_VERSION=5.0.0"
12
16
 
13
17
  matrix:
18
+ exclude:
19
+ - rvm: 2.0.0
20
+ env: "RAILS_VERSION=5.0.0"
21
+ - rvm: 2.1.7
22
+ env: "RAILS_VERSION=5.0.0"
14
23
 
15
24
  notifications:
16
25
  recipients:
@@ -1,3 +1,22 @@
1
+ ## 2.2.0 (August 24, 2016)
2
+
3
+ Changes:
4
+
5
+ - Rails < 3.2 is not longer supported
6
+
7
+ Features:
8
+
9
+ - Added support for `<link rel="image_src" href="...">` tag
10
+ - Added support for App Links
11
+ - Added support for `follow` meta tag
12
+
13
+ Bugfixes:
14
+
15
+ - Fixed double escaping for ampersands (thanks to @srecnig)
16
+ - Removed usage of `alias_method_chain` to fix deprecation warnings with Rails 5
17
+ - Fixed the issue when title was truncated in some cases, when site_title was blank
18
+ - Fixed meta tag attributes for `fb:` meta tags
19
+
1
20
  ## 2.1.0 (October 6, 2015)
2
21
 
3
22
  Changes:
data/README.md CHANGED
@@ -9,8 +9,8 @@ Search Engine Optimization (SEO) plugin for Ruby on Rails applications.
9
9
 
10
10
  ## Ruby on Rails
11
11
 
12
- MetaTags master branch now fully supports Rails 3.0+ and is not backward
13
- compatible. Latest version fully compatible with 2.x is 1.2.3.
12
+ MetaTags master branch now fully supports Rails 3.2+, and is tested against all
13
+ major Rails releases up to 5.0.1.
14
14
 
15
15
  Ruby versions older than 2.0.0 are no longer officially supported.
16
16
 
@@ -110,6 +110,16 @@ Further reading:
110
110
  * [About rel="nofollow"](http://www.google.com/support/webmasters/bin/answer.py?answer=96569)
111
111
  * [Meta tags](http://www.google.com/support/webmasters/bin/answer.py?hl=en&answer=79812)
112
112
 
113
+ ### Follow
114
+
115
+ Follow will work with Noindex meta tag
116
+
117
+ set_meta_tags noindex: true, follow: true
118
+ # <meta name="robots" content="noindex, follow" />
119
+
120
+ It will not look at this page but will crawl through the rest of the pages on
121
+ your website.
122
+
113
123
  ### Canonical URL
114
124
 
115
125
  Canonical link element tells a search engine what is the canonical or main URL
@@ -177,7 +187,7 @@ translated or targeted to users in a certain region.
177
187
 
178
188
  set_meta_tags alternate: { "fr" => "http://yoursite.fr/alternate/url",
179
189
  "de" => "http://yoursite.de/alternate/url" }
180
- # <link rel="alternate" href="http://yoursite.fr/alternate/url" hreflang="en" />
190
+ # <link rel="alternate" href="http://yoursite.fr/alternate/url" hreflang="fr" />
181
191
  # <link rel="alternate" href="http://yoursite.de/alternate/url" hreflang="de" />
182
192
 
183
193
  If you need more than just multi-lingual links, you can use an alternative syntax:
@@ -210,6 +220,13 @@ Further reading:
210
220
  * [Pagination](http://support.google.com/webmasters/bin/answer.py?hl=en&answer=1663744)
211
221
  * [Pagination with rel="next" and rel="prev"](http://googlewebmastercentral.blogspot.ca/2011/09/pagination-with-relnext-and-relprev.html)
212
222
 
223
+ ### image_src links
224
+
225
+ Basically, when you submit/share this to Facebook , this helps Facebook determine which image to put next to the link. If this is not present, Facebook tries to put in the first image it finds on the page, which may not be the best one to represent your site.
226
+
227
+ set_meta_tags image_src: "http://yoursite.com/icons/icon_32.png"
228
+ # <link rel="image_src" href="http://yoursite.com/icons/icon_32.png" />
229
+
213
230
  ### Refresh interval and redirect URL
214
231
 
215
232
  Meta refresh is a method of instructing a web browser to automatically
@@ -357,6 +374,25 @@ Further reading:
357
374
 
358
375
  * [Twitter Cards Documentation](https://dev.twitter.com/docs/cards/)
359
376
 
377
+ ### App Links
378
+
379
+ App Links is an open cross platform solution for deep linking to content in your mobile app. Here's an example for iOS app integration:
380
+
381
+ set_meta_tags al: {
382
+ ios: {
383
+ url: "example://applinks",
384
+ app_store_id: 12345,
385
+ app_name: "Example App"
386
+ }
387
+ }
388
+ # <meta property="al:ios:url" content="example://applinks" />
389
+ # <meta property="al:ios:app_store_id" content="12345" />
390
+ # <meta property="al:ios:app_name" content="Example App" />
391
+
392
+ Further reading:
393
+
394
+ * [App Links Documentation](https://developers.facebook.com/docs/applinks)
395
+
360
396
  ### Custom meta tags
361
397
 
362
398
  Starting from version 1.3.1, you can specify arbitrary meta tags, and they will
@@ -455,11 +491,13 @@ Use these options to customize the title format:
455
491
  * `:reverse` — when true, the page and site names will be reversed;
456
492
  * `:noindex` — add noindex meta tag; when true, 'robots' will be used, otherwise the string will be used;
457
493
  * `:nofollow` — add nofollow meta tag; when true, 'robots' will be used, otherwise the string will be used;
494
+ * `:follow` – add follow meta tag; when true, 'robots' will be used, otherwise the string will be used;
458
495
  * `:canonical` — add canonical link tag;
459
496
  * `:author` — add author link tag;
460
497
  * `:publisher` — add publisher link tag;
461
498
  * `:prev` — add prev link tag;
462
499
  * `:next` — add next link tag;
500
+ * `:image_src` — add image_src link tag;
463
501
  * `:og` — add Open Graph tags (Hash);
464
502
  * `:twitter` — add Twitter tags (Hash);
465
503
  * `:refresh` — refresh interval and optionally url to redirect to.
@@ -546,4 +584,4 @@ And in your pjax templates:
546
584
 
547
585
  ## Author
548
586
 
549
- [Dmytro Shteflyuk](https://github.com/kpumuk), [http://kpumuk.info](http://kpumuk.info/)
587
+ [Dmytro Shteflyuk](https://github.com/kpumuk), [https://kpumuk.info](http://kpumuk.info/)
@@ -0,0 +1,21 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDcDCCAligAwIBAgIBATANBgkqhkiG9w0BAQUFADA/MQ8wDQYDVQQDDAZrcHVt
3
+ dWsxFjAUBgoJkiaJk/IsZAEZFgZrcHVtdWsxFDASBgoJkiaJk/IsZAEZFgRpbmZv
4
+ MB4XDTE2MDgyNDAxMDYwOFoXDTE3MDgyNDAxMDYwOFowPzEPMA0GA1UEAwwGa3B1
5
+ bXVrMRYwFAYKCZImiZPyLGQBGRYGa3B1bXVrMRQwEgYKCZImiZPyLGQBGRYEaW5m
6
+ bzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALw2YroZc+IT+rs8NuPu
7
+ c13DelrxrpAgPEu1zuRb3l7WaHRNWA4TyS8Z6Aa1G2O+FdUZNMW1n7IwP/QMJ9Mz
8
+ ahRBiTmhik5kasJ9s0h1lq5/hZiycm0o5OtGioUzCkvk+UEMpzMHbLmVSZCzYciy
9
+ NDRDbXB0rLLu1eJk+gKgn6Qf5vj93h1w28BdWdaA7YegtbmipZ+pjmzCQAfPActT
10
+ 6uXHG4dSo7Lz9jiFRI5dUizFbGXcRqkQ2b5AB8FFmfcvbqERvzQKBICnybjsKP0N
11
+ pJ3vGgO2sh5GvJFOPk1Vlur2nX9ZFznPEP1CEAQ+NFrmKRt355Z5sgOkAojSGnIL
12
+ /1sCAwEAAaN3MHUwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFPa4
13
+ VFc1YOlV1u/7EGTwMCAk8YE9MB0GA1UdEQQWMBSBEmtwdW11a0BrcHVtdWsuaW5m
14
+ bzAdBgNVHRIEFjAUgRJrcHVtdWtAa3B1bXVrLmluZm8wDQYJKoZIhvcNAQEFBQAD
15
+ ggEBAKOnJYyA5Aq2BPQTSd9uxUzoYL010HsxIz2xFPNRxcI9wvgy6tE7noUD6yu5
16
+ k/IXjQOiqMag0zGF3rdEbDFHsvDhos9xZeGUaM3YIfoYg4YF7P7HgRCQFYL7G3va
17
+ h++H5FhlqFOF8g4lvYZ80AMNBO/tDfGuIzaJFbv+1mlHc2Szd3t7Mt2kNae92OYJ
18
+ x9+w3/LzxW8XariFP1RBseVgHdH9JwbranEqRJ51WwJ0zTGgDnvGxOxigExXEfYE
19
+ He5T3dBG5WWdIclQcE+JgohBpQ78TcVs1pFNjFmW9pC/P7Rm2GlYqOPHBQG1/Qx9
20
+ ySbbrGHRLVz8DCxQbhKw+mdT5bg=
21
+ -----END CERTIFICATE-----
@@ -10,22 +10,15 @@ module MetaTags
10
10
  # as {ViewHelper#set_meta_tags}.
11
11
  #
12
12
  module ControllerHelper
13
- extend ActiveSupport::Concern
14
-
15
- included do
16
- alias_method_chain :render, :meta_tags
17
- end
18
-
19
13
  # Processes the <tt>@page_title</tt>, <tt>@page_keywords</tt>, and
20
14
  # <tt>@page_description</tt> instance variables and calls +render+.
21
- def render_with_meta_tags(*args, &block)
15
+ def render(*args, &block)
22
16
  self.meta_tags[:title] = @page_title if @page_title
23
17
  self.meta_tags[:keywords] = @page_keywords if @page_keywords
24
18
  self.meta_tags[:description] = @page_description if @page_description
25
19
 
26
- render_without_meta_tags(*args, &block)
20
+ super
27
21
  end
28
- protected :render_with_meta_tags
29
22
 
30
23
  # Set meta tags for the page.
31
24
  #
@@ -128,8 +128,11 @@ module MetaTags
128
128
  def extract_noindex
129
129
  noindex_name, noindex_value = extract_noindex_attribute(:noindex)
130
130
  nofollow_name, nofollow_value = extract_noindex_attribute(:nofollow)
131
+ follow_name, follow_value = extract_noindex_attribute(:follow)
131
132
 
132
- if noindex_name == nofollow_name
133
+ if noindex_name == follow_name && (follow_value && noindex_value)
134
+ { noindex_name => [noindex_value, follow_value].compact.join(', ') }
135
+ elsif noindex_name == nofollow_name
133
136
  { noindex_name => [noindex_value, nofollow_value].compact.join(', ') }
134
137
  else
135
138
  { noindex_name => noindex_value, nofollow_name => nofollow_value }
@@ -30,6 +30,8 @@ module MetaTags
30
30
  render_links(tags)
31
31
 
32
32
  render_hash(tags, :og, name_key: :property)
33
+ render_hash(tags, :al, name_key: :property)
34
+ render_hash(tags, :fb, name_key: :property)
33
35
  render_hashes(tags)
34
36
  render_custom(tags)
35
37
 
@@ -147,7 +149,7 @@ module MetaTags
147
149
  # @param [Array<Tag>] tags a buffer object to store tag in.
148
150
  #
149
151
  def render_links(tags)
150
- [ :canonical, :prev, :next, :author, :publisher ].each do |tag_name|
152
+ [ :canonical, :prev, :next, :author, :publisher, :image_src ].each do |tag_name|
151
153
  href = meta_tags.extract(tag_name)
152
154
  if href.present?
153
155
  @normalized_meta_tags[tag_name] = href
@@ -203,13 +205,13 @@ module MetaTags
203
205
  #
204
206
  def process_tree(tags, property, content, options = {})
205
207
  method = case content
206
- when Hash
207
- :process_hash
208
- when Array
209
- :process_array
210
- else
211
- :render_tag
212
- end
208
+ when Hash
209
+ :process_hash
210
+ when Array
211
+ :process_array
212
+ else
213
+ :render_tag
214
+ end
213
215
  send(method, tags, property, content, options)
214
216
  end
215
217
 
@@ -16,7 +16,13 @@ module MetaTags
16
16
  separator = strip_tags(separator)
17
17
 
18
18
  if MetaTags.config.title_limit
19
- limit = MetaTags.config.title_limit - separator.length
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
25
+
20
26
  if limit > site_title.length
21
27
  title = truncate_array(title, limit - site_title.length, separator)
22
28
  else
@@ -68,10 +74,16 @@ module MetaTags
68
74
  # Strips all HTML tags from the +html+, including comments.
69
75
  #
70
76
  # @param [String] string HTML string.
71
- # @return [String] string with no HTML tags.
77
+ # @return [String] html_safe string with no HTML tags.
72
78
  #
73
79
  def self.strip_tags(string)
74
- ERB::Util.html_escape helpers.strip_tags(string)
80
+ if defined?(Loofah)
81
+ # Instead of strip_tags we will use Loofah to strip tags from now on
82
+ stripped_unescaped = Loofah.fragment(string).text(encode_special_chars: false)
83
+ ERB::Util.html_escape stripped_unescaped
84
+ else
85
+ ERB::Util.html_escape helpers.strip_tags(string)
86
+ end
75
87
  end
76
88
 
77
89
  # This method returns a html safe string similar to what <tt>Array#join</tt>
@@ -115,8 +127,8 @@ module MetaTags
115
127
  # @return [String] truncated string.
116
128
  #
117
129
  def self.truncate(string, limit = nil, natural_separator = ' ')
118
- string = helpers.truncate(string, length: limit, separator: natural_separator, omission: '') if limit
119
- string
130
+ string = helpers.truncate(string, length: limit, separator: natural_separator, omission: '', escape: false) if limit
131
+ string.html_safe
120
132
  end
121
133
 
122
134
  # Truncates a string to a specific limit.
@@ -1,4 +1,4 @@
1
1
  module MetaTags
2
2
  # Gem version.
3
- VERSION = '2.1.0'
3
+ VERSION = '2.2.0'
4
4
  end
@@ -6,13 +6,14 @@ Gem::Specification.new do |s|
6
6
  s.name = 'meta-tags'
7
7
  s.version = MetaTags::VERSION
8
8
  s.platform = Gem::Platform::RUBY
9
+ s.license = "MIT"
9
10
  s.authors = ['Dmytro Shteflyuk']
10
11
  s.email = ['kpumuk@kpumuk.info']
11
12
  s.homepage = 'http://github.com/kpumuk/meta-tags'
12
13
  s.summary = %q{Collection of SEO helpers for Ruby on Rails.}
13
14
  s.description = %q{Search Engine Optimization (SEO) plugin for Ruby on Rails applications.}
14
15
 
15
- s.add_dependency 'actionpack', '>= 3.0.0'
16
+ s.add_dependency 'actionpack', '>= 3.2.0'
16
17
 
17
18
  s.add_development_dependency 'rake'
18
19
  s.add_development_dependency 'rspec', '~> 3.3.0'
@@ -20,6 +21,9 @@ Gem::Specification.new do |s|
20
21
  s.add_development_dependency 'yard'
21
22
  s.add_development_dependency 'bluecloth'
22
23
 
24
+ s.cert_chain = ['certs/kpumuk.pem']
25
+ s.signing_key = File.expand_path("~/.ssh/gem-kpumuk.pem") if $0 =~ /gem\z/
26
+
23
27
  s.files = `git ls-files`.split("\n")
24
28
  s.test_files = `git ls-files -- {spec}/*`.split("\n")
25
29
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
@@ -1,24 +1,27 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  class MetaTagsController < ActionController::Base
4
- attr_reader :rendered
5
-
6
- def render_without_meta_tags
7
- @rendered = true
8
- end
9
-
10
4
  def index
11
5
  @page_title = 'title'
12
6
  @page_keywords = 'key1, key2, key3'
13
7
  @page_description = 'description'
14
- render
8
+
9
+ if Gem.loaded_specs["actionpack"].version > Gem::Version.new('4.2.0')
10
+ render plain: '_rendered_'
11
+ else
12
+ render text: '_rendered_'
13
+ end
15
14
  end
16
15
 
17
16
  public :set_meta_tags, :meta_tags
18
17
  end
19
18
 
20
19
  describe MetaTags::ControllerHelper do
21
- subject { MetaTagsController.new }
20
+ subject {
21
+ MetaTagsController.new.tap do |c|
22
+ c.response = ActionDispatch::TestResponse.new
23
+ end
24
+ }
22
25
 
23
26
  context 'module' do
24
27
  it 'should be mixed into ActionController::Base' do
@@ -33,7 +36,7 @@ describe MetaTags::ControllerHelper do
33
36
  describe '.render' do
34
37
  it 'should set meta tags from instance variables' do
35
38
  subject.index
36
- expect(subject.rendered).to be_truthy
39
+ expect(subject.response.body).to eq('_rendered_')
37
40
  expect(subject.meta_tags.meta_tags).to eq('title' => 'title', 'keywords' => 'key1, key2, key3', 'description' => 'description')
38
41
  end
39
42
  end
@@ -14,6 +14,11 @@ describe MetaTags::TextNormalizer, '.normalize_title' do
14
14
  it 'should reverse title parts when reverse is true' do
15
15
  expect(subject.normalize_title('', %w[title subtitle], '-', true)).to eq('subtitle-title')
16
16
  end
17
+
18
+ it 'should not truncate title when limit is equal to the title length' do
19
+ title = 'b' * MetaTags.config.title_limit
20
+ expect(subject.normalize_title('', title, '-')).to eq(title)
21
+ end
17
22
  end
18
23
 
19
24
  context 'when site_title is specified' do
@@ -122,4 +122,25 @@ describe MetaTags::ViewHelper do
122
122
  end
123
123
  end
124
124
  end
125
+
126
+ context 'displaying image_src url' do
127
+ it 'should not display image_src url by default' do
128
+ subject.display_meta_tags(site: 'someSite').tap do |meta|
129
+ expect(meta).to_not have_tag('link', with: { href: "http://example.com/base/url", rel: "image_src" })
130
+ end
131
+ end
132
+
133
+ it 'should display image_src url when "set_meta_tags" used' do
134
+ subject.set_meta_tags(image_src: 'http://example.com/base/url')
135
+ subject.display_meta_tags(site: 'someSite').tap do |meta|
136
+ expect(meta).to have_tag('link', with: { href: "http://example.com/base/url", rel: "image_src" })
137
+ end
138
+ end
139
+
140
+ it 'should display default image_src url' do
141
+ subject.display_meta_tags(site: 'someSite', image_src: 'http://example.com/base/url').tap do |meta|
142
+ expect(meta).to have_tag('link', with: { href: "http://example.com/base/url", rel: "image_src" })
143
+ end
144
+ end
145
+ end
125
146
  end
@@ -28,13 +28,41 @@ describe MetaTags::ViewHelper do
28
28
  expect(subject.display_meta_tags).to eq('<title>someTitle</title>')
29
29
  end
30
30
 
31
- it 'should display title when "set_meta_tags" used' do
31
+ it 'should display title when "set_meta_tags" is used' do
32
32
  subject.set_meta_tags(title: 'someTitle')
33
33
  subject.display_meta_tags(site: 'someSite').tap do |meta|
34
34
  expect(meta).to eq('<title>someSite | someTitle</title>')
35
35
  end
36
36
  end
37
37
 
38
+ it 'should escape the title when "set_meta_tags" is used' do
39
+ subject.set_meta_tags(title: 'someTitle & somethingElse')
40
+ subject.display_meta_tags(site: 'someSite').tap do |meta|
41
+ expect(meta).to eq('<title>someSite | someTitle &amp; somethingElse</title>')
42
+ end
43
+ end
44
+
45
+ it 'should escape a very long title when "set_meta_tags" is used' do
46
+ subject.set_meta_tags(title: 'Kombucha kale chips forage try-hard & green juice. IPhone marfa PBR&B venmo listicle, irony kitsch thundercats.')
47
+ subject.display_meta_tags(site: 'someSite').tap do |meta|
48
+ expect(meta).to eq('<title>someSite | Kombucha kale chips forage try-hard &amp; green juice.</title>')
49
+ end
50
+ end
51
+
52
+ it 'should strip tags in the title' do
53
+ subject.set_meta_tags(title: '<b>hackxor</b>')
54
+ subject.display_meta_tags(site: 'someSite').tap do |meta|
55
+ expect(meta).to eq('<title>someSite | hackxor</title>')
56
+ end
57
+ end
58
+
59
+ it 'should strip tags from very long titles' do
60
+ subject.set_meta_tags(title: 'Kombucha <b>kale</b> chips forage try-hard & green juice. IPhone marfa PBR&B venmo listicle, irony kitsch thundercats.')
61
+ subject.display_meta_tags(site: 'someSite').tap do |meta|
62
+ expect(meta).to eq('<title>someSite | Kombucha kale chips forage try-hard &amp; green juice.</title>')
63
+ end
64
+ end
65
+
38
66
  it 'should display custom title if given' do
39
67
  subject.title('someTitle')
40
68
  subject.display_meta_tags(site: 'someSite', title: 'defaultTitle').tap do |meta|