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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b1a2ad81306bf59b5075c769765801e249bc6611
4
+ data.tar.gz: e823588e8adcbde48dbd143714c1c5163c06033f
5
+ SHA512:
6
+ metadata.gz: d6ff6cfbf120dc15f6129b50d8a37ebd67a888c74b74ce32fdf1f4f7248592dcb584b0f2b71fe115302a93cd4502760cccf5d2e8c88f287d03ea9dd829e5c932
7
+ data.tar.gz: 050f219c2841728490b6d566756d3a949da964c0c6bd0e13ea9bcc535401bfa173398307a2fc953cbce4e9edb1824823aefa39ae74bf9356c01ed836edfe057b
@@ -0,0 +1,549 @@
1
+ /**
2
+ * WebMentions.io JS
3
+ * A re-tooling of Aaron Parecki’s recommended JS for using the WebMention.io API
4
+ *
5
+ * Updates Webmentions on a static site immediately when the page is loaded and
6
+ * in real-time (using WebSockets) as the user engages with the page.
7
+ *
8
+ * To inform the JavaScript of additional URLs to check (e.g. when the current page
9
+ * receives redirects from old URLs), use the following meta element:
10
+ *
11
+ * <meta property="webmention:redirected_from" content="URL_1,URL_2">
12
+ *
13
+ * The content should be a single URL or multiple, separated by commas.
14
+ */
15
+
16
+ ;(function( window, document ){
17
+ 'use strict';
18
+
19
+ if ( ! ( 'querySelectorAll' in document ) ){ return; }
20
+
21
+ if ( ! ( 'AG' in window ) ){ window.AG = {}; }
22
+
23
+ if ( ! window.location.origin )
24
+ {
25
+ window.location.origin = window.location.protocol + '//' + window.location.host;
26
+ }
27
+
28
+ var $webmentions_list = document.querySelectorAll( '.webmentions__list' ),
29
+ elements = {
30
+ a: document.createElement('a'),
31
+ author_name:document.createElement('b'),
32
+ article: document.createElement('article'),
33
+ div: document.createElement('div'),
34
+ photo: document.createElement('img'),
35
+ li: document.createElement('li'),
36
+ time: document.createElement('time')
37
+ },
38
+ space = document.createTextNode(' '),
39
+ months = [
40
+ 'January', 'February', 'March', 'April', 'May', 'June',
41
+ 'July', 'August', 'September', 'October', 'November', 'December'
42
+ ],
43
+ json_webmentions,
44
+ targets = [],
45
+ $none = false,
46
+ $redirects = document.querySelector('meta[property="webmention:redirected_from"]'),
47
+ redirects,
48
+ complete_urls = [],
49
+ base_url = window.location.origin,
50
+ $existing_webmentions,
51
+ existing_webmentions = [],
52
+ e = 0;
53
+
54
+ // handle redirects
55
+ if ( $redirects )
56
+ {
57
+ redirects = $redirects.getAttribute('content').split(',');
58
+ redirects.forEach(function( value ){
59
+ targets.push(
60
+ value.indexOf('//') < 0 ? base_url + value : value
61
+ );
62
+ });
63
+ redirects = false;
64
+ }
65
+
66
+ // map to http too
67
+ if ( window.location.protocol != 'http:' )
68
+ {
69
+ targets.forEach(function( value ){
70
+ complete_urls.push( value );
71
+ if ( value.indexOf( 'https://' ) != -1 )
72
+ {
73
+ complete_urls.push( value.replace( 'https://', 'http://' ) );
74
+ }
75
+ });
76
+ targets = complete_urls;
77
+ complete_urls = false;
78
+ }
79
+
80
+ // Do we need to create the list?
81
+ if ( $webmentions_list.length < 1 )
82
+ {
83
+ $none = document.querySelectorAll( '.webmentions__not-found' );
84
+ if ( $none.length )
85
+ {
86
+ $none = $none[0];
87
+ $webmentions_list = document.createElement( 'ol' );
88
+ $webmentions_list.className = 'webmentions__list';
89
+ }
90
+ else
91
+ {
92
+ return;
93
+ }
94
+ }
95
+ else
96
+ {
97
+ $webmentions_list = $webmentions_list[0];
98
+ // get existing webmentions
99
+ $existing_webmentions = $webmentions_list.querySelectorAll( '[id^=webmention-]' );
100
+ e = $existing_webmentions.length;
101
+ while ( e-- )
102
+ {
103
+ existing_webmentions.push(
104
+ $existing_webmentions[e]
105
+ .getAttribute( 'id' )
106
+ .replace( 'webmention-', '' )
107
+ );
108
+ }
109
+ //console.log(existing_webmentions);
110
+ $existing_webmentions = null;
111
+ }
112
+ window.AG.existing_webmentions = existing_webmentions;
113
+
114
+ // Set up the markup
115
+ elements.li.className = 'webmentions__item';
116
+ elements.article.className = 'h-cite webmention';
117
+ elements.time.className = 'webmention__pubdate dt-published';
118
+ elements.author = elements.div.cloneNode();
119
+ elements.author.className = 'webmention__author p-author h-card';
120
+ elements.author_name.className = 'p-name';
121
+ elements.author_link = elements.a.cloneNode();
122
+ elements.author_link.className = 'u-url';
123
+ elements.photo.className = 'webmention__author__photo u-photo';
124
+ elements.photo.alt = '';
125
+ elements.title = elements.div.cloneNode();
126
+ elements.title.className = 'webmention__title p-name';
127
+ elements.permalink = elements.a.cloneNode();
128
+ elements.permalink.className = 'webmention__source u-url';
129
+ elements.permalink.appendChild( document.createTextNode('Permalink') );
130
+ elements.content = elements.div.cloneNode();
131
+ elements.content.className = 'webmention__content p-content';
132
+ elements.meta = elements.div.cloneNode();
133
+ elements.meta.className = 'webmention__meta';
134
+
135
+ function addMention( mention )
136
+ {
137
+ //console.log(mention);
138
+ var streaming = !( 'data' in mention ),
139
+ data = streaming ? mention : mention.data,
140
+ id = streaming ? mention.element_id : mention.id,
141
+ is_tweet = false,
142
+ is_gplus = false;
143
+
144
+ // make sure the id is a string
145
+ id = id.toString();
146
+
147
+ // Tweets gets handled differently
148
+ if ( data.url && data.url.indexOf( 'twitter.com/' ) > -1 )
149
+ {
150
+ is_tweet = true;
151
+ // Unique tweets gets unique IDs
152
+ if ( data.url.indexOf( '#favorited-by' ) == -1 )
153
+ {
154
+ id = data.url.replace( /^.*?status\/(.*)$/, '$1' );
155
+ }
156
+ }
157
+
158
+ // No need to replace
159
+ //console.log( existing_webmentions, id, existing_webmentions.indexOf( id ) );
160
+ if ( existing_webmentions.indexOf( id ) > -1 )
161
+ {
162
+ return;
163
+ }
164
+
165
+ // Google Plus gets handled differently
166
+ if ( data.url.indexOf( '/googleplus/' ) )
167
+ {
168
+ is_gplus = true;
169
+ }
170
+
171
+ var $item = elements.li.cloneNode( true ),
172
+ $mention = elements.article.cloneNode( true ),
173
+ $author = elements.author.cloneNode( true ),
174
+ $author_name = elements.author_name.cloneNode( true ),
175
+ $author_link = elements.author_link.cloneNode( true ),
176
+ $author_photo = elements.photo.cloneNode( true ),
177
+ $meta = elements.meta.cloneNode( true ),
178
+ $pubdate = elements.time.cloneNode( true ),
179
+ $block,
180
+ $link,
181
+ title = data.name,
182
+ link_title = false,
183
+ content = data.content,
184
+ url = data.url || mention.source,
185
+ type = mention.activity.type,
186
+ author = data.author ? data.author.name : false,
187
+ author_photo = data.author ? data.author.photo : false,
188
+ pubdate,
189
+ display_date = '';
190
+
191
+ $item.id = 'webmention-' + id;
192
+ $item.appendChild( $mention );
193
+
194
+ // no data, skip it
195
+ if ( ! title && ! content )
196
+ {
197
+ return;
198
+ }
199
+
200
+ ////
201
+ // Authorship
202
+ ////
203
+ if ( author )
204
+ {
205
+ if ( author_photo )
206
+ {
207
+ $author_photo.src = author_photo;
208
+ $author_link.appendChild( $author_photo );
209
+ }
210
+ else
211
+ {
212
+ $mention.className += ' webmention--no-photo';
213
+ }
214
+ $author_name.appendChild( document.createTextNode( author ) );
215
+ if ( data.author.url )
216
+ {
217
+ $author_link.href = data.author.url;
218
+ $author_link.appendChild( $author_name );
219
+ $author.appendChild( $author_link );
220
+ }
221
+ else
222
+ {
223
+ $author.appendChild( $author_name );
224
+ }
225
+ $mention.appendChild( $author );
226
+ }
227
+ else
228
+ {
229
+ $mention.className += ' webmention--no-author';
230
+ }
231
+
232
+ ////
233
+ // Content
234
+ ////
235
+ if ( ! type )
236
+ {
237
+ // Trap Google Plus from Bridgy
238
+ if ( is_gplus )
239
+ {
240
+ if ( url.indexOf( '/like/' ) > -1 )
241
+ {
242
+ type = 'like';
243
+ }
244
+ else if ( url.indexOf( '/repost/' ) > -1 )
245
+ {
246
+ type = 'repost';
247
+ }
248
+ else if ( url.indexOf( '/comment/' ) > -1 )
249
+ {
250
+ type = 'reply';
251
+ }
252
+ else
253
+ {
254
+ type = 'link';
255
+ }
256
+ }
257
+ // Default
258
+ else
259
+ {
260
+ type = 'post';
261
+ }
262
+ }
263
+
264
+ // more than likely the content was pushed into the post name
265
+ if ( title && title.length > 200 )
266
+ {
267
+ title = false;
268
+ }
269
+
270
+ // TODO: Google Plus masked by Bridgy
271
+ // Ruby Code:
272
+ // if is_gplus and url.include? 'brid-gy'
273
+ // #
274
+ // status = `curl -s -I -L -o /dev/null -w "%{http_code}" --location "#{url}"`
275
+ // if status == '200'
276
+ // # Now get the content
277
+ // html_source = `curl -s --location "#{url}"`
278
+ //
279
+ // if ! html_source.valid_encoding?
280
+ // html_source = html_source.encode('UTF-16be', :invalid=>:replace, :replace=>"?").encode('UTF-8')
281
+ // end
282
+ //
283
+ // matches = /class="u-url" href=".+">(https:.+)</.match( html_source )
284
+ // if matches
285
+ // url = matches[1].strip
286
+ // end
287
+ // else
288
+ // url = false
289
+ // end
290
+ // end
291
+
292
+ // Posts (but not tweeted links)
293
+ if ( type == 'post' ||
294
+ ( type == 'link' && ! is_tweet && ! is_gplus ) )
295
+ {
296
+ link_title = title;
297
+
298
+ // No title - Async update
299
+ if ( ! title && url )
300
+ {
301
+ readWebPage( url, function( html_source ){
302
+ if ( html_source )
303
+ {
304
+ linkTitle( $item, url, html_source );
305
+ }
306
+ });
307
+ }
308
+ }
309
+ // Likes & Shares
310
+ else if ( type == 'like' || type == 'repost' )
311
+ {
312
+ // new Twitter faves are doing something weird
313
+ if ( type == 'like' && is_tweet )
314
+ {
315
+ link_title = author + ' favorited this.';
316
+ }
317
+ else if ( type == 'repost' && is_tweet )
318
+ {
319
+ link_title = author + ' retweeted this.';
320
+ }
321
+ else
322
+ {
323
+ link_title = title;
324
+ }
325
+ $mention.className += ' webmention--author-starts';
326
+ }
327
+
328
+ // Published info
329
+ if ( data.published_ts )
330
+ {
331
+ pubdate = new Date(0);
332
+ pubdate.setUTCSeconds( data.published_ts );
333
+ }
334
+ else if ( data.published || mention.verified_date )
335
+ {
336
+ pubdate = new Date( data.published || mention.verified_date );
337
+ }
338
+ if ( pubdate )
339
+ {
340
+ $pubdate.setAttribute( 'datetime', pubdate.toISOString() );
341
+ display_date += pubdate.getUTCDate() + ' ';
342
+ display_date += months[ pubdate.getUTCMonth() ] + ' ';
343
+ display_date += pubdate.getUTCFullYear();
344
+ $pubdate.appendChild( document.createTextNode( display_date ) );
345
+ $meta.appendChild( $pubdate );
346
+ }
347
+
348
+ if ( ! link_title )
349
+ {
350
+ if ( pubdate && url )
351
+ {
352
+ $meta.appendChild( document.createTextNode( ' | ' ) );
353
+ }
354
+ if ( url )
355
+ {
356
+ $link = elements.permalink.cloneNode( true );
357
+ $link.href = url;
358
+ $meta.appendChild( $link );
359
+ }
360
+ }
361
+
362
+ if ( author &&
363
+ $mention.className.indexOf( 'webmention--author-starts' ) == -1 &&
364
+ ( ( title && title.indexOf( author ) == '0' ) ||
365
+ ( content && content.indexOf( author ) == '0' ) ) )
366
+ {
367
+ $mention.className += ' webmention--author-starts';
368
+ }
369
+
370
+ if ( link_title )
371
+ {
372
+ $mention.className += ' webmention--title-only';
373
+
374
+ link_title = link_title.replace( 'reposts', 'reposted' );
375
+
376
+ if ( url )
377
+ {
378
+ $link = elements.a.cloneNode( true );
379
+ $link.href = url;
380
+ $link.appendChild( document.createTextNode( link_title ) );
381
+ }
382
+ else
383
+ {
384
+ $link = document.createTextNode( link_title );
385
+ }
386
+
387
+ $block = elements.title.cloneNode( true );
388
+ $block.appendChild( $link );
389
+ $mention.appendChild( space.cloneNode( true ) );
390
+ $mention.appendChild( $block );
391
+ }
392
+ else
393
+ {
394
+ $mention.className += ' webmention--content-only';
395
+ $block = elements.content.cloneNode( true );
396
+ $block.innerHTML = content;
397
+ $mention.appendChild( $block );
398
+ }
399
+
400
+ if ( $meta.children.length > 0 )
401
+ {
402
+ $mention.appendChild( $meta );
403
+ }
404
+
405
+ if ( !! $none )
406
+ {
407
+ $none.parentNode.replaceChild( $webmentions_list, $none );
408
+ $none = false;
409
+ }
410
+ $webmentions_list.appendChild( $item );
411
+
412
+ // Store the id
413
+ existing_webmentions.push( id );
414
+
415
+ // Release
416
+ $item = null;
417
+ $mention = null;
418
+ $author = null;
419
+ $author_name = null;
420
+ $author_link = null;
421
+ $author_photo = null;
422
+ $block = null;
423
+ $link = null;
424
+ $meta = null;
425
+ $pubdate = null;
426
+
427
+ }
428
+
429
+ window.AG.processWebmentions = function( data ){
430
+ if ( data &&
431
+ ! ( 'error' in data ) )
432
+ {
433
+ data.links.reverse();
434
+ data.links.forEach( addMention );
435
+ updateCount();
436
+ }
437
+ };
438
+
439
+ // Update the webmentions count
440
+ function updateCount() {
441
+ var $webmentions_link = document.querySelector( '.entry__jump--webmentions a' ),
442
+ webmentions_count = document.querySelectorAll( '.webmentions__item' ).length;
443
+
444
+ $webmentions_link.innerHTML = webmentions_count + ' webmentions';
445
+ }
446
+
447
+ // Synchromous XHR proxied through whateverorigin.org
448
+ function readWebPage( uri, callback )
449
+ {
450
+ if ( 'XMLHttpRequest' in window )
451
+ {
452
+ var XHR = new XMLHttpRequest();
453
+ readWebPage = function( uri, callback ){
454
+ var done = false;
455
+ uri = '//whateverorigin.org/get?url=' + encodeURIComponent( uri );
456
+ XHR.onreadystatechange = function() {
457
+ if ( this.readyState == 4 && ! done ) {
458
+ done = true;
459
+ callback( XHR.responseText );
460
+ }
461
+ };
462
+ xhr.onabort = function() {
463
+ if ( ! done )
464
+ {
465
+ done = true;
466
+ callback( false );
467
+ }
468
+ };
469
+ XHR.onerror = XHR.onabort;
470
+ XHR.open( 'GET', uri );
471
+ XHR.send( null );
472
+ };
473
+ }
474
+ else
475
+ {
476
+ readWebPage = function( uri, callback ){
477
+ callback( false );
478
+ };
479
+ }
480
+ return readWebPage( uri, callback );
481
+ }
482
+
483
+ // Async update of the title
484
+ function updateTitle( $item, url, html_source )
485
+ {
486
+ var $current_title = $item.querySelector( '.webmention__title' ),
487
+ matches = /<title>\s*(.*)\s*<\/title>/.match( html_source ),
488
+ title = '',
489
+ $link_title;
490
+
491
+ if ( matches )
492
+ {
493
+ title = matches[1];
494
+ }
495
+ else
496
+ {
497
+ matches = /<h1>\s*(.*)\s*<\/h1>/.match( html_source );
498
+ if ( matches )
499
+ {
500
+ title = matches[1];
501
+ }
502
+ else
503
+ {
504
+ title = 'No title available';
505
+ }
506
+ }
507
+
508
+ if ( title )
509
+ {
510
+ $link_title = elements.a.cloneNode( true );
511
+ $link_title.href = url;
512
+ $link_title.appendChild( document.createTextNode( title ) );
513
+ // clear and replace title contents
514
+ $current_title.innerHTML = '';
515
+ $currentTitle.appendChild( $link_title );
516
+ }
517
+ }
518
+
519
+ // Preconnect to Webmention.io
520
+ if ( 'preconnect' in window.AG )
521
+ {
522
+ window.AG.preconnect( '//webmention.io' );
523
+ window.AG.preconnect( 'ws://webmention.io:8080' );
524
+ }
525
+
526
+ // Load up any unpublished webmentions on load
527
+ json_webmentions = document.createElement('script');
528
+ json_webmentions.async = true;
529
+ json_webmentions.src = '//webmention.io/api/mentions?jsonp=window.AG.processWebmentions&target[]=' +
530
+ targets.join( '&target[]=' );
531
+ document.getElementsByTagName('head')[0].appendChild( json_webmentions );
532
+
533
+ // Listen for new ones
534
+ if ( $webmentions_list.length &&
535
+ 'WebSocket' in window )
536
+ {
537
+ var ws = new WebSocket('ws://webmention.io:8080');
538
+
539
+ ws.onopen = function(){
540
+ // Send the current window URL to the server to register to receive notifications about this URL
541
+ ws.send( window.location );
542
+ };
543
+ ws.onmessage = function( event ){
544
+ addMention( JSON.parse( event.data ) );
545
+ updateCount();
546
+ };
547
+ }
548
+
549
+ }(this,this.document));