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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 672d103d7af89eb78fc8881d15b01eaca2baf478
4
- data.tar.gz: d485382ea200b239585a503544b1d369f2206fb0
3
+ metadata.gz: 050572d103fbe6372e35ddc50d232de12227baf7
4
+ data.tar.gz: 8f0d233cf38cd0de07bfa64a74c85adc1fea97e6
5
5
  SHA512:
6
- metadata.gz: b222875c7301ad0756e548c6d1b9a67787fd6d292b7db1f3d3d4370c2ee2b8ab151fb86aa70e1760aebdcef1376a83d036733e3c084a2277c9bd8d12b2b3d411
7
- data.tar.gz: beaf1fe3a89efc69c43d9397f06c17a2335a01383ec000ddaa93115b7c8c8f3a77adfd6d42cfae40292930f3fe9b5463df72c04adc076f4651bb1001003b8942
6
+ metadata.gz: 241a79370736d77a40337a48e220f333ba8fa9d4ea3b6487910b7065992c6cdf633eed6f3aeca20e5d942a220a3cc8973a322a15cf4b48ec7cab94e72c92ac28
7
+ data.tar.gz: 5f7df1e176bc298f8538347486f55eeb69b2a66d87371967a2e52eead9eefb4a2de5821f94cce741ed49f50bfd2d3d032a86273f98e9e3a7513ba275e2e12f26
@@ -0,0 +1,511 @@
1
+ (function(window, document){
2
+
3
+ // prerequisites
4
+ if ( ! ( 'querySelectorAll' in document ) ||
5
+ ! ( 'filter' in [] ) ||
6
+ ! ( 'content' in document.createElement('template') ) ){ return; }
7
+
8
+ if ( ! ( 'JekyllWebmentionIO' in window ) ){ window.JekyllWebmentionIO = {}; }
9
+
10
+ //
11
+ // Public Properties
12
+ //
13
+ JekyllWebmentionIO.existing_webmentions = [];
14
+
15
+ //
16
+ // Public Methods
17
+ //
18
+
19
+ JekyllWebmentionIO.processWebmentions = function( data ){
20
+ // console.log( 'incoming webmentions', data.links );
21
+ if ( data && ! ( 'error' in data ) )
22
+ {
23
+ webmentions = data.links.reverse();
24
+
25
+ webmentions = rationalizeIds( webmentions );
26
+
27
+ webmentions = removeDuplicates( webmentions );
28
+
29
+ // We may not need to proceed if we had them all
30
+ if ( webmentions.length )
31
+ {
32
+ webmentions = addMetadata( webmentions );
33
+
34
+ // hande them out
35
+ doleOutWebmentions( webmentions );
36
+
37
+ // reset the counters
38
+ if ( this.counter_update_event )
39
+ {
40
+ document.dispatchEvent( this.counter_update_event );
41
+ }
42
+ }
43
+ else
44
+ {
45
+ // console.log( 'no new webmentions to add' );
46
+ }
47
+ }
48
+ };
49
+
50
+ //
51
+ // Private Properties
52
+ //
53
+
54
+ var webmention_receivers = {},
55
+ templates = {};
56
+
57
+ //
58
+ // Private Methods
59
+ //
60
+
61
+ // Gathers embewdded templates
62
+ function collectTemplates()
63
+ {
64
+ var $templates = document.querySelectorAll( 'template[id^=webmention-]' ),
65
+ t = $templates.length,
66
+ $template;
67
+
68
+ while ( t-- )
69
+ {
70
+ $template = $templates[t];
71
+ // We only need the list (if one exists)
72
+ if ( $template.content.querySelector('ol') )
73
+ {
74
+ templates[$template.id] = $template.content.querySelector('ol');
75
+ }
76
+ else
77
+ {
78
+ templates[$template.id] = $template.content;
79
+ }
80
+ }
81
+ $template = null;
82
+ }
83
+
84
+ // Collects webmentions that are already on the page
85
+ function collectExistingWebmentions()
86
+ {
87
+ var $existing_webmentions = document.querySelectorAll( '[id^=webmention-]' ),
88
+ e = $existing_webmentions.length;
89
+
90
+ while ( e-- )
91
+ {
92
+ JekyllWebmentionIO.existing_webmentions.push(
93
+ $existing_webmentions[e]
94
+ .getAttribute( 'id' )
95
+ .replace( 'webmention-', '' )
96
+ );
97
+ }
98
+
99
+ $existing_webmentions = null;
100
+ }
101
+
102
+ function identifyWebmentionCollections()
103
+ {
104
+ var $webmention_collections = document.querySelectorAll( '.webmentions' ),
105
+ w = $webmention_collections.length,
106
+ $webmention_collection,
107
+ type,
108
+ types, t;
109
+
110
+ // Assign the type & template if we can determine it
111
+ while ( w-- )
112
+ {
113
+ $webmention_collection = $webmention_collections[w];
114
+
115
+ // Assign the type
116
+ type = 'webmentions'; // Generic
117
+ if ( $webmention_collection.className.indexOf('webmentions--') > -1 )
118
+ {
119
+ type = $webmention_collection.className.match(/webmentions\-\-(.*)/)[1];
120
+ }
121
+ $webmention_collection.type = type;
122
+
123
+ // Assign the template
124
+ if ( templates['webmention-' + type] )
125
+ {
126
+ $webmention_collection.template = templates['webmention-' + type];
127
+ }
128
+
129
+ // Add to the queues
130
+ if ( 'dataset' in $webmention_collection &&
131
+ 'webmentionTypes' in $webmention_collection.dataset )
132
+ {
133
+ types = $webmention_collection.dataset.webmentionTypes.split(',');
134
+ }
135
+ else
136
+ {
137
+ types = [ type ];
138
+ }
139
+ t = types.length;
140
+ while (t--)
141
+ {
142
+ type = types[t];
143
+ if ( ! ( type in webmention_receivers ) )
144
+ {
145
+ webmention_receivers[type] = [];
146
+ }
147
+ webmention_receivers[type].push( $webmention_collection );
148
+ }
149
+ }
150
+
151
+ $webmention_collection = null;
152
+ }
153
+
154
+ // Divvies up the webmentions and populate the lists
155
+ function doleOutWebmentions( webmentions )
156
+ {
157
+ var i = 0, j,
158
+ webmention,
159
+ incoming = {},
160
+ queue_keys = Object.keys( webmention_receivers ),
161
+ plural_type;
162
+
163
+ // set up the queues
164
+ i = queue_keys.length;
165
+ while( i--)
166
+ {
167
+ incoming[queue_keys[i]] = [];
168
+ }
169
+
170
+ // Assign the webmentions to their respective queues
171
+ i = webmentions.length;
172
+ while ( i-- )
173
+ {
174
+ webmention = webmentions[i];
175
+ // reverse lookup to get the plural from the singular
176
+ plural_type = Object.keys(JekyllWebmentionIO.types)
177
+ .filter(function(key) {
178
+ return JekyllWebmentionIO.types[key] === webmention.type;
179
+ })[0];
180
+
181
+ // Is there a specific queue requesting this?
182
+ if ( queue_keys.indexOf( plural_type ) > -1 )
183
+ {
184
+ incoming[plural_type].push( webmention );
185
+ }
186
+
187
+ // If there’s a generic, add it there too
188
+ if ( incoming.webmentions )
189
+ {
190
+ incoming.webmentions.push( webmention );
191
+ }
192
+ }
193
+
194
+ // Now hand them out
195
+ i = queue_keys.length;
196
+ while( i-- )
197
+ {
198
+ j = webmention_receivers[queue_keys[i]].length;
199
+ while ( j-- )
200
+ {
201
+ // No point passing nothing
202
+ if ( incoming[queue_keys[i]].length > 0 )
203
+ {
204
+ addWebmentionsToCollection( incoming[queue_keys[i]], webmention_receivers[queue_keys[i]][j] );
205
+ }
206
+ }
207
+ }
208
+
209
+ }
210
+
211
+ function addWebmentionsToCollection( mentions, $webmention_collection )
212
+ {
213
+ if ( mentions.length < 1 )
214
+ {
215
+ console.warn( 'No webmentions to add, check your application code' );
216
+ return;
217
+ }
218
+
219
+ if ( ! $webmention_collection.template )
220
+ {
221
+ console.error( 'No template found for this webmention group', $webmention_collection );
222
+ return;
223
+ }
224
+
225
+ if ( ! ( 'Liquid' in window ) )
226
+ {
227
+ console.error( 'Liquid parsing engine is not available' );
228
+ return;
229
+ }
230
+
231
+ var $list = $webmention_collection.querySelector('.webmentions__list'),
232
+ template = $webmention_collection.template,
233
+ mode = 'append',
234
+ html;
235
+
236
+ // Already working with a list
237
+ if ( $list )
238
+ {
239
+ template = Liquid.parse( template.innerHTML );
240
+ }
241
+ // Need a list
242
+ else
243
+ {
244
+ template = Liquid.parse( template.outerHTML );
245
+ mode = 'replace';
246
+ }
247
+
248
+ // append
249
+ html = template.render({ 'webmentions': mentions });
250
+ if ( mode == 'append' )
251
+ {
252
+ $list.innerHTML += html;
253
+ }
254
+ else
255
+ {
256
+ $webmention_collection.innerHTML = html;
257
+ }
258
+
259
+ // console.log( 'Successfully added', mentions.length );
260
+ }
261
+
262
+ // Uses the ID attribute for everything except tweets
263
+ function rationalizeIds( webmentions )
264
+ {
265
+ // console.log( 'rationizing IDs' );
266
+ var i = webmentions.length,
267
+ id,
268
+ url;
269
+
270
+ while ( i-- )
271
+ {
272
+ id = webmentions[i].id;
273
+ url = webmentions[i].data.url || webmentions[i].source;
274
+ if ( url && url.indexOf( 'twitter.com/' ) > -1 )
275
+ {
276
+ // Unique tweets gets unique IDs
277
+ if ( url.indexOf( '#favorited-by' ) < 0 )
278
+ {
279
+ id = url.replace( /^.*?status\/(\d+)$/, '$1' );
280
+ }
281
+ }
282
+ // coerce to a string
283
+ webmentions[i].id = id + '';
284
+ }
285
+
286
+ // console.log( webmentions.length, 'IDs rationalized' );
287
+ return webmentions;
288
+ }
289
+
290
+ // Removes duplicate webmentions
291
+ function removeDuplicates( webmentions )
292
+ {
293
+ // console.log( 'removing duplicates' );
294
+ // going backwards, so reverse things to start out
295
+ webmentions.reverse();
296
+
297
+ var unique_webmentions = [],
298
+ i = webmentions.length,
299
+ id;
300
+
301
+ while ( i-- )
302
+ {
303
+ if ( JekyllWebmentionIO.existing_webmentions.indexOf( webmentions[i].id ) < 0 )
304
+ {
305
+ unique_webmentions.push(webmentions[i]);
306
+ }
307
+ }
308
+
309
+ // console.log( 'removed', webmentions.length - unique_webmentions.length, 'duplicates' );
310
+ return unique_webmentions;
311
+ }
312
+
313
+ // Adds the necessary metadata to each webmention object for the liquid templates
314
+ function addMetadata( webmentions )
315
+ {
316
+ // console.log( 'adding metadata' );
317
+ // going backwards, so reverse things to start out
318
+ webmentions.reverse();
319
+
320
+ var i = webmentions.length,
321
+ webmention,
322
+ webmention_object;
323
+
324
+ while ( i-- )
325
+ {
326
+ webmention = webmentions[i];
327
+
328
+ uri = webmention.data.url || webmention.source;
329
+
330
+ source = false;
331
+ if ( uri.indexOf('twitter.com/') )
332
+ {
333
+ source = 'twitter';
334
+ }
335
+ else if ( uri.indexOf('/googleplus/') > -1 )
336
+ {
337
+ source = 'googleplus';
338
+ }
339
+
340
+ pubdate = webmention.data.published_ts;
341
+ if ( ! pubdate && webmention.verified_date )
342
+ {
343
+ pubdate = webmention.verified_date;
344
+ }
345
+ if ( pubdate )
346
+ {
347
+ pubdate = (new Date(pubdate)).getTime();
348
+ }
349
+
350
+ webmention_object = {
351
+ id: webmention.id,
352
+ url: uri,
353
+ source: source,
354
+ pubdate: pubdate,
355
+ raw: webmentions[i]
356
+ };
357
+
358
+ if ( 'author' in webmention.data )
359
+ {
360
+ webmention_object.author = webmentions[i].data.author;
361
+ }
362
+
363
+ type = webmentions[i].activity.type;
364
+ if ( ! type )
365
+ {
366
+ if ( source == 'googleplus' )
367
+ {
368
+ if ( uri.indexOf('/like/') > -1 )
369
+ {
370
+ type = 'like';
371
+ }
372
+ else if ( uri.indexOf( '/repost/' ) > -1 )
373
+ {
374
+ type = 'repost';
375
+ }
376
+ else if ( uri.indexOf( '/comment/' ) > -1 )
377
+ {
378
+ type = 'reply';
379
+ }
380
+ else
381
+ {
382
+ type = 'link';
383
+ }
384
+ }
385
+ else
386
+ {
387
+ type = 'post';
388
+ }
389
+ }
390
+ webmention_object.type = type;
391
+
392
+ // Posts
393
+ title = false;
394
+ if ( type == 'post' )
395
+ {
396
+ readWebPage( uri, function( html_source ){
397
+ if ( html_source )
398
+ {
399
+ updateTitle( webmention_object.id, uri, html_source );
400
+ }
401
+ });
402
+ }
403
+
404
+ content = webmention.data.content;
405
+ if ( type != 'post' && type != 'reply' && type != 'link' )
406
+ {
407
+ content = webmention.activity.sentence_html;
408
+ }
409
+ webmention_object.content = content;
410
+
411
+ // replace the existing webmention
412
+ webmentions[i] = webmention_object;
413
+ }
414
+
415
+ // console.log( 'added metadata to', webmentions.length, 'webmentions' );
416
+ return webmentions;
417
+ }
418
+
419
+ // Async update of the title
420
+ function updateTitle( webmention_id, url, html_source )
421
+ {
422
+ var $webmention = document.querySelector( '#webmention-' + webmention_id ),
423
+ $current_title = $webmention.querySelector( '.webmention__title' ),
424
+ $page = document.createElement('html'),
425
+ title = '',
426
+ $link_title,
427
+ $title,
428
+ $h1;
429
+
430
+ $page.innerHTML = html_source;
431
+ $title = $page.querySelector('title');
432
+ $h1 = $page.querySelector('h1');
433
+
434
+ if ( $current_title.length < 0 )
435
+ {
436
+ $current_title = $webmention.querySelector( '.webmention__content' );
437
+ }
438
+
439
+ if ( $current_title.length > 0 )
440
+ {
441
+ if ( $title.length > 0 )
442
+ {
443
+ title = $title.innerText;
444
+ }
445
+ else
446
+ {
447
+ if ( $h1.length > 0 )
448
+ {
449
+ title = $h1.innerHTML;
450
+ }
451
+ else
452
+ {
453
+ title = 'No title available';
454
+ }
455
+ }
456
+
457
+ if ( title )
458
+ {
459
+ // cleanup
460
+ title = title.replace( /<\/?[^>]+?>}/, '' );
461
+ $link_title = document.createElement('a');
462
+ $link_title.href = uri;
463
+ $link_title.appendChild( document.createTextNode( title ) );
464
+ // replace title contents
465
+ $current_title.innerHTML = $link_title.outerHTML;
466
+ }
467
+ }
468
+ }
469
+
470
+ // Synchromous XHR proxied through whateverorigin.org
471
+ function readWebPage( uri, callback )
472
+ {
473
+ if ( 'XMLHttpRequest' in window )
474
+ {
475
+ var XHR = new XMLHttpRequest();
476
+ readWebPage = function( uri, callback ){
477
+ var done = false;
478
+ uri = '//whateverorigin.org/get?url=' + encodeURIComponent( uri );
479
+ XHR.onreadystatechange = function() {
480
+ if ( this.readyState == 4 && ! done ) {
481
+ done = true;
482
+ callback( XHR.responseText );
483
+ }
484
+ };
485
+ xhr.onabort = function() {
486
+ if ( ! done )
487
+ {
488
+ done = true;
489
+ callback( false );
490
+ }
491
+ };
492
+ XHR.onerror = XHR.onabort;
493
+ XHR.open( 'GET', uri );
494
+ XHR.send( null );
495
+ };
496
+ }
497
+ else
498
+ {
499
+ readWebPage = function( uri, callback ){
500
+ callback( false );
501
+ };
502
+ }
503
+ return readWebPage( uri, callback );
504
+ }
505
+
506
+ // init
507
+ collectTemplates();
508
+ collectExistingWebmentions();
509
+ identifyWebmentionCollections();
510
+
511
+ }(this, this.document));
@@ -0,0 +1,33 @@
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 ( ! window.location.origin )
20
+ {
21
+ window.location.origin = window.location.protocol + '//' + window.location.host;
22
+ }
23
+
24
+ // http://tokenposts.blogspot.com.au/2012/04/javascript-objectkeys-browser.html
25
+ if (!Object.keys) Object.keys = function(o) {
26
+ if (o !== Object(o))
27
+ throw new TypeError('Object.keys called on a non-object');
28
+ var k=[],p;
29
+ for (p in o) if (Object.prototype.hasOwnProperty.call(o,p)) k.push(p);
30
+ return k;
31
+ };
32
+
33
+ }(this,this.document));