jekyll-webmention_io 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/jekyll/assets/JekyllWebmentionIO.js +511 -0
- data/lib/jekyll/assets/_utils.js +33 -0
- data/lib/jekyll/assets/liquid.js +134 -0
- data/lib/jekyll/assets/webmention_counters.js +48 -0
- data/lib/jekyll/assets/webmention_loader.js +34 -0
- data/lib/jekyll/assets/webmention_websocket.js +21 -0
- data/lib/jekyll/generators/compile_js.rb +74 -0
- data/lib/jekyll/generators/gather_webmentions.rb +182 -175
- data/lib/jekyll/tags/_.rb +7 -3
- data/lib/jekyll/tags/count.rb +2 -2
- data/lib/jekyll/tags/likes.rb +1 -1
- data/lib/jekyll/tags/links.rb +1 -1
- data/lib/jekyll/tags/posts.rb +1 -1
- data/lib/jekyll/tags/replies.rb +1 -1
- data/lib/jekyll/tags/reposts.rb +1 -1
- data/lib/jekyll/tags/webmentions_head.rb +34 -0
- data/lib/jekyll/tags/webmentions_js.rb +56 -0
- data/lib/jekyll/templates/count.html +2 -1
- data/lib/jekyll/templates/likes.html +15 -15
- data/lib/jekyll/templates/links.html +20 -18
- data/lib/jekyll/templates/posts.html +12 -12
- data/lib/jekyll/templates/replies.html +26 -24
- data/lib/jekyll/templates/reposts.html +15 -15
- data/lib/jekyll/templates/webmentions.html +32 -31
- data/lib/jekyll/webmention_io/version.rb +1 -1
- metadata +25 -3
- data/lib/jekyll/assets/webmention_io.js +0 -549
@@ -12,31 +12,31 @@ module Jekyll
|
|
12
12
|
priority :high
|
13
13
|
|
14
14
|
def generate(site)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
15
|
+
if site.config['webmentions']['pause_lookups'] == true
|
16
|
+
Jekyll::WebmentionIO::log 'info', 'Webmention lookups are currently paused.'
|
17
|
+
return
|
18
|
+
end
|
19
|
+
|
20
|
+
Jekyll::WebmentionIO::log 'info', 'Beginning to gather webmentions of your posts. This may take a while.'
|
21
|
+
|
22
|
+
Jekyll::WebmentionIO::set_api_endpoint('mentions')
|
23
23
|
# add an arbitrarily high perPage to trump pagination
|
24
24
|
Jekyll::WebmentionIO::set_api_suffix('&perPage=9999')
|
25
25
|
|
26
|
-
|
27
|
-
|
26
|
+
cache_file = Jekyll::WebmentionIO::get_cache_file_path 'incoming'
|
27
|
+
if File.exists?(cache_file)
|
28
28
|
@cached_webmentions = open(cache_file) { |f| YAML.load(f) }
|
29
29
|
else
|
30
30
|
@cached_webmentions = {}
|
31
31
|
end
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
32
|
+
|
33
|
+
if Jekyll::VERSION >= "3.0.0"
|
34
|
+
posts = site.posts.docs
|
35
|
+
else
|
36
|
+
posts = site.posts
|
37
|
+
end
|
38
|
+
|
39
|
+
# post Jekyll commit 0c0aea3
|
40
40
|
# https://github.com/jekyll/jekyll/commit/0c0aea3ad7d2605325d420a23d21729c5cf7cf88
|
41
41
|
if defined? site.find_converter_instance
|
42
42
|
@converter = site.find_converter_instance(::Jekyll::Converters::Markdown)
|
@@ -44,201 +44,208 @@ module Jekyll
|
|
44
44
|
else
|
45
45
|
@converter = site.getConverterImpl(::Jekyll::Converters::Markdown)
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
posts.each do |post|
|
49
|
-
|
50
|
-
|
49
|
+
# Gather the URLs
|
50
|
+
targets = get_webmention_target_urls(site, post)
|
51
|
+
|
52
|
+
# execute the API
|
53
|
+
api_params = targets.collect { |v| "target[]=#{v}" }.join('&')
|
54
|
+
response = Jekyll::WebmentionIO::get_response(api_params)
|
55
|
+
# @webmention_io.log 'info', response.inspect
|
51
56
|
|
52
|
-
|
53
|
-
api_params = targets.collect { |v| "target[]=#{v}" }.join('&')
|
54
|
-
response = Jekyll::WebmentionIO::get_response(api_params)
|
55
|
-
# @webmention_io.log 'info', response.inspect
|
56
|
-
|
57
|
-
process_webmentions( post.url, response )
|
57
|
+
process_webmentions( post.url, response )
|
58
58
|
end # posts loop
|
59
59
|
|
60
60
|
File.open(cache_file, 'w') { |f| YAML.dump(@cached_webmentions, f) }
|
61
|
-
|
62
|
-
|
63
|
-
|
61
|
+
|
62
|
+
Jekyll::WebmentionIO::log 'info', 'Webmentions have been gathered and cached.'
|
63
|
+
end # generate
|
64
64
|
|
65
65
|
def get_webmention_target_urls(site, post)
|
66
66
|
targets = []
|
67
67
|
uri = "#{site.config['url']}#{post.url}"
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
68
|
+
targets.push( uri )
|
69
|
+
|
70
|
+
# Redirection?
|
71
|
+
redirected = false
|
72
|
+
if post.data.has_key? 'redirect_from'
|
73
|
+
if post.data['redirect_from'].is_a? String
|
74
|
+
redirected = uri.sub post.url, post.data['redirect_from']
|
75
|
+
targets.push( redirected )
|
76
|
+
elsif post.data['redirect_from'].is_a? Array
|
77
|
+
post.data['redirect_from'].each do |redirect|
|
78
|
+
redirected = uri.sub post.url, redirect
|
79
|
+
targets.push( redirected )
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Domain changed?
|
85
|
+
if Jekyll::WebmentionIO::config.has_key? 'legacy_domains'
|
86
|
+
# Jekyll::WebmentionIO::log 'info', 'adding legacy URIs'
|
87
|
+
Jekyll::WebmentionIO::config['legacy_domains'].each do |domain|
|
88
|
+
legacy = uri.sub site.config['url'], domain
|
89
|
+
# Jekyll::WebmentionIO::log 'info', "adding URI #{legacy}"
|
90
|
+
targets.push(legacy)
|
91
|
+
end
|
92
|
+
end
|
86
93
|
return targets
|
87
94
|
end
|
88
95
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
response['links'].reverse_each do |link|
|
109
|
-
|
110
|
-
uri = link['data']['url'] || link['source']
|
111
|
-
|
112
|
-
# set the source
|
113
|
-
source = false
|
114
|
-
if uri.include? 'twitter.com/'
|
115
|
-
source = 'twitter'
|
116
|
-
elsif uri.include? '/googleplus/'
|
117
|
-
source = 'googleplus'
|
118
|
-
end
|
119
|
-
|
120
|
-
# set an id
|
121
|
-
id = link['id'].to_s
|
122
|
-
if source == 'twitter' and ! uri.include? '#favorited-by'
|
123
|
-
id = URI(uri).path.split('/').last.to_s
|
124
|
-
end
|
125
|
-
if ! id
|
126
|
-
time = Time.now();
|
127
|
-
id = time.strftime('%s').to_s
|
128
|
-
end
|
129
|
-
|
130
|
-
# Do we already have it?
|
131
|
-
if webmentions.has_key? id
|
132
|
-
next
|
133
|
-
end
|
134
|
-
|
135
|
-
# Get the mentioned URI, stripping fragments and query strings
|
136
|
-
#target = URI::parse( link['target'] )
|
137
|
-
#target.fragment = target.query = nil
|
138
|
-
#target = target.to_s
|
96
|
+
def markdownify( string )
|
97
|
+
string = @converter.convert("#{string}")
|
98
|
+
if ! string.start_with?('<p')
|
99
|
+
string = string.sub(/^<[^>]+>/, '<p>').sub(/<\/[^>]+>$/, '</p>')
|
100
|
+
end
|
101
|
+
string.strip
|
102
|
+
end
|
103
|
+
|
104
|
+
def process_webmentions( post_uri, response )
|
105
|
+
|
106
|
+
# Get cached webmentions
|
107
|
+
if @cached_webmentions.has_key? post_uri
|
108
|
+
webmentions = @cached_webmentions[post_uri]
|
109
|
+
else
|
110
|
+
webmentions = {}
|
111
|
+
end
|
112
|
+
|
113
|
+
if response and response['links']
|
139
114
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
115
|
+
response['links'].reverse_each do |link|
|
116
|
+
|
117
|
+
uri = link['data']['url'] || link['source']
|
118
|
+
|
119
|
+
# set the source
|
120
|
+
source = false
|
121
|
+
if uri.include? 'twitter.com/'
|
122
|
+
source = 'twitter'
|
123
|
+
elsif uri.include? '/googleplus/'
|
124
|
+
source = 'googleplus'
|
125
|
+
end
|
126
|
+
|
127
|
+
# set an id
|
128
|
+
id = link['id'].to_s
|
129
|
+
if source == 'twitter' and ! uri.include? '#favorited-by'
|
130
|
+
id = URI(uri).path.split('/').last.to_s
|
131
|
+
end
|
132
|
+
if ! id
|
133
|
+
time = Time.now();
|
134
|
+
id = time.strftime('%s').to_s
|
135
|
+
end
|
136
|
+
|
137
|
+
# Do we already have it?
|
138
|
+
if webmentions.has_key? id
|
139
|
+
next
|
140
|
+
end
|
141
|
+
|
142
|
+
# Get the mentioned URI, stripping fragments and query strings
|
143
|
+
#target = URI::parse( link['target'] )
|
144
|
+
#target.fragment = target.query = nil
|
145
|
+
#target = target.to_s
|
146
|
+
|
147
|
+
pubdate = link['data']['published_ts']
|
148
|
+
if pubdate
|
149
|
+
pubdate = Time.at(pubdate)
|
150
|
+
elsif link['verified_date']
|
151
|
+
pubdate = Time.parse(link['verified_date'])
|
152
|
+
end
|
153
|
+
#the_date = pubdate.strftime('%s')
|
154
|
+
|
155
|
+
# Make sure we have the date
|
156
|
+
# if ! webmentions.has_key? the_date
|
150
157
|
# webmentions[the_date] = {}
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
158
|
+
# end
|
159
|
+
|
160
|
+
# Make sure we have the webmention
|
161
|
+
if ! webmentions.has_key? id
|
162
|
+
|
163
|
+
# Scaffold the webmention
|
164
|
+
webmention = {
|
165
|
+
'id' => id,
|
166
|
+
'url' => uri,
|
167
|
+
'source' => source,
|
168
|
+
'pubdate' => pubdate,
|
169
|
+
'raw' => link
|
170
|
+
}
|
171
|
+
|
172
|
+
# Set the author
|
173
|
+
if link['data'].has_key? 'author'
|
174
|
+
webmention['author'] = link['data']['author']
|
175
|
+
end
|
176
|
+
|
177
|
+
# Set the type
|
178
|
+
type = link['activity']['type']
|
179
|
+
if ! type
|
180
|
+
if source == 'googleplus'
|
181
|
+
if uri.include? '/like/'
|
182
|
+
type = 'like'
|
183
|
+
elsif uri.include? '/repost/'
|
184
|
+
type = 'repost'
|
185
|
+
elsif uri.include? '/comment/'
|
186
|
+
type = 'reply'
|
187
|
+
else
|
188
|
+
type = 'link'
|
189
|
+
end
|
190
|
+
else
|
191
|
+
type = 'post'
|
192
|
+
end
|
193
|
+
end # if no type
|
194
|
+
webmention['type'] = type
|
195
|
+
|
196
|
+
# Posts
|
197
|
+
title = false
|
198
|
+
if type == 'post'
|
199
|
+
|
200
|
+
html_source = Jekyll::WebmentionIO::get_uri_source( uri )
|
194
201
|
if ! html_source
|
195
202
|
next
|
196
203
|
end
|
197
|
-
|
198
|
-
|
204
|
+
|
205
|
+
if ! html_source.valid_encoding?
|
199
206
|
html_source = html_source.encode('UTF-16be', :invalid=>:replace, :replace=>"?").encode('UTF-8')
|
200
207
|
end
|
201
208
|
|
202
|
-
|
209
|
+
# Check the `title` first
|
203
210
|
matches = /<title>(.*)<\/title>/.match( html_source )
|
204
211
|
if matches
|
205
212
|
title = matches[1].strip
|
206
213
|
else
|
207
|
-
|
208
|
-
|
214
|
+
# Fall back to the first `h1`
|
215
|
+
matches = /<h1>(.*)<\/h1>/.match( html_source )
|
209
216
|
if matches
|
210
217
|
title = matches[1].strip
|
211
218
|
else
|
212
|
-
|
219
|
+
# No title found
|
213
220
|
title = 'No title available'
|
214
221
|
end
|
215
222
|
end
|
216
223
|
|
217
|
-
|
224
|
+
# cleanup
|
218
225
|
title = title.gsub(%r{</?[^>]+?>}, '')
|
219
|
-
|
220
|
-
|
226
|
+
end # if no title
|
227
|
+
webmention['title'] = markdownify( title ) if title
|
221
228
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
229
|
+
# Everything else
|
230
|
+
content = link['data']['content']
|
231
|
+
if type != 'post' && type != 'reply' && type != 'link'
|
232
|
+
content = link['activity']['sentence_html']
|
233
|
+
end
|
234
|
+
webmention['content'] = markdownify( content )
|
228
235
|
|
229
|
-
|
230
|
-
|
231
|
-
|
236
|
+
# Add it to the list
|
237
|
+
# @webmention_io.log 'info', webmention.inspect
|
238
|
+
webmentions[id] = webmention
|
232
239
|
|
233
|
-
|
234
|
-
|
235
|
-
|
240
|
+
end # if ID does not exist
|
241
|
+
|
242
|
+
end # each link
|
236
243
|
|
237
|
-
|
244
|
+
end # if response
|
238
245
|
|
239
|
-
|
246
|
+
@cached_webmentions[post_uri] = webmentions
|
240
247
|
|
241
|
-
|
248
|
+
end # process_webmentions
|
242
249
|
|
243
250
|
end
|
244
251
|
end
|
data/lib/jekyll/tags/_.rb
CHANGED
@@ -49,8 +49,8 @@ module Jekyll
|
|
49
49
|
# Jekyll::WebmentionIO::log 'info', "template: #{@template}"
|
50
50
|
end
|
51
51
|
|
52
|
-
def set_data(data)
|
53
|
-
@data = { 'webmentions' => data }
|
52
|
+
def set_data( data, types )
|
53
|
+
@data = { 'webmentions' => data, 'types' => types }
|
54
54
|
end
|
55
55
|
|
56
56
|
def extract_type( type, webmentions )
|
@@ -83,6 +83,9 @@ module Jekyll
|
|
83
83
|
uri = args.shift
|
84
84
|
uri = lookup(context, uri)
|
85
85
|
|
86
|
+
# capture the types in case JS needs them
|
87
|
+
types = []
|
88
|
+
|
86
89
|
if @cached_webmentions.has_key? uri
|
87
90
|
all_webmentions = @cached_webmentions[uri].clone
|
88
91
|
# Jekyll::WebmentionIO::log 'info', "#{all_webmentions.length} total webmentions for #{uri}"
|
@@ -90,6 +93,7 @@ module Jekyll
|
|
90
93
|
# Jekyll::WebmentionIO::log 'info', "Requesting only #{args.inspect}"
|
91
94
|
webmentions = {}
|
92
95
|
args.each do |type|
|
96
|
+
types.push type
|
93
97
|
extracted = extract_type( type, all_webmentions )
|
94
98
|
# Jekyll::WebmentionIO::log 'info', "Merging in #{extracted.length} #{type}"
|
95
99
|
webmentions = webmentions.merge( extracted )
|
@@ -105,7 +109,7 @@ module Jekyll
|
|
105
109
|
|
106
110
|
webmentions = sort_webmentions( webmentions )
|
107
111
|
|
108
|
-
set_data( webmentions )
|
112
|
+
set_data( webmentions, types )
|
109
113
|
end
|
110
114
|
|
111
115
|
args = nil
|
data/lib/jekyll/tags/count.rb
CHANGED
data/lib/jekyll/tags/likes.rb
CHANGED
data/lib/jekyll/tags/links.rb
CHANGED
data/lib/jekyll/tags/posts.rb
CHANGED
data/lib/jekyll/tags/replies.rb
CHANGED
data/lib/jekyll/tags/reposts.rb
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
# (c) Aaron Gustafson
|
2
|
+
# https://github.com/aarongustafson/jekyll-webmention_io
|
3
|
+
# Licence : MIT
|
4
|
+
#
|
5
|
+
# Stuff for the `head`
|
6
|
+
#
|
7
|
+
|
8
|
+
module Jekyll
|
9
|
+
module WebmentionIO
|
10
|
+
class WebmentionHeadTag < Liquid::Tag
|
11
|
+
def render(context)
|
12
|
+
head = ''
|
13
|
+
head << '<link rel="dns-prefetch" href="//webmention.io">'
|
14
|
+
head << '<link rel="preconnect" href="//webmention.io">'
|
15
|
+
head << '<link rel="preconnect" href="ws://webmention.io:8080">'
|
16
|
+
|
17
|
+
page = context['page']
|
18
|
+
site = context.registers[:site]
|
19
|
+
if page['redirect_from']
|
20
|
+
if page['redirect_from'].is_a? String
|
21
|
+
redirect = site.config['url'] + page['redirect_from']
|
22
|
+
elsif page['redirect_from'].is_a? Array
|
23
|
+
redirect = site.config['url'] + page['redirect_from'].join(",#{site.config['url']}")
|
24
|
+
end
|
25
|
+
head << "<meta property=\"webmention:redirected_from\" content=\"#{redirect}\">"
|
26
|
+
end
|
27
|
+
|
28
|
+
head
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
Liquid::Template.register_tag('webmentions_head', Jekyll::WebmentionIO::WebmentionHeadTag)
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# (c) Aaron Gustafson
|
2
|
+
# https://github.com/aarongustafson/jekyll-webmention_io
|
3
|
+
# Licence : MIT
|
4
|
+
#
|
5
|
+
# JS stuff
|
6
|
+
#
|
7
|
+
|
8
|
+
module Jekyll
|
9
|
+
module WebmentionIO
|
10
|
+
class WebmentionJSTag < Liquid::Tag
|
11
|
+
def render(context)
|
12
|
+
site = context.registers[:site]
|
13
|
+
|
14
|
+
# JS can be turned off too
|
15
|
+
if site.config['webmentions']['js'] == false
|
16
|
+
return
|
17
|
+
end
|
18
|
+
|
19
|
+
config = {
|
20
|
+
'destination' => "js",
|
21
|
+
'uglify' => true
|
22
|
+
}
|
23
|
+
site_config = site.config['webmentions']['js'] || {}
|
24
|
+
config = config.merge(site_config)
|
25
|
+
|
26
|
+
# JS file
|
27
|
+
js = ''
|
28
|
+
unless config['deploy'] == false
|
29
|
+
js_file_path = "#{site.config['baseurl']}/#{config['destination']}/JekyllWebmentionIO.js"
|
30
|
+
js << "<script src=\"#{js_file_path}\" async></script>"
|
31
|
+
end
|
32
|
+
|
33
|
+
templates = ''
|
34
|
+
template_files = Jekyll::WebmentionIO::types + ['count', 'webmentions']
|
35
|
+
template_files.each do |template|
|
36
|
+
if Jekyll::WebmentionIO::config.has_key? 'templates' and Jekyll::WebmentionIO::config['templates'].has_key? template
|
37
|
+
# Jekyll::WebmentionIO::log 'info', "Using custom #{template} template"
|
38
|
+
template_file = Jekyll::WebmentionIO::config['templates'][template]
|
39
|
+
else
|
40
|
+
# Jekyll::WebmentionIO::log 'info', "Using default #{template} template"
|
41
|
+
template_file = File.join(File.dirname(File.expand_path(__FILE__)), "../templates/#{template}.html")
|
42
|
+
end
|
43
|
+
# Jekyll::WebmentionIO::log 'info', "Template file: #{template_file}"
|
44
|
+
handler = File.open(template_file, 'rb')
|
45
|
+
template_contents = handler.read
|
46
|
+
|
47
|
+
templates << "<template id=\"webmention-#{template}\">#{template_contents}</template>"
|
48
|
+
end
|
49
|
+
|
50
|
+
"#{js}\n#{templates}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
Liquid::Template.register_tag('webmentions_js', Jekyll::WebmentionIO::WebmentionJSTag)
|
@@ -1 +1,2 @@
|
|
1
|
-
|
1
|
+
{% capture webmention_types %}{{ types | join: ',' }}{% endcapture %}
|
2
|
+
<span class="webmention-count"{% unless webmention_types=="" %} data-webmention-types="{{ webmention_types }}"{% endunless %}>{{ count }}</span>
|
@@ -1,17 +1,17 @@
|
|
1
1
|
<div class="webmentions webmentions--likes">
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
2
|
+
{% if webmentions.size > 0 %}
|
3
|
+
<ol class="webmentions__list">
|
4
|
+
{% for webmention in webmentions %}
|
5
|
+
<li id="webmention-{{ webmention.id }}" class="webmentions__item webmention webmention--{{ 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
17
|
</div>
|