jekyll-webmention_io 2.1.0 → 2.2.0

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 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));