diff --git a/assets/js/webmention.js b/assets/js/webmention.js new file mode 100644 index 0000000..fc87fd8 --- /dev/null +++ b/assets/js/webmention.js @@ -0,0 +1,342 @@ +/* webmention.js + +Simple thing for embedding webmentions from webmention.io into a page, client-side. + +(c)2018-2020 fluffy (http://beesbuzz.biz) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +GitHub repo (for latest released versions, issue tracking, etc.): + + https://github.com/PlaidWeb/webmention.js + +Basic usage: + + +
+ +Allowed parameters: + + page-url: + + The base URL to use for this page. Defaults to window.location + + add-urls: + + Additional URLs to check, separated by |s + + id: + + The HTML ID for the object to fill in with the webmention data. + Defaults to "webmentions" + + wordcount: + + The maximum number of words to render in reply mentions. + + max-webmentions: + + The maximum number of mentions to retrieve. Defaults to 30. + + prevent-spoofing: + + By default, Webmentions render using the mf2 'url' element, which plays + nicely with webmention bridges (such as brid.gy and telegraph) + but allows certain spoofing attacks. If you would like to prevent + spoofing, set this to a non-empty string (e.g. "true"). + + sort-by: + + What to order the responses by; defaults to 'published'. See + https://github.com/aaronpk/webmention.io#api + + sort-dir: + + The order to sort the responses by; defaults to 'up' (i.e. oldest + first). See https://github.com/aaronpk/webmention.io#api + + comments-are-reactions: + + If set to a non-empty string (e.g. "true"), will display comment-type responses + (replies/mentions/etc.) as being part of the reactions + (favorites/bookmarks/etc.) instead of in a separate comment list. + +A more detailed example: + + + +*/ + + +(function () { + "use strict"; + + function getCfg(key, dfl) { + return document.currentScript.getAttribute("data-" + key) || dfl; + } + + var refurl = getCfg('page-url', + window.location.href.replace(/#.*$/, '')); + var addurls = getCfg('add-urls', undefined); + var containerID = getCfg('id', "webmentions"); + var textMaxWords = getCfg('wordcount'); + var maxWebmentions = getCfg('max-webmentions', 30); + var mentionSource = getCfg('prevent-spoofing') ? 'wm-source' : 'url'; + var sortBy = getCfg('sort-by', 'published'); + var sortDir = getCfg('sort-dir', 'up'); + var commentsAreReactions = getCfg('comments-are-reactions'); + + var reactTitle = { + 'in-reply-to': 'replied', + 'like-of': 'liked', + 'repost-of': 'reposted', + 'bookmark-of': 'bookmarked', + 'mention-of': 'mentioned', + 'rsvp': 'RSVPed', + 'follow-of': 'followed' + }; + + var reactEmoji = { + 'in-reply-to': '💬', + 'like-of': '❤️', + 'repost-of': '🔄', + 'bookmark-of': '⭐️', + 'mention-of': '💬', + 'rsvp': '📅', + 'follow-of': '🐜' + }; + + var rsvpEmoji = { + 'yes': '✅', + 'no': '❌', + 'interested': '💡', + 'maybe': '💭' + }; + + function entities(text) { + return text.replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + } + + function reactImage(r, isComment) { + var who = entities((r.author && r.author.name) + ? r.author.name + : r.url.split('/')[2]); + var response = reactTitle[r['wm-property']] || 'reacted'; + if (!isComment && r.content && r.content.text) { + response += ": " + extractComment(r); + } + var html = ''; + if (r.author && r.author.photo) { + html += ''; + } + html += (reactEmoji[r['wm-property']] || '💥'); + if (r.rsvp && rsvpEmoji[r.rsvp]) { + html += '' + rsvpEmoji[r.rsvp] + ''; + } + html += ''; + + return html; + } + + // strip the protocol off a URL + function stripurl(url) { + return url.substr(url.indexOf('//')); + } + + // Deduplicate multiple mentions from the same source URL + function dedupe(mentions) { + var filtered = []; + var seen = {}; + + mentions.forEach(function(r) { + // Strip off the protocol (i.e. treat http and https the same) + var source = stripurl(r.url); + if (!seen[source]) { + filtered.push(r); + seen[source] = true; + } + }); + + return filtered; + } + + function extractComment(c) { + var text = entities(c.content.text); + + if (textMaxWords) { + var words = text.replace(/\s+/g,' ') + .split(' ', textMaxWords + 1); + if (words.length > textMaxWords) { + words[textMaxWords - 1] += '…'; + words = words.slice(0, textMaxWords); + text = words.join(' '); + } + } + + return text; + } + + function formatComments(comments) { + var html = '