jekyll-webmention_io 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
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));