meta_tags-rails 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/.rspec +3 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +21 -0
- data/CHANGELOG.md +135 -0
- data/Gemfile +13 -0
- data/MIT-LICENSE +22 -0
- data/README.md +627 -0
- data/Rakefile +28 -0
- data/lib/meta_tags-rails.rb +37 -0
- data/lib/meta_tags-rails/configuration.rb +21 -0
- data/lib/meta_tags-rails/content_tag.rb +14 -0
- data/lib/meta_tags-rails/controller_helper.rb +44 -0
- data/lib/meta_tags-rails/meta_tags_collection.rb +176 -0
- data/lib/meta_tags-rails/renderer.rb +253 -0
- data/lib/meta_tags-rails/tag.rb +25 -0
- data/lib/meta_tags-rails/text_normalizer.rb +148 -0
- data/lib/meta_tags-rails/version.rb +4 -0
- data/lib/meta_tags-rails/view_helper.rb +205 -0
- data/meta-tags.gemspec +30 -0
- data/spec/configuration_spec.rb +14 -0
- data/spec/controller_helper_spec.rb +42 -0
- data/spec/spec_helper.rb +84 -0
- data/spec/text_normalizer/normalize_title_spec.rb +43 -0
- data/spec/text_normalizer/truncate_array_spec.rb +60 -0
- data/spec/view_helper/charset_spec.rb +16 -0
- data/spec/view_helper/custom_spec.rb +67 -0
- data/spec/view_helper/description_spec.rb +61 -0
- data/spec/view_helper/icon_spec.rb +42 -0
- data/spec/view_helper/keywords_spec.rb +58 -0
- data/spec/view_helper/links_spec.rb +125 -0
- data/spec/view_helper/module_spec.rb +41 -0
- data/spec/view_helper/noindex_spec.rb +107 -0
- data/spec/view_helper/open_graph_spec.rb +86 -0
- data/spec/view_helper/open_search_spec.rb +33 -0
- data/spec/view_helper/refresh_spec.rb +32 -0
- data/spec/view_helper/title_spec.rb +155 -0
- data/spec/view_helper/twitter_spec.rb +31 -0
- data/spec/view_helper_spec.rb +57 -0
- metadata +172 -0
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
6
|
+
|
7
|
+
task test: :spec
|
8
|
+
task default: :spec
|
9
|
+
|
10
|
+
desc 'Starts irb with MetaTags gem loaded'
|
11
|
+
task :console do
|
12
|
+
require 'irb'
|
13
|
+
|
14
|
+
$:.unshift File.expand_path('../lib', __FILE__)
|
15
|
+
require 'meta_tags'
|
16
|
+
ARGV.clear
|
17
|
+
IRB.start
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'yard'
|
21
|
+
YARD::Rake::YardocTask.new(:yard) do |t|
|
22
|
+
t.options = ['--title', 'MetaTags Documentation']
|
23
|
+
if ENV['PRIVATE']
|
24
|
+
t.options.concat ['--protected', '--private']
|
25
|
+
else
|
26
|
+
t.options.concat ['--protected', '--no-private']
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'action_controller'
|
2
|
+
require 'action_view'
|
3
|
+
|
4
|
+
# MetaTags gem namespace.
|
5
|
+
module MetaTags
|
6
|
+
# Returns MetaTags gem configuration.
|
7
|
+
#
|
8
|
+
def self.config
|
9
|
+
@@config ||= Configuration.new
|
10
|
+
end
|
11
|
+
|
12
|
+
# Configures MetaTags gem.
|
13
|
+
#
|
14
|
+
# @yield [Configuration] configuration object.
|
15
|
+
# @example
|
16
|
+
#
|
17
|
+
# MetaTags.configure do |config|
|
18
|
+
# # config.title_limit = 100
|
19
|
+
# end
|
20
|
+
def self.configure
|
21
|
+
yield config
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'meta_tags-rails/version'
|
26
|
+
|
27
|
+
require 'meta_tags-rails/configuration'
|
28
|
+
require 'meta_tags-rails/controller_helper'
|
29
|
+
require 'meta_tags-rails/meta_tags_collection'
|
30
|
+
require 'meta_tags-rails/renderer'
|
31
|
+
require 'meta_tags-rails/tag'
|
32
|
+
require 'meta_tags-rails/content_tag'
|
33
|
+
require 'meta_tags-rails/text_normalizer'
|
34
|
+
require 'meta_tags-rails/view_helper'
|
35
|
+
|
36
|
+
ActionView::Base.send :include, MetaTags::ViewHelper
|
37
|
+
ActionController::Base.send :include, MetaTags::ControllerHelper
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module MetaTags
|
2
|
+
# MetaTags configuration.
|
3
|
+
class Configuration
|
4
|
+
# How many characters to truncate title to.
|
5
|
+
attr_accessor :title_limit
|
6
|
+
# How many characters to truncate description to.
|
7
|
+
attr_accessor :description_limit
|
8
|
+
# How many characters to truncate keywords to.
|
9
|
+
attr_accessor :keywords_limit
|
10
|
+
# Keywords separator - a string to join keywords with.
|
11
|
+
attr_accessor :keywords_separator
|
12
|
+
|
13
|
+
# Initializes a new instance of Configuration class.
|
14
|
+
def initialize
|
15
|
+
@title_limit = 70
|
16
|
+
@description_limit = 160
|
17
|
+
@keywords_limit = 255
|
18
|
+
@keywords_separator = ', '
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module MetaTags
|
2
|
+
# Represents an HTML meta tag with content (<tag></tag>).
|
3
|
+
# Content should be passed as a `:content` attribute.
|
4
|
+
class ContentTag < Tag
|
5
|
+
# Render tag into a Rails view.
|
6
|
+
#
|
7
|
+
# @param [ActionView::Base] view instance of a Rails view.
|
8
|
+
# @return [String] HTML string for the tag.
|
9
|
+
#
|
10
|
+
def render(view)
|
11
|
+
view.content_tag(name, attributes[:content], attributes.except(:content))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module MetaTags
|
2
|
+
# Contains methods to use in controllers.
|
3
|
+
#
|
4
|
+
# You can define several instance variables to set meta tags:
|
5
|
+
# @page_title = 'Member Login'
|
6
|
+
# @page_description = 'Member login page.'
|
7
|
+
# @page_keywords = 'Site, Login, Members'
|
8
|
+
#
|
9
|
+
# Also you can use {#set_meta_tags} method, that have the same parameters
|
10
|
+
# as {ViewHelper#set_meta_tags}.
|
11
|
+
#
|
12
|
+
module ControllerHelper
|
13
|
+
extend ActiveSupport::Concern
|
14
|
+
|
15
|
+
included do
|
16
|
+
alias_method_chain :render, :meta_tags
|
17
|
+
end
|
18
|
+
|
19
|
+
# Processes the <tt>@page_title</tt>, <tt>@page_keywords</tt>, and
|
20
|
+
# <tt>@page_description</tt> instance variables and calls +render+.
|
21
|
+
def render_with_meta_tags(*args, &block)
|
22
|
+
self.meta_tags[:title] = @page_title if @page_title
|
23
|
+
self.meta_tags[:keywords] = @page_keywords if @page_keywords
|
24
|
+
self.meta_tags[:description] = @page_description if @page_description
|
25
|
+
|
26
|
+
render_without_meta_tags(*args, &block)
|
27
|
+
end
|
28
|
+
protected :render_with_meta_tags
|
29
|
+
|
30
|
+
# Set meta tags for the page.
|
31
|
+
#
|
32
|
+
# See <tt>MetaTags::ViewHelper#set_meta_tags</tt> for details.
|
33
|
+
def set_meta_tags(meta_tags)
|
34
|
+
self.meta_tags.update(meta_tags)
|
35
|
+
end
|
36
|
+
protected :set_meta_tags
|
37
|
+
|
38
|
+
# Get meta tags for the page.
|
39
|
+
def meta_tags
|
40
|
+
@meta_tags ||= MetaTagsCollection.new
|
41
|
+
end
|
42
|
+
protected :meta_tags
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
module MetaTags
|
2
|
+
# Class represents a collection of meta tags. Basically a wrapper around
|
3
|
+
# HashWithIndifferentAccess, with some additional helper methods.
|
4
|
+
class MetaTagsCollection
|
5
|
+
attr_reader :meta_tags
|
6
|
+
|
7
|
+
# Initializes a new instance of MetaTagsCollection.
|
8
|
+
#
|
9
|
+
def initialize
|
10
|
+
@meta_tags = HashWithIndifferentAccess.new
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns meta tag value by name.
|
14
|
+
#
|
15
|
+
# @param [String, Symbol] name meta tag name.
|
16
|
+
# @return meta tag value.
|
17
|
+
#
|
18
|
+
def [](name)
|
19
|
+
@meta_tags[name]
|
20
|
+
end
|
21
|
+
|
22
|
+
# Sets meta tag value by name.
|
23
|
+
#
|
24
|
+
# @param [String, Symbol] name meta tag name.
|
25
|
+
# @param value meta tag value.
|
26
|
+
# @return meta tag value.
|
27
|
+
#
|
28
|
+
def []=(name, value)
|
29
|
+
@meta_tags[name] = value
|
30
|
+
end
|
31
|
+
|
32
|
+
# Recursively merges a Hash of meta tag attributes into current list.
|
33
|
+
#
|
34
|
+
# @param [Hash] meta_tags meta tags Hash to merge into current list.
|
35
|
+
# @return [Hash] result of the merge.
|
36
|
+
#
|
37
|
+
def update(meta_tags = {})
|
38
|
+
@meta_tags.deep_merge! normalize_open_graph(meta_tags)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Temporary merges defaults with current meta tags list and yields the block.
|
42
|
+
#
|
43
|
+
# @param [Hash] defaults list of default meta tag attributes.
|
44
|
+
# @return result of the block call.
|
45
|
+
#
|
46
|
+
def with_defaults(defaults = {})
|
47
|
+
old_meta_tags = @meta_tags
|
48
|
+
@meta_tags = normalize_open_graph(defaults).deep_merge!(self.meta_tags)
|
49
|
+
yield
|
50
|
+
ensure
|
51
|
+
@meta_tags = old_meta_tags
|
52
|
+
end
|
53
|
+
|
54
|
+
# Constructs the full title as if it would be rendered in title meta tag.
|
55
|
+
#
|
56
|
+
# @param [Hash] defaults list of default meta tag attributes.
|
57
|
+
# @return [String] page title.
|
58
|
+
#
|
59
|
+
def full_title(defaults = {})
|
60
|
+
with_defaults(defaults) { extract_full_title }
|
61
|
+
end
|
62
|
+
|
63
|
+
# Deletes and returns a meta tag value by name.
|
64
|
+
#
|
65
|
+
# @param [String, Symbol] name meta tag name.
|
66
|
+
# @return [Object] meta tag value.
|
67
|
+
#
|
68
|
+
def extract(name)
|
69
|
+
@meta_tags.delete(name)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Deletes specified meta tags.
|
73
|
+
#
|
74
|
+
# @param [Array<String, Symbol>] names a list of meta tags to delete.
|
75
|
+
#
|
76
|
+
def delete(*names)
|
77
|
+
names.each { |name| @meta_tags.delete(name) }
|
78
|
+
end
|
79
|
+
|
80
|
+
# Extracts full page title and deletes all related meta tags.
|
81
|
+
#
|
82
|
+
# @return [String] page title.
|
83
|
+
#
|
84
|
+
def extract_full_title
|
85
|
+
site_title = extract(:site) || ''
|
86
|
+
title = extract_title || []
|
87
|
+
separator = extract_separator
|
88
|
+
reverse = extract(:reverse) === true
|
89
|
+
|
90
|
+
TextNormalizer.normalize_title(site_title, title, separator, reverse)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Extracts page title as an array of segments without site title and separators.
|
94
|
+
#
|
95
|
+
# @return [Array<String>] segments of page title.
|
96
|
+
#
|
97
|
+
def extract_title
|
98
|
+
title = extract(:title).presence
|
99
|
+
return unless title
|
100
|
+
|
101
|
+
title = Array(title)
|
102
|
+
title.each(&:downcase!) if extract(:lowercase) === true
|
103
|
+
title
|
104
|
+
end
|
105
|
+
|
106
|
+
# Extracts title separator as a string.
|
107
|
+
#
|
108
|
+
# @return [String] page title separator.
|
109
|
+
#
|
110
|
+
def extract_separator
|
111
|
+
if meta_tags[:separator] === false
|
112
|
+
# Special case: if separator is hidden, do not display suffix/prefix
|
113
|
+
prefix = separator = suffix = ''
|
114
|
+
else
|
115
|
+
prefix = extract_separator_section(:prefix, ' ')
|
116
|
+
separator = extract_separator_section(:separator, '|')
|
117
|
+
suffix = extract_separator_section(:suffix, ' ')
|
118
|
+
end
|
119
|
+
delete(:separator, :prefix, :suffix)
|
120
|
+
|
121
|
+
TextNormalizer.safe_join([prefix, separator, suffix], '')
|
122
|
+
end
|
123
|
+
|
124
|
+
# Extracts noindex settings as a Hash mapping noindex tag name to value.
|
125
|
+
#
|
126
|
+
# @return [Hash<String,String>] noindex attributes.
|
127
|
+
#
|
128
|
+
def extract_noindex
|
129
|
+
noindex_name, noindex_value = extract_noindex_attribute(:noindex)
|
130
|
+
nofollow_name, nofollow_value = extract_noindex_attribute(:nofollow)
|
131
|
+
|
132
|
+
if noindex_name == nofollow_name
|
133
|
+
{ noindex_name => [noindex_value, nofollow_value].compact.join(', ') }
|
134
|
+
else
|
135
|
+
{ noindex_name => noindex_value, nofollow_name => nofollow_value }
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
protected
|
140
|
+
|
141
|
+
# Converts input hash to HashWithIndifferentAccess and renames :open_graph to :og.
|
142
|
+
#
|
143
|
+
# @param [Hash] meta_tags list of meta tags.
|
144
|
+
# @return [HashWithIndifferentAccess] normalized meta tags list.
|
145
|
+
#
|
146
|
+
def normalize_open_graph(meta_tags)
|
147
|
+
meta_tags = meta_tags.is_a?(HashWithIndifferentAccess) ? meta_tags.dup : meta_tags.with_indifferent_access
|
148
|
+
meta_tags[:og] = meta_tags.delete(:open_graph) if meta_tags.key?(:open_graph)
|
149
|
+
meta_tags
|
150
|
+
end
|
151
|
+
|
152
|
+
# Extracts separator segment without deleting it from meta tags list.
|
153
|
+
# If the value is false, empty string will be returned.
|
154
|
+
#
|
155
|
+
# @param [Symbol, String] name separator segment name.
|
156
|
+
# @param [String] default default value.
|
157
|
+
# @return [String] separator segment value.
|
158
|
+
#
|
159
|
+
def extract_separator_section(name, default)
|
160
|
+
meta_tags[name] === false ? '' : (meta_tags[name] || default)
|
161
|
+
end
|
162
|
+
|
163
|
+
# Extracts noindex attribute name and value without deleting it from meta tags list.
|
164
|
+
#
|
165
|
+
# @param [String, Symbol] name noindex attribute name.
|
166
|
+
# @return [Array<String>] pair of noindex attribute name and value.
|
167
|
+
#
|
168
|
+
def extract_noindex_attribute(name)
|
169
|
+
noindex = extract(name)
|
170
|
+
noindex_name = String === noindex ? noindex : 'robots'
|
171
|
+
noindex_value = noindex ? name.to_s : nil
|
172
|
+
|
173
|
+
[ noindex_name, noindex_value ]
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -0,0 +1,253 @@
|
|
1
|
+
module MetaTags
|
2
|
+
# This class is used by MetaTags gems to render HTML meta tags into page.
|
3
|
+
class Renderer
|
4
|
+
attr_reader :meta_tags, :normalized_meta_tags
|
5
|
+
|
6
|
+
# Initialized a new instance of Renderer.
|
7
|
+
#
|
8
|
+
# @param [MetaTagsCollection] meta_tags meta tags object to render.
|
9
|
+
#
|
10
|
+
def initialize(meta_tags)
|
11
|
+
@meta_tags = meta_tags
|
12
|
+
@normalized_meta_tags = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
# Renders meta tags on the page.
|
16
|
+
#
|
17
|
+
# @param [ActionView::Base] view Rails view object.
|
18
|
+
def render(view)
|
19
|
+
tags = []
|
20
|
+
|
21
|
+
render_charset(tags)
|
22
|
+
render_title(tags)
|
23
|
+
render_icon(tags)
|
24
|
+
render_with_normalization(tags, :description)
|
25
|
+
render_with_normalization(tags, :keywords)
|
26
|
+
render_refresh(tags)
|
27
|
+
render_noindex(tags)
|
28
|
+
render_alternate(tags)
|
29
|
+
render_open_search(tags)
|
30
|
+
render_links(tags)
|
31
|
+
|
32
|
+
render_hash(tags, :og, name_key: :property)
|
33
|
+
render_hashes(tags)
|
34
|
+
render_custom(tags)
|
35
|
+
|
36
|
+
tags.compact.map { |tag| tag.render(view) }.join("\n").html_safe
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
|
41
|
+
|
42
|
+
# Renders charset tag.
|
43
|
+
#
|
44
|
+
# @param [Array<Tag>] tags a buffer object to store tag in.
|
45
|
+
#
|
46
|
+
def render_charset(tags)
|
47
|
+
if charset = meta_tags.extract(:charset)
|
48
|
+
tags << Tag.new(:meta, charset: charset) if charset.present?
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Renders title tag.
|
53
|
+
#
|
54
|
+
# @param [Array<Tag>] tags a buffer object to store tag in.
|
55
|
+
#
|
56
|
+
def render_title(tags)
|
57
|
+
title = meta_tags.extract_full_title
|
58
|
+
normalized_meta_tags[:title] = title
|
59
|
+
tags << ContentTag.new(:title, content: title) if title.present?
|
60
|
+
end
|
61
|
+
|
62
|
+
# Renders icon(s) tag.
|
63
|
+
#
|
64
|
+
# @param [Array<Tag>] tags a buffer object to store tag in.
|
65
|
+
#
|
66
|
+
def render_icon(tags)
|
67
|
+
if icon = meta_tags.extract(:icon)
|
68
|
+
if String === icon
|
69
|
+
tags << Tag.new(:link, rel: 'icon', href: icon, type: 'image/x-icon')
|
70
|
+
else
|
71
|
+
icon = [icon] if Hash === icon
|
72
|
+
icon.each do |icon_params|
|
73
|
+
icon_params = { rel: 'icon', type: 'image/x-icon' }.with_indifferent_access.merge(icon_params)
|
74
|
+
tags << Tag.new(:link, icon_params)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Renders meta tag with normalization (should have a corresponding normalize_
|
81
|
+
# method in TextNormalizer).
|
82
|
+
#
|
83
|
+
# @param [Array<Tag>] tags a buffer object to store tag in.
|
84
|
+
# @see TextNormalizer
|
85
|
+
#
|
86
|
+
def render_with_normalization(tags, name)
|
87
|
+
value = TextNormalizer.public_send("normalize_#{name}", meta_tags.extract(name))
|
88
|
+
normalized_meta_tags[name] = value
|
89
|
+
tags << Tag.new(:meta, name: name, content: value) if value.present?
|
90
|
+
end
|
91
|
+
|
92
|
+
# Renders noindex and nofollow meta tags.
|
93
|
+
#
|
94
|
+
# @param [Array<Tag>] tags a buffer object to store tag in.
|
95
|
+
#
|
96
|
+
def render_noindex(tags)
|
97
|
+
meta_tags.extract_noindex.each do |name, content|
|
98
|
+
tags << Tag.new(:meta, name: name, content: content) if content.present?
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Renders refresh meta tag.
|
103
|
+
#
|
104
|
+
# @param [Array<Tag>] tags a buffer object to store tag in.
|
105
|
+
#
|
106
|
+
def render_refresh(tags)
|
107
|
+
if refresh = meta_tags.extract(:refresh)
|
108
|
+
tags << Tag.new(:meta, 'http-equiv' => 'refresh', content: refresh.to_s) if refresh.present?
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Renders alternate link tags.
|
113
|
+
#
|
114
|
+
# @param [Array<Tag>] tags a buffer object to store tag in.
|
115
|
+
#
|
116
|
+
def render_alternate(tags)
|
117
|
+
if alternate = meta_tags.extract(:alternate)
|
118
|
+
if Hash === alternate
|
119
|
+
alternate.each do |hreflang, href|
|
120
|
+
tags << Tag.new(:link, rel: 'alternate', href: href, hreflang: hreflang) if href.present?
|
121
|
+
end
|
122
|
+
elsif Array === alternate
|
123
|
+
alternate.each do |link_params|
|
124
|
+
tags << Tag.new(:link, { rel: 'alternate' }.with_indifferent_access.merge(link_params))
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Renders open_search link tag.
|
131
|
+
#
|
132
|
+
# @param [Array<Tag>] tags a buffer object to store tag in.
|
133
|
+
#
|
134
|
+
def render_open_search(tags)
|
135
|
+
if open_search = meta_tags.extract(:open_search)
|
136
|
+
href = open_search[:href]
|
137
|
+
title = open_search[:title]
|
138
|
+
if href.present?
|
139
|
+
type = "application/opensearchdescription+xml"
|
140
|
+
tags << Tag.new(:link, rel: 'search', type: type, href: href, title: title)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# Renders links.
|
146
|
+
#
|
147
|
+
# @param [Array<Tag>] tags a buffer object to store tag in.
|
148
|
+
#
|
149
|
+
def render_links(tags)
|
150
|
+
[ :canonical, :prev, :next, :author, :publisher ].each do |tag_name|
|
151
|
+
href = meta_tags.extract(tag_name)
|
152
|
+
if href.present?
|
153
|
+
@normalized_meta_tags[tag_name] = href
|
154
|
+
tags << Tag.new(:link, rel: tag_name, href: href)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# Renders complex hash objects.
|
160
|
+
#
|
161
|
+
# @param [Array<Tag>] tags a buffer object to store tag in.
|
162
|
+
#
|
163
|
+
def render_hashes(tags, options = {})
|
164
|
+
meta_tags.meta_tags.each do |property, data|
|
165
|
+
if data.is_a?(Hash)
|
166
|
+
process_hash(tags, property, data, options)
|
167
|
+
meta_tags.extract(property)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# Renders a complex hash object by key.
|
173
|
+
#
|
174
|
+
# @param [Array<Tag>] tags a buffer object to store tag in.
|
175
|
+
#
|
176
|
+
def render_hash(tags, key, options = {})
|
177
|
+
data = meta_tags.meta_tags[key]
|
178
|
+
if data.is_a?(Hash)
|
179
|
+
process_hash(tags, key, data, options)
|
180
|
+
meta_tags.extract(key)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# Renders custom meta tags.
|
185
|
+
#
|
186
|
+
# @param [Array<Tag>] tags a buffer object to store tag in.
|
187
|
+
#
|
188
|
+
def render_custom(tags)
|
189
|
+
meta_tags.meta_tags.each do |name, data|
|
190
|
+
Array(data).each do |val|
|
191
|
+
tags << Tag.new(:meta, name: name, content: val)
|
192
|
+
end
|
193
|
+
meta_tags.extract(name)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
# Recursive method to process all the hashes and arrays on meta tags
|
198
|
+
#
|
199
|
+
# @param [Array<Tag>] tags a buffer object to store tag in.
|
200
|
+
# @param [String, Symbol] property a Hash or a String to render as meta tag.
|
201
|
+
# @param [Hash, Array, String, Symbol] content text content or a symbol reference to
|
202
|
+
# top-level meta tag.
|
203
|
+
#
|
204
|
+
def process_tree(tags, property, content, options = {})
|
205
|
+
method = case content
|
206
|
+
when Hash
|
207
|
+
:process_hash
|
208
|
+
when Array
|
209
|
+
:process_array
|
210
|
+
else
|
211
|
+
:render_tag
|
212
|
+
end
|
213
|
+
send(method, tags, property, content, options)
|
214
|
+
end
|
215
|
+
|
216
|
+
# Recursive method to process a hash with meta tags
|
217
|
+
#
|
218
|
+
# @param [Array<Tag>] tags a buffer object to store tag in.
|
219
|
+
# @param [String, Symbol] property a Hash or a String to render as meta tag.
|
220
|
+
# @param [Hash] content nested meta tag attributes.
|
221
|
+
#
|
222
|
+
def process_hash(tags, property, content, options = {})
|
223
|
+
content.each do |key, value|
|
224
|
+
key = key.to_s == '_' ? property : "#{property}:#{key}"
|
225
|
+
value = normalized_meta_tags[value] if value.is_a?(Symbol)
|
226
|
+
process_tree(tags, key, value, options)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
# Recursive method to process a hash with meta tags
|
231
|
+
#
|
232
|
+
# @param [Array<Tag>] tags a buffer object to store tag in.
|
233
|
+
# @param [String, Symbol] property a Hash or a String to render as meta tag.
|
234
|
+
# @param [Array] content array of nested meta tag attributes or values.
|
235
|
+
#
|
236
|
+
def process_array(tags, property, content, options = {})
|
237
|
+
content.each { |v| process_tree(tags, property, v, options) }
|
238
|
+
end
|
239
|
+
|
240
|
+
# Recursive method to process a hash with meta tags
|
241
|
+
#
|
242
|
+
# @param [Array<Tag>] tags a buffer object to store tag in.
|
243
|
+
# @param [String, Symbol] name a Hash or a String to render as meta tag.
|
244
|
+
# @param [String, Symbol] value text content or a symbol reference to
|
245
|
+
# top-level meta tag.
|
246
|
+
#
|
247
|
+
def render_tag(tags, name, value, options = {})
|
248
|
+
name_key = options.fetch(:name_key, :name)
|
249
|
+
value_key = options.fetch(:value_key, :content)
|
250
|
+
tags << Tag.new(:meta, name_key => name.to_s, value_key => value) unless value.blank?
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|