jekyll-webmention_io 2.0.1
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 +7 -0
- data/assets/webmention_io.js +549 -0
- data/lib/jekyll/commands/webmention.rb +48 -0
- data/lib/jekyll/generators/gather_webmentions.rb +239 -0
- data/lib/jekyll/generators/queue_webmentions.rb +50 -0
- data/lib/jekyll/tags/_.rb +132 -0
- data/lib/jekyll/tags/count.rb +26 -0
- data/lib/jekyll/tags/likes.rb +27 -0
- data/lib/jekyll/tags/links.rb +27 -0
- data/lib/jekyll/tags/posts.rb +27 -0
- data/lib/jekyll/tags/replies.rb +27 -0
- data/lib/jekyll/tags/reposts.rb +27 -0
- data/lib/jekyll/tags/webmentions.rb +23 -0
- data/lib/jekyll/webmention_io/version.rb +3 -0
- data/lib/jekyll/webmention_io.rb +207 -0
- data/lib/jekyll-webmention_io.rb +1 -0
- data/templates/count.html +1 -0
- data/templates/likes.html +17 -0
- data/templates/links.html +24 -0
- data/templates/posts.html +18 -0
- data/templates/replies.html +29 -0
- data/templates/reposts.html +17 -0
- data/templates/webmentions.html +48 -0
- metadata +152 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
# (c) Aaron Gustafson
|
2
|
+
# https://github.com/aarongustafson/jekyll-webmention_io
|
3
|
+
# Licence : MIT
|
4
|
+
#
|
5
|
+
# this liquid plugin insert a webmentions into your Octopress or Jekill blog
|
6
|
+
# using http://webmention.io/ and the following syntax:
|
7
|
+
#
|
8
|
+
# {% webmention_count post.url [ likes | links | posts | replies | reposts ]* %}
|
9
|
+
#
|
10
|
+
module Jekyll
|
11
|
+
class WebmentionCountTag < WebmentionTag
|
12
|
+
|
13
|
+
def initialize(tagName, text, tokens)
|
14
|
+
super
|
15
|
+
@text = text
|
16
|
+
set_template 'count'
|
17
|
+
end
|
18
|
+
|
19
|
+
def set_data(data)
|
20
|
+
@data = { 'count' => data.length }
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
Liquid::Template.register_tag('webmention_count', Jekyll::WebmentionCountTag)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# (c) Aaron Gustafson
|
2
|
+
# https://github.com/aarongustafson/jekyll-webmention_io
|
3
|
+
# Licence : MIT
|
4
|
+
#
|
5
|
+
# this liquid plugin insert a webmentions into your Octopress or Jekill blog
|
6
|
+
# using http://webmention.io/ and the following syntax:
|
7
|
+
#
|
8
|
+
# {% webmention_likes post.url %}
|
9
|
+
#
|
10
|
+
module Jekyll
|
11
|
+
class WebmentionLikesTag < WebmentionTag
|
12
|
+
|
13
|
+
def initialize(tagName, text, tokens)
|
14
|
+
super
|
15
|
+
@text = text
|
16
|
+
set_template 'likes'
|
17
|
+
end
|
18
|
+
|
19
|
+
def set_data(data)
|
20
|
+
webmentions = extract_type 'likes', data
|
21
|
+
@data = { 'webmentions' => webmentions.values }
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
Liquid::Template.register_tag('webmention_likes', Jekyll::WebmentionLikesTag)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# (c) Aaron Gustafson
|
2
|
+
# https://github.com/aarongustafson/jekyll-webmention_io
|
3
|
+
# Licence : MIT
|
4
|
+
#
|
5
|
+
# this liquid plugin insert a webmentions into your Octopress or Jekill blog
|
6
|
+
# using http://webmention.io/ and the following syntax:
|
7
|
+
#
|
8
|
+
# {% webmention_links post.url %}
|
9
|
+
#
|
10
|
+
module Jekyll
|
11
|
+
class WebmentionLinksTag < WebmentionTag
|
12
|
+
|
13
|
+
def initialize(tagName, text, tokens)
|
14
|
+
super
|
15
|
+
@text = text
|
16
|
+
set_template 'links'
|
17
|
+
end
|
18
|
+
|
19
|
+
def set_data(data)
|
20
|
+
webmentions = extract_type 'links', data
|
21
|
+
@data = { 'webmentions' => webmentions.values }
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
Liquid::Template.register_tag('webmention_links', Jekyll::WebmentionLinksTag)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# (c) Aaron Gustafson
|
2
|
+
# https://github.com/aarongustafson/jekyll-webmention_io
|
3
|
+
# Licence : MIT
|
4
|
+
#
|
5
|
+
# this liquid plugin insert a webmentions into your Octopress or Jekill blog
|
6
|
+
# using http://webmention.io/ and the following syntax:
|
7
|
+
#
|
8
|
+
# {% webmention_posts post.url %}
|
9
|
+
#
|
10
|
+
module Jekyll
|
11
|
+
class WebmentionRepostsTag < WebmentionTag
|
12
|
+
|
13
|
+
def initialize(tagName, text, tokens)
|
14
|
+
super
|
15
|
+
@text = text
|
16
|
+
set_template 'posts'
|
17
|
+
end
|
18
|
+
|
19
|
+
def set_data(data)
|
20
|
+
webmentions = extract_type 'posts', data
|
21
|
+
@data = { 'webmentions' => webmentions.values }
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
Liquid::Template.register_tag('webmention_posts', Jekyll::WebmentionRepostsTag)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# (c) Aaron Gustafson
|
2
|
+
# https://github.com/aarongustafson/jekyll-webmention_io
|
3
|
+
# Licence : MIT
|
4
|
+
#
|
5
|
+
# this liquid plugin insert a webmentions into your Octopress or Jekill blog
|
6
|
+
# using http://webmention.io/ and the following syntax:
|
7
|
+
#
|
8
|
+
# {% webmention_replies post.url %}
|
9
|
+
#
|
10
|
+
module Jekyll
|
11
|
+
class WebmentionRepliesTag < WebmentionTag
|
12
|
+
|
13
|
+
def initialize(tagName, text, tokens)
|
14
|
+
super
|
15
|
+
@text = text
|
16
|
+
set_template 'replies'
|
17
|
+
end
|
18
|
+
|
19
|
+
def set_data(data)
|
20
|
+
webmentions = extract_type 'replies', data
|
21
|
+
@data = { 'webmentions' => webmentions.values }
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
Liquid::Template.register_tag('webmention_replies', Jekyll::WebmentionRepliesTag)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# (c) Aaron Gustafson
|
2
|
+
# https://github.com/aarongustafson/jekyll-webmention_io
|
3
|
+
# Licence : MIT
|
4
|
+
#
|
5
|
+
# this liquid plugin insert a webmentions into your Octopress or Jekill blog
|
6
|
+
# using http://webmention.io/ and the following syntax:
|
7
|
+
#
|
8
|
+
# {% webmention_reposts post.url %}
|
9
|
+
#
|
10
|
+
module Jekyll
|
11
|
+
class WebmentionRepostsTag < WebmentionTag
|
12
|
+
|
13
|
+
def initialize(tagName, text, tokens)
|
14
|
+
super
|
15
|
+
@text = text
|
16
|
+
set_template 'reposts'
|
17
|
+
end
|
18
|
+
|
19
|
+
def set_data(data)
|
20
|
+
webmentions = extract_type 'reposts', data
|
21
|
+
@data = { 'webmentions' => webmentions.values }
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
Liquid::Template.register_tag('webmention_reposts', Jekyll::WebmentionRepostsTag)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# (c) Aaron Gustafson
|
2
|
+
# https://github.com/aarongustafson/jekyll-webmention_io
|
3
|
+
# Licence : MIT
|
4
|
+
#
|
5
|
+
# this liquid plugin insert a webmentions into your Octopress or Jekill blog
|
6
|
+
# using http://webmention.io/ and the following syntax:
|
7
|
+
#
|
8
|
+
# {% webmentions post.url [ likes | links | posts | replies | reposts ]* %}
|
9
|
+
#
|
10
|
+
module Jekyll
|
11
|
+
class WebmentionsTag < WebmentionTag
|
12
|
+
|
13
|
+
def initialize(tagName, text, tokens)
|
14
|
+
super
|
15
|
+
@text = text
|
16
|
+
set_template 'webmentions'
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
Liquid::Template.register_tag('webmentions', Jekyll::WebmentionsTag)
|
@@ -0,0 +1,207 @@
|
|
1
|
+
# (c) Aaron Gustafson
|
2
|
+
# https://github.com/aarongustafson/jekyll-webmention_io
|
3
|
+
# Licence : MIT
|
4
|
+
#
|
5
|
+
# this liquid plugin insert a webmentions into your Octopress or Jekill blog
|
6
|
+
# using http://webmention.io/ and the following syntax:
|
7
|
+
#
|
8
|
+
require 'jekyll/webmention_io/version'
|
9
|
+
|
10
|
+
require 'json'
|
11
|
+
require 'net/http'
|
12
|
+
require 'uri'
|
13
|
+
require 'openssl'
|
14
|
+
require 'string_inflection'
|
15
|
+
|
16
|
+
module Jekyll
|
17
|
+
class WebmentionIO
|
18
|
+
|
19
|
+
@logger_prefix = '[jekyll-webmention_io]'
|
20
|
+
|
21
|
+
# @jekyll_config = Jekyll.configuration({ 'quiet' => true })
|
22
|
+
@jekyll_config = Jekyll.configuration({})
|
23
|
+
@config = @jekyll_config['webmentions']
|
24
|
+
|
25
|
+
@api_url = 'https://webmention.io/api'
|
26
|
+
@api_endpoint = @api_url
|
27
|
+
@api_suffix = ''
|
28
|
+
|
29
|
+
# Set up the cache folder & files
|
30
|
+
cache_folder = @config['cache_folder'] || '.cache'
|
31
|
+
Dir.mkdir(cache_folder) unless File.exists?(cache_folder)
|
32
|
+
file_prefix = ''
|
33
|
+
if ! cache_folder.include? 'webmention'
|
34
|
+
file_prefix = 'webmention_io_'
|
35
|
+
end
|
36
|
+
@cache_files = {
|
37
|
+
'incoming' => "#{cache_folder}/#{file_prefix}received.yml",
|
38
|
+
'outgoing' => "#{cache_folder}/#{file_prefix}queued.yml",
|
39
|
+
'sent' => "#{cache_folder}/#{file_prefix}sent.yml",
|
40
|
+
'bad_uris' => "#{cache_folder}/#{file_prefix}bad_uris.yml"
|
41
|
+
}
|
42
|
+
@cache_files.each do |key, file|
|
43
|
+
if ! File.exists?(file)
|
44
|
+
File.open(file, 'w') { |f| YAML.dump({}, f) }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
@types = ['likes','links','posts','replies','reposts']
|
49
|
+
|
50
|
+
# Attributes
|
51
|
+
def self.config
|
52
|
+
@config
|
53
|
+
end
|
54
|
+
def self.jekyll_config
|
55
|
+
@jekyll_config
|
56
|
+
end
|
57
|
+
def self.cache_files
|
58
|
+
@cache_files
|
59
|
+
end
|
60
|
+
def self.types
|
61
|
+
@types
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.get_cache_file_path( key )
|
65
|
+
path = false
|
66
|
+
if @cache_files.has_key? key
|
67
|
+
path = @cache_files[key]
|
68
|
+
end
|
69
|
+
return path
|
70
|
+
end
|
71
|
+
|
72
|
+
# API helpers
|
73
|
+
#def uri_params_for(api_params)
|
74
|
+
# api_params.keys.sort.map do |k|
|
75
|
+
# "#{CGI::escape(k)}=#{CGI::escape(api_params[k])}"
|
76
|
+
# end.join('&')
|
77
|
+
#end
|
78
|
+
|
79
|
+
def self.set_api_endpoint(path)
|
80
|
+
@api_endpoint = "#{@api_url}/#{path}"
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.set_api_suffix(suffix)
|
84
|
+
@api_suffix = suffix
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.get_response(api_params)
|
88
|
+
api_params << @api_suffix
|
89
|
+
source = get_uri_source(@api_endpoint + "?#{api_params}")
|
90
|
+
if source
|
91
|
+
JSON.parse(source)
|
92
|
+
else
|
93
|
+
""
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.get_webmention_endpoint( uri )
|
98
|
+
log 'info', "Looking for webmention endpoint at #{uri}"
|
99
|
+
return `curl -s --location "#{uri}" | grep 'rel="webmention"'`
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.webmention( source, target, endpoint )
|
103
|
+
log 'info', "Sending webmention of #{source} to #{endpoint}"
|
104
|
+
return `curl -s -i -d \"source=#{source}&target=#{target}\" -o /dev/null #{endpoint}`
|
105
|
+
end
|
106
|
+
|
107
|
+
# Utilities
|
108
|
+
# def key_exists(hash, test_key)
|
109
|
+
# if hash.is_a? Hash
|
110
|
+
# hash.each do |key, value|
|
111
|
+
# if test_key == key
|
112
|
+
# return true
|
113
|
+
# # nest
|
114
|
+
# elsif value.is_a? Hash
|
115
|
+
# if key_exists value, test_key
|
116
|
+
# return true
|
117
|
+
# end
|
118
|
+
# end
|
119
|
+
# end
|
120
|
+
# end
|
121
|
+
# return false
|
122
|
+
# end
|
123
|
+
|
124
|
+
# Connections
|
125
|
+
def self.is_uri_ok( uri )
|
126
|
+
uri = URI.parse(URI.encode(uri))
|
127
|
+
now = Time.now.to_s
|
128
|
+
bad_uris = open(@cache_files['bad_uris']) { |f| YAML.load(f) }
|
129
|
+
if bad_uris.key? uri.host
|
130
|
+
last_checked = DateTime.parse( bad_uris[uri.host] )
|
131
|
+
cache_bad_uris_for = @config['cache_bad_uris_for'] || 1 # in days
|
132
|
+
recheck_at = last_checked.next_day(cache_bad_uris_for).to_s
|
133
|
+
if recheck_at > now
|
134
|
+
return false
|
135
|
+
end
|
136
|
+
end
|
137
|
+
return true
|
138
|
+
end
|
139
|
+
|
140
|
+
# Cache bad URLs for a bit
|
141
|
+
def self.uri_is_not_ok( uri )
|
142
|
+
cache_file = @cache_files['bad_uris']
|
143
|
+
bad_uris = open(cache_file) { |f| YAML.load(f) }
|
144
|
+
bad_uris[uri.host] = Time.now.to_s
|
145
|
+
File.open(cache_file, 'w') { |f| YAML.dump(bad_uris, f) }
|
146
|
+
end
|
147
|
+
|
148
|
+
def self.get_uri_source(uri, redirect_limit = 10, original_uri = false)
|
149
|
+
original_uri = original_uri || uri
|
150
|
+
if ! is_uri_ok(uri)
|
151
|
+
return false
|
152
|
+
end
|
153
|
+
if redirect_limit > 0
|
154
|
+
uri = URI.parse(URI.encode(uri))
|
155
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
156
|
+
http.read_timeout = 10
|
157
|
+
if uri.scheme == 'https'
|
158
|
+
http.use_ssl = true
|
159
|
+
http.ssl_version = :TLSv1
|
160
|
+
http.ciphers = "ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:-LOW"
|
161
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
162
|
+
end
|
163
|
+
begin
|
164
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
165
|
+
response = http.request(request)
|
166
|
+
rescue SocketError, Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, Errno::ECONNREFUSED, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError, OpenSSL::SSL::SSLError => e
|
167
|
+
log 'warn', "Got an error checking #{original_uri}: #{e}"
|
168
|
+
uri_is_not_ok(uri)
|
169
|
+
return false
|
170
|
+
end
|
171
|
+
case response
|
172
|
+
when Net::HTTPSuccess then
|
173
|
+
return response.body.force_encoding('UTF-8')
|
174
|
+
when Net::HTTPRedirection then
|
175
|
+
redirect_to = URI.parse(URI.encode(response['location']))
|
176
|
+
redirect_to = redirect_to.relative? ? "#{uri.scheme}://#{uri.host}" + redirect_to.to_s : redirect_to.to_s
|
177
|
+
return get_uri_source(redirect_to, redirect_limit - 1, original_uri)
|
178
|
+
else
|
179
|
+
uri_is_not_ok(uri)
|
180
|
+
return false
|
181
|
+
end
|
182
|
+
else
|
183
|
+
if original_uri
|
184
|
+
log 'warn', "too many redirects for #{original_uri}"
|
185
|
+
end
|
186
|
+
uri_is_not_ok(uri)
|
187
|
+
return false
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def self.log( type, message )
|
192
|
+
Jekyll.logger.method(type).call( "#{@logger_prefix} #{message}" )
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
# Load all the bits
|
199
|
+
Dir[File.dirname(__FILE__) + '/commands/*.rb'].each do |file|
|
200
|
+
require file
|
201
|
+
end
|
202
|
+
Dir[File.dirname(__FILE__) + '/generators/*.rb'].each do |file|
|
203
|
+
require file
|
204
|
+
end
|
205
|
+
Dir[File.dirname(__FILE__) + '/tags/*.rb'].each do |file|
|
206
|
+
require file
|
207
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'jekyll/webmention_io'
|
@@ -0,0 +1 @@
|
|
1
|
+
<span class="webmention-count">{{ count }}</span>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<div class="webmentions webmentions--likes">
|
2
|
+
{% if webmentions.size > 0 %}
|
3
|
+
<ol class="webmentions__list">
|
4
|
+
{% for webmention in webmentions %}
|
5
|
+
<li id="webmention-{{ webmention.id }}" class="webmentions__item webmentions__item--{{ webmention.type }}">
|
6
|
+
<div class="webmention__author p-author h-card">
|
7
|
+
<a class="u-url" href="{{ webmention.author.url }}">
|
8
|
+
<img class="webmention__author__photo u-photo" src="{{ webmention.author.photo }}" alt="" title="{{ webmention.author.name }}">
|
9
|
+
</a>
|
10
|
+
</div>
|
11
|
+
</li>
|
12
|
+
{% endfor %}
|
13
|
+
</ol>
|
14
|
+
{% else %}
|
15
|
+
<p class="webmentions__not-found">No likes were found.</p>
|
16
|
+
{% endif %}
|
17
|
+
</div>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<div class="webmentions webmentions--links">
|
2
|
+
{% if webmentions.size > 0 %}
|
3
|
+
<ol class="webmentions__list">
|
4
|
+
{% for webmention in webmentions %}
|
5
|
+
<li id="webmention-{{ webmention.id }}" class="webmentions__item webmentions__item--{{ webmention.type }}">
|
6
|
+
{{ webmention.content }}
|
7
|
+
<div class="webmention__meta">
|
8
|
+
{% if webmention.author %}
|
9
|
+
<a class="u-url" href="{{ webmention.author.url }}">{{ webmention.author.name }}</a>
|
10
|
+
{% endif %}
|
11
|
+
{% if webmention.pubdate and webmention.url %}on{% endif %}
|
12
|
+
{% if webmention.pubdate %}
|
13
|
+
<a class="webmention__source u-url" href="{{ webmention.url }}">
|
14
|
+
<time class="webmention__pubdate dt-published" datetime="{{ webmention.pubdate | date: '%FT%T%:z' }}">{{ webmention.pubdate | date: '%d %B %Y' }}</time>
|
15
|
+
</a>
|
16
|
+
{% endif %}
|
17
|
+
</div>
|
18
|
+
</li>
|
19
|
+
{% endfor %}
|
20
|
+
</ol>
|
21
|
+
{% else %}
|
22
|
+
<p class="webmentions__not-found">No webmentions were found.</p>
|
23
|
+
{% endif %}
|
24
|
+
</div>
|