social_linker 0.4.0.2 → 0.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
- data/README.md +17 -5
- data/app/helpers/view_helpers.rb +37 -5
- data/lib/social_linker.rb +1 -0
- data/lib/social_linker/engine.rb +1 -0
- data/lib/social_linker/subject.rb +97 -47
- data/lib/social_linker/version.rb +2 -1
- 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: c0dbc4dbe4ad685bd7760c48fe3dac052a188032
|
4
|
+
data.tar.gz: f16384779b4de79aa9967b7725eb4cc7513a4f99
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dee63ce241837647b68683a93f3bd285163b8d0d5511b03c6a794aa6689f7a81b1eef3e10c28c9468a179107fa956a578d88e48b3afb354376bf1a4f57c8dc5a
|
7
|
+
data.tar.gz: 4e0d002887b6b7aba2959883a31ae2bedba65483c3f099657a59fd486907bf2190143c6ed1d5995270506d7c873ab717950cbc4d5b5444461b7430733761a123
|
data/README.md
CHANGED
@@ -56,7 +56,7 @@ Which will deliver you the following url:
|
|
56
56
|
The supported options are:
|
57
57
|
|
58
58
|
* url
|
59
|
-
* media (media url, e.g. an image (
|
59
|
+
* media (media url, e.g. an image (shared only for Pinterest, but also used in OpenGraph headers & Twitter Cards))
|
60
60
|
* summary
|
61
61
|
* description
|
62
62
|
* title
|
@@ -76,8 +76,8 @@ For example:
|
|
76
76
|
@subject = SocialLinker::Subject.new(
|
77
77
|
title: "title",
|
78
78
|
url: "https://murb.nl/blog",
|
79
|
-
|
80
|
-
|
79
|
+
media: "https://murb.nl/image.jpg",
|
80
|
+
media_dimensions: [640, 480],
|
81
81
|
summary: "short summary",
|
82
82
|
tags: ["key1", "key2", "key3"],
|
83
83
|
)
|
@@ -97,12 +97,24 @@ ApplicationController. Later on you can merge details into this subject:
|
|
97
97
|
@subject.merge!({
|
98
98
|
title: "title",
|
99
99
|
url: "https://murb.nl/blog",
|
100
|
-
|
101
|
-
|
100
|
+
media: "https://murb.nl/image.jpg",
|
101
|
+
media_dimensions: [640, 480],
|
102
102
|
summary: "short summary",
|
103
103
|
tags: ["key1", "key2", "key3"]
|
104
104
|
})
|
105
105
|
|
106
|
+
*Hint*, the media_dimensions are 'compatible' with the output of the Dimensions-gem:
|
107
|
+
|
108
|
+
@subject.merge!({
|
109
|
+
title: @article.title,
|
110
|
+
url: article_url(@article),
|
111
|
+
media: @article.image.url(:inline),
|
112
|
+
media_dimensions: Dimensions.dimensions(@article.image.path(:inline)),
|
113
|
+
summary: @article.description,
|
114
|
+
tags: @article.tag_list.to_a
|
115
|
+
})
|
116
|
+
|
117
|
+
|
106
118
|
### Creating share links
|
107
119
|
|
108
120
|
|
data/app/helpers/view_helpers.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ViewHelpers
|
2
3
|
# renders a metatag
|
3
4
|
# param [String, Symbol] name (or property) (defaults to name, values starting with 'og:' (opengraph) will be using the property attribute)
|
4
5
|
# param [String, Symbol] content (the value for the name or the property)
|
5
6
|
# @returns [String, nil] nil is returned when the content is empty
|
6
7
|
def meta_tag(name, content)
|
7
|
-
|
8
|
-
name = erb_sanitized(name)
|
8
|
+
key_value_pairs = {}
|
9
9
|
name_or_property_attribute = if (name.start_with?("og:") or name.start_with?("fb:"))
|
10
10
|
"property"
|
11
11
|
elsif ['Content-Language'].include? name
|
@@ -13,7 +13,27 @@ module ViewHelpers
|
|
13
13
|
else
|
14
14
|
"name"
|
15
15
|
end
|
16
|
-
|
16
|
+
key_value_pairs[name_or_property_attribute] = name
|
17
|
+
key_value_pairs[:content] = content
|
18
|
+
tag_if(:meta, key_value_pairs, :content)
|
19
|
+
end
|
20
|
+
|
21
|
+
# renders a tag conditionally (if value is said)
|
22
|
+
# param [String, Symbol] tagname of the tag
|
23
|
+
# param [Hash] key value pairs (the attributes and their corresponding values
|
24
|
+
# param [String, Symbol] if_key is the key to be checked for containing a value, otherwise nil is returned, defaults to :content
|
25
|
+
# @returns [String, nil] nil is returned when the if_key is empty
|
26
|
+
def tag_if(tagname, key_value_pairs, if_key=:content)
|
27
|
+
tag = tagname.to_sym
|
28
|
+
critical_value = key_value_pairs[if_key]
|
29
|
+
if critical_value and critical_value.to_s.strip != ""
|
30
|
+
attribs = key_value_pairs.collect do |k,v|
|
31
|
+
key = erb_sanitized(k)
|
32
|
+
value = erb_sanitized(v)
|
33
|
+
rv = "#{key}=\"#{value}\""
|
34
|
+
end.join(" ")
|
35
|
+
"<#{tag} #{attribs} />"
|
36
|
+
end
|
17
37
|
end
|
18
38
|
|
19
39
|
def erb_sanitized(value)
|
@@ -40,8 +60,15 @@ module ViewHelpers
|
|
40
60
|
|
41
61
|
header_html = []
|
42
62
|
|
63
|
+
# <link href="https://plus.google.com/+YourPage" rel="publisher">
|
64
|
+
# <meta itemprop="name" content="Content Title">
|
65
|
+
# <meta itemprop="description" content="Content description less than 200 characters">
|
66
|
+
# <meta itemprop="image" content="http://example.com/image.jpg">
|
67
|
+
# =
|
68
|
+
|
43
69
|
header_html << meta_tag("twitter:site", options[:twitter_username])
|
44
70
|
header_html << meta_tag("twitter:creator", options[:twitter_username])
|
71
|
+
header_html << tag_if(:link, {href: "https://plus.google.com/+#{options[:google_plus_name]}", rel: "publisher"}, :href) if options[:google_plus_name]
|
45
72
|
header_html << meta_tag("twitter:domain", domain)
|
46
73
|
header_html << meta_tag("Content-Language", language)
|
47
74
|
header_html << meta_tag("dc.language", language)
|
@@ -61,12 +88,15 @@ module ViewHelpers
|
|
61
88
|
|
62
89
|
header_html << meta_tag("twitter:description", subject.summary(true))
|
63
90
|
header_html << meta_tag("og:description", subject.summary(false))
|
64
|
-
|
91
|
+
header_html << tag_if(:meta, {itemprop: :description, content: subject.summary(false)})
|
65
92
|
|
66
93
|
if subject.media
|
67
94
|
header_html << meta_tag("twitter:image:src", subject.media)
|
68
95
|
header_html << meta_tag("og:image", subject.media)
|
69
|
-
header_html << meta_tag("og:image:
|
96
|
+
header_html << meta_tag("og:image:width", subject.media_width)
|
97
|
+
header_html << meta_tag("og:image:height", subject.media_height)
|
98
|
+
header_html << meta_tag("og:image:type", subject.image_type)
|
99
|
+
header_html << tag_if(:meta, {itemprop: :image, content: subject.media})
|
70
100
|
end
|
71
101
|
end
|
72
102
|
|
@@ -77,6 +107,8 @@ module ViewHelpers
|
|
77
107
|
header_html << meta_tag("twitter:title", title)
|
78
108
|
header_html << meta_tag("og:title", title)
|
79
109
|
header_html << meta_tag("og:site_name", site_name)
|
110
|
+
header_html << tag_if(:meta, {itemprop: :name, content: site_title}, :content)
|
111
|
+
|
80
112
|
|
81
113
|
header_html.compact!
|
82
114
|
header_html = header_html.join("\n") if header_html
|
data/lib/social_linker.rb
CHANGED
data/lib/social_linker/engine.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module SocialLinker
|
2
3
|
class Subject
|
3
4
|
|
@@ -77,12 +78,60 @@ module SocialLinker
|
|
77
78
|
@options[:image_url]
|
78
79
|
end
|
79
80
|
|
80
|
-
def
|
81
|
+
def media_dimensions
|
82
|
+
return @media_dimensions if @media_dimensions
|
83
|
+
if media
|
84
|
+
@media_dimensions = @options[:media_dimensions]
|
85
|
+
if @media_dimensions.is_a? Array
|
86
|
+
@media_dimensions = {
|
87
|
+
width: @media_dimensions[0],
|
88
|
+
height: @media_dimensions[1]
|
89
|
+
}
|
90
|
+
end
|
91
|
+
@media_dimensions ||= {
|
92
|
+
width: @options[:media_width],
|
93
|
+
height: @options[:media_height]
|
94
|
+
}
|
95
|
+
else
|
96
|
+
@media_dimensions = {}
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def media_width
|
101
|
+
media_dimensions[:width].to_i if media_dimensions[:width]
|
102
|
+
end
|
103
|
+
|
104
|
+
def media_height
|
105
|
+
media_dimensions[:height].to_i if media_dimensions[:height]
|
106
|
+
end
|
107
|
+
|
108
|
+
def utm_parameters?
|
81
109
|
[nil, true].include?(@options[:utm_parameters]) ? true : false
|
82
110
|
end
|
83
111
|
|
112
|
+
def utm_parameters
|
113
|
+
if utm_parameters?
|
114
|
+
{
|
115
|
+
utm_source: "<%=share_source%>",
|
116
|
+
utm_medium: "share_link",
|
117
|
+
utm_campaign: "social"
|
118
|
+
}
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
84
122
|
def canonical_url
|
85
|
-
@options[:canonical_url]
|
123
|
+
prefix_domain((@options[:canonical_url] || @options[:url]), @options[:domain])
|
124
|
+
end
|
125
|
+
|
126
|
+
def share_url
|
127
|
+
url_to_share = prefix_domain((@options[:share_url] || @options[:url]), @options[:domain])
|
128
|
+
if utm_parameters?
|
129
|
+
utm_url_params = utm_parameters.collect{|k,v| "#{k}=#{v}" unless url_to_share.match(k.to_s)}.compact.join("&")
|
130
|
+
combine_with = url_to_share.match(/\?/) ? "&" : "?"
|
131
|
+
return "#{url_to_share}#{combine_with}#{utm_url_params}"
|
132
|
+
else
|
133
|
+
return url_to_share
|
134
|
+
end
|
86
135
|
end
|
87
136
|
|
88
137
|
# default title accessor
|
@@ -94,7 +143,8 @@ module SocialLinker
|
|
94
143
|
# default summary accessor
|
95
144
|
# @return String with summary
|
96
145
|
def summary(strip=false)
|
97
|
-
|
146
|
+
summ = @options[:summary] || @options[:description]
|
147
|
+
strip ? strip_string(summ, 300) : summ
|
98
148
|
end
|
99
149
|
|
100
150
|
# default media accessor
|
@@ -103,6 +153,23 @@ module SocialLinker
|
|
103
153
|
@options[:media]
|
104
154
|
end
|
105
155
|
|
156
|
+
def filename_derived_image_type
|
157
|
+
if media
|
158
|
+
extension = media.to_s.split(".").last.downcase
|
159
|
+
if extension == "jpg" or extension == "jpeg"
|
160
|
+
"image/jpeg"
|
161
|
+
elsif extension == "png"
|
162
|
+
"image/png"
|
163
|
+
elsif extension == "gif"
|
164
|
+
"image/gif"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def image_type
|
170
|
+
@options[:image_type] || filename_derived_image_type
|
171
|
+
end
|
172
|
+
|
106
173
|
# default tags accessor
|
107
174
|
# @return Array<String> with tags
|
108
175
|
def tags
|
@@ -142,6 +209,7 @@ module SocialLinker
|
|
142
209
|
# * url
|
143
210
|
# * title
|
144
211
|
# * image_url & image_type(image/jpeg, image/png)
|
212
|
+
# * width and height for the images
|
145
213
|
# * description
|
146
214
|
# * facebook_app_id
|
147
215
|
# * twitter_username
|
@@ -180,38 +248,18 @@ module SocialLinker
|
|
180
248
|
# @return SocialLinker::Subject (self)
|
181
249
|
def merge!(options)
|
182
250
|
options = options.options if options.is_a? SocialLinker::Subject
|
251
|
+
options[:render_site_title_postfix] = true if options[:render_site_title_postfix].nil?
|
252
|
+
options[:u] ||= options[:url]
|
253
|
+
options[:media] ||= options[:image_url]
|
254
|
+
options[:title] ||= "#{ strip_string(options[:summary], 120) }"
|
255
|
+
options[:subject] ||= options[:title]
|
256
|
+
options[:via] ||= options[:twitter_username]
|
257
|
+
options[:url] ||= options[:media]
|
258
|
+
options[:text] = "#{options[:title]} #{options[:url]}" unless options[:text] #facebook & whatsapp native
|
259
|
+
options[:domain] = options[:url].split(/\//)[0..2].join("/") if options[:url] and !options[:domain]
|
260
|
+
options.select!{|k,v| !v.nil?}
|
183
261
|
@options.merge!(options)
|
184
|
-
|
185
|
-
@options[:u] = @options[:url] unless @options[:u]
|
186
|
-
@options[:media] = @options[:image_url] unless @options[:media]
|
187
|
-
@options[:description] = @options[:summary] unless @options[:description]
|
188
|
-
@options[:summary] = @options[:description] unless @options[:summary]
|
189
|
-
@options[:title] = "#{ strip_string(@options[:summary], 120) }" unless @options[:title]
|
190
|
-
@options[:description] = @options[:title] unless @options[:description]
|
191
|
-
@options[:subject] = @options[:title] unless @options[:subject]
|
192
|
-
@options[:via] = @options[:twitter_username] unless @options[:via]
|
193
|
-
@options[:url] = @options[:media] unless @options[:url]
|
194
|
-
raise ArgumentError, "#{url} is not a valid url" if @options[:url] and !@options[:url].include?('//')
|
195
|
-
|
196
|
-
@options[:text] = "#{@options[:title]} #{@options[:url]}" unless @options[:text] #facebook & whatsapp native
|
197
|
-
@options[:canonical_url] = @options[:url]
|
198
|
-
@options[:share_url] = @options[:url]
|
199
|
-
@options[:domain] = @options[:url].split(/\//)[0..2].join("/") if @options[:url] and !@options[:domain]
|
200
|
-
|
201
|
-
if @options[:share_url] and utm_parameters
|
202
|
-
unless @options[:share_url].match /utm_source/
|
203
|
-
combine_with = @options[:share_url].match(/\?/) ? "&" : "?"
|
204
|
-
@options[:share_url] = "#{@options[:share_url]}#{combine_with}utm_source=<%=share_source%>"
|
205
|
-
end
|
206
|
-
unless @options[:share_url].match /utm_medium/
|
207
|
-
combine_with = "&"
|
208
|
-
@options[:share_url] = "#{@options[:share_url]}#{combine_with}utm_medium=share_link"
|
209
|
-
end
|
210
|
-
unless @options[:share_url].match /utm_campaign/
|
211
|
-
combine_with = "&"
|
212
|
-
@options[:share_url] = "#{@options[:share_url]}#{combine_with}utm_campaign=social"
|
213
|
-
end
|
214
|
-
end
|
262
|
+
|
215
263
|
if @options[:tags]
|
216
264
|
@options[:tags].compact!
|
217
265
|
@options[:hashtags] = @options[:tags][0..1].collect{|a| camelize_tag_when_needed(a) }.join(",") if @options[:tags] and !@options[:hashtags]
|
@@ -219,8 +267,6 @@ module SocialLinker
|
|
219
267
|
|
220
268
|
# make sure urls are absolute
|
221
269
|
@options[:url] = prefix_domain(@options[:url],@options[:domain])
|
222
|
-
@options[:share_url] = prefix_domain(@options[:share_url],@options[:domain])
|
223
|
-
@options[:canonical_url] = prefix_domain(@options[:canonical_url],@options[:domain])
|
224
270
|
@options[:image_url] = prefix_domain(@options[:image_url],@options[:domain])
|
225
271
|
@options[:media] = prefix_domain(@options[:media],@options[:domain])
|
226
272
|
|
@@ -236,16 +282,20 @@ module SocialLinker
|
|
236
282
|
def body
|
237
283
|
return options[:body] if options[:body]
|
238
284
|
rv = ""
|
239
|
-
rv += "#{
|
240
|
-
rv += "\n#{
|
241
|
-
rv += "\n#{
|
242
|
-
rv += "\n#{@options[:media]}\n" if options[:media] !=
|
285
|
+
rv += "#{summary}\n" if summary
|
286
|
+
rv += "\n#{share_url}\n" if share_url
|
287
|
+
rv += "\n#{description}\n" if summary != description and description
|
288
|
+
rv += "\n#{@options[:media]}\n" if options[:media] != share_url and options[:media]
|
243
289
|
rv += "\n\n#{hashtag_string(@options[:tags])}" if options[:tags]
|
244
290
|
rv.strip!
|
245
291
|
rv = nil if rv == ""
|
246
292
|
return rv
|
247
293
|
end
|
248
294
|
|
295
|
+
def description
|
296
|
+
@options[:description] || @options[:summary]
|
297
|
+
end
|
298
|
+
|
249
299
|
# Turns the first two tags in to tweetable hash tags
|
250
300
|
# Conform recommendation never to have more than 2 tags in a twitter message
|
251
301
|
# @return String with two tags as #tags.
|
@@ -278,13 +328,14 @@ module SocialLinker
|
|
278
328
|
# @param [String] domain of the file
|
279
329
|
# @return String with full url
|
280
330
|
def prefix_domain path, domain
|
281
|
-
return_string = path
|
282
331
|
if path and !path.include?("//")
|
283
|
-
|
284
|
-
|
285
|
-
|
332
|
+
return [
|
333
|
+
domain.gsub(/\/$/,''),
|
334
|
+
path.gsub(/^\//,'')
|
335
|
+
].join("/")
|
336
|
+
else
|
337
|
+
return path
|
286
338
|
end
|
287
|
-
return_string
|
288
339
|
end
|
289
340
|
|
290
341
|
# Returns the given options, extended with the (derived) defaults
|
@@ -331,5 +382,4 @@ module SocialLinker
|
|
331
382
|
end
|
332
383
|
end
|
333
384
|
end
|
334
|
-
end
|
335
|
-
|
385
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: social_linker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- murb
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-10-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|