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.
@@ -1,549 +0,0 @@
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));