Cleaning scripts

This commit is contained in:
Fundor333
2025-08-28 00:42:01 +02:00
parent 3eabb3f99d
commit 935089abac
17 changed files with 657 additions and 344 deletions

View File

@@ -16,11 +16,11 @@ like: null
rsvp: null rsvp: null
bookmark: null bookmark: null
syndication: syndication:
- https://mastodon.social/@fundor333/115101269000557955 - https://mastodon.social/@fundor333/115101286930871373
comments: comments:
host: mastodon.social host: mastodon.social
username: fundor333 username: fundor333
id: '115101269000557955' id: '115101286930871373'
--- ---
Waiting for tomorrow when I am going to the PyData Event in Venice 🐍👨🏻‍💻🐍 Waiting for tomorrow when I am going to the PyData Event in Venice 🐍👨🏻‍💻🐍

File diff suppressed because one or more lines are too long

View File

@@ -1 +1,25 @@
[{"type": "entry", "author": {"type": "card", "name": "fundor333", "photo": "https://avatars.webmention.io/shiitake.us-east.host.bsky.network/745ae7c92d33ea40ee0a0cc07825d49dcf5f0375c9b77cf4404889a238e66f93.jpg", "url": "https://bsky.app/profile/fundor333.bsky.social"}, "url": "https://bsky.app/profile/did:plc:u7piwonv4s27ysugjaa6im2q/post/3lxfbpfjmo422", "published": "2025-08-27T14:09:19+00:00", "wm-received": "2025-08-27T14:51:03Z", "wm-id": 1933884, "wm-source": "https://bsky.brid.gy/convert/web/at://did:plc:u7piwonv4s27ysugjaa6im2q/app.bsky.feed.post/3lxfbpfjmo422%23bridgy-fed-create", "wm-target": "https://fundor333.com/micro/2025/08/pydata-venezia-2025/?utm_source=fundor333.com&utm_medium=jsonfeed&utm_campaign=blogging&ref=fundor333feed.com", "wm-protocol": "webmention", "content": {"html": "Waiting for tomorrow when I am going to the PyData Event in Venice ????????????\u200d???????? [<a href=\"https://www.meetup.com/pydata-venice/events/310339068/?eventOrigin=home_page_upcoming_events%24all\">\u2026] https://fundor333.com/micro/2025/08/pydata-venezia-2025/?utm_source=fundor333.com&amp;utm_medium=json</a><a href=\"https://fundor333.com/micro/2025/08/pydata-venezia-2025/?utm_source=fundor333.com&amp;utm_medium=jsonfeed&amp;utm_campaign=blogging&amp;ref=fundor333feed.com\">https://fundor333.com/micro/2025/08/pydata-venezia-2025/?utm_source=fundor333.com&amp;utm_medium=jsonfeed&amp;utm_campaign=blogging&amp;ref=fundor333feed.com</a><a href=\"https://bsky.app/search?q=%23pydatave\">ed&amp;utm_ca</a>m<a href=\"https://bsky.app/search?q=%23event\">paign=</a>b<a href=\"https://bsky.app/search?q=%23python\">logging</a>&amp;<a href=\"https://bsky.app/search?q=%23data\">ref=f</a>u<a href=\"https://bsky.app/search?q=%23pydata\">ndor333</a>f<a href=\"https://bsky.app/search?q=%23venice\">eed.com</a>", "text": "Waiting for tomorrow when I am going to the PyData Event in Venice ????????????\u200d???????? [\u2026] https://fundor333.com/micro/2025/08/pydata-venezia-2025/?utm_source=fundor333.com&utm_medium=jsonhttps://fundor333.com/micro/2025/08/pydata-venezia-2025/?utm_source=fundor333.com&utm_medium=jsonfeed&utm_campaign=blogging&ref=fundor333feed.comed&utm_campaign=blogging&ref=fundor333feed.com"}, "mention-of": "https://fundor333.com/micro/2025/08/pydata-venezia-2025/?utm_source=fundor333.com&utm_medium=jsonfeed&utm_campaign=blogging&ref=fundor333feed.com", "wm-property": "mention-of", "wm-private": false}] [
{
"type": "entry",
"author": {
"type": "card",
"name": "fundor333",
"photo": "https://avatars.webmention.io/shiitake.us-east.host.bsky.network/745ae7c92d33ea40ee0a0cc07825d49dcf5f0375c9b77cf4404889a238e66f93.jpg",
"url": "https://bsky.app/profile/fundor333.bsky.social"
},
"url": "https://bsky.app/profile/did:plc:u7piwonv4s27ysugjaa6im2q/post/3lxfbpfjmo422",
"published": "2025-08-27T14:09:19+00:00",
"wm-received": "2025-08-27T14:51:03Z",
"wm-id": 1933884,
"wm-source": "https://bsky.brid.gy/convert/web/at://did:plc:u7piwonv4s27ysugjaa6im2q/app.bsky.feed.post/3lxfbpfjmo422%23bridgy-fed-create",
"wm-target": "https://fundor333.com/micro/2025/08/pydata-venezia-2025/?utm_source=fundor333.com&utm_medium=jsonfeed&utm_campaign=blogging&ref=fundor333feed.com",
"wm-protocol": "webmention",
"content": {
"html": "Waiting for tomorrow when I am going to the PyData Event in Venice ????????????\u200d???????? [<a href=\"https://www.meetup.com/pydata-venice/events/310339068/?eventOrigin=home_page_upcoming_events%24all\">\u2026] https://fundor333.com/micro/2025/08/pydata-venezia-2025/?utm_source=fundor333.com&amp;utm_medium=json</a><a href=\"https://fundor333.com/micro/2025/08/pydata-venezia-2025/?utm_source=fundor333.com&amp;utm_medium=jsonfeed&amp;utm_campaign=blogging&amp;ref=fundor333feed.com\">https://fundor333.com/micro/2025/08/pydata-venezia-2025/?utm_source=fundor333.com&amp;utm_medium=jsonfeed&amp;utm_campaign=blogging&amp;ref=fundor333feed.com</a><a href=\"https://bsky.app/search?q=%23pydatave\">ed&amp;utm_ca</a>m<a href=\"https://bsky.app/search?q=%23event\">paign=</a>b<a href=\"https://bsky.app/search?q=%23python\">logging</a>&amp;<a href=\"https://bsky.app/search?q=%23data\">ref=f</a>u<a href=\"https://bsky.app/search?q=%23pydata\">ndor333</a>f<a href=\"https://bsky.app/search?q=%23venice\">eed.com</a>",
"text": "Waiting for tomorrow when I am going to the PyData Event in Venice ????????????\u200d???????? [\u2026] https://fundor333.com/micro/2025/08/pydata-venezia-2025/"
},
"mention-of": "https://fundor333.com/micro/2025/08/pydata-venezia-2025/",
"wm-property": "mention-of",
"wm-private": false
}
]

View File

@@ -1 +1,21 @@
[{"type": "entry", "author": {"type": "card", "name": "Jonathan Rogivue", "photo": "https://avatars.webmention.io/files.mastodon.social/6cb4d618935f059605596af59ea79931acdca17c7db823392c9499fe081649ed.png", "url": "https://mastodon.social/@jrovu"}, "url": "https://mastodon.social/@fundor333/115101286930871373#favorited-by-114691517400809872", "published": null, "wm-received": "2025-08-27T15:16:17Z", "wm-id": 1933894, "wm-source": "https://brid.gy/like/mastodon/@fundor333@mastodon.social/115101286930871373/114691517400809872", "wm-target": "https://fundor333.com/micro/2025/08/pydata-venezia-2025/?amp%3Butm_medium=jsonfeed&amp%3Butm_campaign=blogging&amp%3Bref=fundor333feed.com", "wm-protocol": "webmention", "like-of": "https://fundor333.com/micro/2025/08/pydata-venezia-2025/?amp%3Butm_medium=jsonfeed&amp%3Butm_campaign=blogging&amp%3Bref=fundor333feed.com", "wm-property": "like-of", "wm-private": false}] [
{
"type": "entry",
"author": {
"type": "card",
"name": "Jonathan Rogivue",
"photo": "https://avatars.webmention.io/files.mastodon.social/6cb4d618935f059605596af59ea79931acdca17c7db823392c9499fe081649ed.png",
"url": "https://mastodon.social/@jrovu"
},
"url": "https://mastodon.social/@fundor333/115101286930871373#favorited-by-114691517400809872",
"published": null,
"wm-received": "2025-08-27T15:16:17Z",
"wm-id": 1933894,
"wm-source": "https://brid.gy/like/mastodon/@fundor333@mastodon.social/115101286930871373/114691517400809872",
"wm-target": "https://fundor333.com/micro/2025/08/pydata-venezia-2025/",
"wm-protocol": "webmention",
"like-of": "https://fundor333.com/micro/2025/08/pydata-venezia-2025/",
"wm-property": "like-of",
"wm-private": false
}
]

View File

@@ -1 +1,21 @@
[{"type": "entry", "author": {"type": "card", "name": "Jonathan Rogivue", "photo": "https://avatars.webmention.io/files.mastodon.social/6cb4d618935f059605596af59ea79931acdca17c7db823392c9499fe081649ed.png", "url": "https://mastodon.social/@jrovu"}, "url": "https://mastodon.social/@fundor333/115101286930871373#reblogged-by-114691517400809872", "published": null, "wm-received": "2025-08-27T15:16:20Z", "wm-id": 1933896, "wm-source": "https://brid.gy/repost/mastodon/@fundor333@mastodon.social/115101286930871373/114691517400809872", "wm-target": "https://fundor333.com/micro/2025/08/pydata-venezia-2025/?amp%3Butm_medium=jsonfeed&amp%3Butm_campaign=blogging&amp%3Bref=fundor333feed.com", "wm-protocol": "webmention", "repost-of": "https://fundor333.com/micro/2025/08/pydata-venezia-2025/?amp%3Butm_medium=jsonfeed&amp%3Butm_campaign=blogging&amp%3Bref=fundor333feed.com", "wm-property": "repost-of", "wm-private": false}] [
{
"type": "entry",
"author": {
"type": "card",
"name": "Jonathan Rogivue",
"photo": "https://avatars.webmention.io/files.mastodon.social/6cb4d618935f059605596af59ea79931acdca17c7db823392c9499fe081649ed.png",
"url": "https://mastodon.social/@jrovu"
},
"url": "https://mastodon.social/@fundor333/115101286930871373#reblogged-by-114691517400809872",
"published": null,
"wm-received": "2025-08-27T15:16:20Z",
"wm-id": 1933896,
"wm-source": "https://brid.gy/repost/mastodon/@fundor333@mastodon.social/115101286930871373/114691517400809872",
"wm-target": "https://fundor333.com/micro/2025/08/pydata-venezia-2025/",
"wm-protocol": "webmention",
"repost-of": "https://fundor333.com/micro/2025/08/pydata-venezia-2025/",
"wm-property": "repost-of",
"wm-private": false
}
]

View File

@@ -1 +1,21 @@
[{"type": "entry", "author": {"type": "card", "name": "Programming Channel", "photo": "https://avatars.webmention.io/files.mastodon.social/53dcc6ece2e0abd79a8aa637b9109d33bab0fa02e6536db85fd6c18ebc662722.png", "url": "https://newsmast.community/@programming"}, "url": "https://mastodon.social/@fundor333/115101286930871373#reblogged-by-111653091517742065", "published": null, "wm-received": "2025-08-27T15:16:22Z", "wm-id": 1933897, "wm-source": "https://brid.gy/repost/mastodon/@fundor333@mastodon.social/115101286930871373/111653091517742065", "wm-target": "https://fundor333.com/micro/2025/08/pydata-venezia-2025/?amp%3Butm_medium=jsonfeed&amp%3Butm_campaign=blogging&amp%3Bref=fundor333feed.com", "wm-protocol": "webmention", "repost-of": "https://fundor333.com/micro/2025/08/pydata-venezia-2025/?amp%3Butm_medium=jsonfeed&amp%3Butm_campaign=blogging&amp%3Bref=fundor333feed.com", "wm-property": "repost-of", "wm-private": false}] [
{
"type": "entry",
"author": {
"type": "card",
"name": "Programming Channel",
"photo": "https://avatars.webmention.io/files.mastodon.social/53dcc6ece2e0abd79a8aa637b9109d33bab0fa02e6536db85fd6c18ebc662722.png",
"url": "https://newsmast.community/@programming"
},
"url": "https://mastodon.social/@fundor333/115101286930871373#reblogged-by-111653091517742065",
"published": null,
"wm-received": "2025-08-27T15:16:22Z",
"wm-id": 1933897,
"wm-source": "https://brid.gy/repost/mastodon/@fundor333@mastodon.social/115101286930871373/111653091517742065",
"wm-target": "https://fundor333.com/micro/2025/08/pydata-venezia-2025/",
"wm-protocol": "webmention",
"repost-of": "https://fundor333.com/micro/2025/08/pydata-venezia-2025/?amp%3Butm_medium=jsonfeed&amp%3Butm_campaign=blogging&amp%3Bref=fundor333feed.com",
"wm-property": "repost-of",
"wm-private": false
}
]

View File

@@ -1 +1,21 @@
[{"type": "entry", "author": {"type": "card", "name": "ZioN1k9", "photo": "https://avatars.webmention.io/files.mastodon.social/cff7c181721f7b6d2ac02f8fb12a44cbea1f5e6f9defce1401e7a158d9a1d80d.png", "url": "https://livellosegreto.it/@n1k9"}, "url": "https://mastodon.social/@fundor333/115101286930871373#reblogged-by-109094054789012545", "published": null, "wm-received": "2025-08-27T19:46:22Z", "wm-id": 1933981, "wm-source": "https://brid.gy/repost/mastodon/@fundor333@mastodon.social/115101286930871373/109094054789012545", "wm-target": "https://fundor333.com/micro/2025/08/pydata-venezia-2025/?amp%3Butm_medium=jsonfeed&amp%3Butm_campaign=blogging&amp%3Bref=fundor333feed.com", "wm-protocol": "webmention", "repost-of": "https://fundor333.com/micro/2025/08/pydata-venezia-2025/?amp%3Butm_medium=jsonfeed&amp%3Butm_campaign=blogging&amp%3Bref=fundor333feed.com", "wm-property": "repost-of", "wm-private": false}] [
{
"type": "entry",
"author": {
"type": "card",
"name": "ZioN1k9",
"photo": "https://avatars.webmention.io/files.mastodon.social/cff7c181721f7b6d2ac02f8fb12a44cbea1f5e6f9defce1401e7a158d9a1d80d.png",
"url": "https://livellosegreto.it/@n1k9"
},
"url": "https://mastodon.social/@fundor333/115101286930871373#reblogged-by-109094054789012545",
"published": null,
"wm-received": "2025-08-27T19:46:22Z",
"wm-id": 1933981,
"wm-source": "https://brid.gy/repost/mastodon/@fundor333@mastodon.social/115101286930871373/109094054789012545",
"wm-target": "https://fundor333.com/micro/2025/08/pydata-venezia-2025/",
"wm-protocol": "webmention",
"repost-of": "https://fundor333.com/micro/2025/08/pydata-venezia-2025/",
"wm-property": "repost-of",
"wm-private": false
}
]

View File

@@ -44,7 +44,7 @@
"date_published": "{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}", "date_published": "{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}",
"date_modified": "{{ .Lastmod.Format "2006-01-02T15:04:05Z07:00" }}", "date_modified": "{{ .Lastmod.Format "2006-01-02T15:04:05Z07:00" }}",
"id": "{{ .Permalink }}", "id": "{{ .Permalink }}",
"url": "{{ .Permalink }}?utm_source=fundor333.com&utm_medium=jsonfeed&utm_campaign=blogging&ref=fundor333feed.com", "url": "{{ .Permalink }}",
{{ with .Params.author -}} {{ with .Params.author -}}
"authors": [ "authors": [
{ {

View File

@@ -1,10 +1,9 @@
<script src="/js/jquery-3.7.1.min.js"></script>
<meta name="fediverse:creator" content="@fundor333@mastodon.social"> <meta name="fediverse:creator" content="@fundor333@mastodon.social">
<link rel="webmention" href="https://webmention.io/fundor333.com/webmention" /> <link rel="webmention" href="https://webmention.io/fundor333.com/webmention" />
<link rel="pingback" href="https://webmention.io/fundor333.com/xmlrpc" /> <link rel="pingback" href="https://webmention.io/fundor333.com/xmlrpc" />
<link rel="stylesheet" href="/css/webmention.css" />
<script src="https://cdn.jsdelivr.net/npm/anchor-js/anchor.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/anchor-js/anchor.min.js"></script>
<script src="https://kit.fontawesome.com/2f3b6e2e4c.js" crossorigin="anonymous"></script> <script src="https://kit.fontawesome.com/2f3b6e2e4c.js" crossorigin="anonymous"></script>

View File

@@ -1,27 +1,26 @@
<footer class="footer wrapper"> <footer class="footer wrapper">
<span class="footer_item"> </span> <span class="footer_item"> </span>
{{ partial "hcard" . }} {{ partial "hcard" . }}
<div class="footer_social-icons flex">
<div class="footer_social-icons flex"> {{- partial "socialIcons.html" site.Params.socialIcons -}}
{{- partial "socialIcons.html" site.Params.socialIcons -}} <p class="flex justify-center">
<p class="flex justify-center"> <a href='https://webring.xxiivv.com/#random' target='_blank'>
<a href='https://webring.xxiivv.com/#random' target='_blank'> <img loading="lazy" width=" 30" height="30" src='https://webring.xxiivv.com/icon.white.svg' />
<img loading="lazy" width=" 30" height="30" src='https://webring.xxiivv.com/icon.white.svg' /> </a>
</a> </p>
</p> <p>
<p> <a href="https://xn--sr8hvo.ws/previous"></a>
<a href="https://xn--sr8hvo.ws/previous"></a> <a href="https://xn--sr8hvo.ws">IndieWeb Webring</a>
<a href="https://xn--sr8hvo.ws">IndieWeb Webring</a> <a href="https://xn--sr8hvo.ws/next"></a>
<a href="https://xn--sr8hvo.ws/next"></a> </p>
</p> <div class="webring">
<div class="webring"> <webring-css site="https://fundor333.com"></webring-css>
<webring-css site="https://fundor333.com"></webring-css> <script src="https://djangowebring.com/static/webring.js"></script>
<script src="https://djangowebring.com/static/webring.js"></script> </div>
</div> </div>
</div> <small class="footer_copyright">
<small class="footer_copyright">
© {{ now.Format "2006" }} {{ .Site.Params.author.name }}. © {{ now.Format "2006" }} {{ .Site.Params.author.name }}.
{{ T "footer.disclaimer" | safeHTML }} {{ T "footer.disclaimer" | safeHTML }}
</small> </small>
@@ -29,7 +28,7 @@
{{- if .Site.Params.goToTop -}} {{- if .Site.Params.goToTop -}}
<a href="#" title="{{ T "footer.go_to_top" }}" id="totop"> <a href="#" title="{{ T "footer.go_to_top" }}" id="totop">
{{ partial "svgs/arrowUp.svg" (dict "height" 48 "width" 48) . }} {{ partial "svgs/arrowUp.svg" (dict "height" 48 "width" 48) . }}
</a> </a>
{{- end -}} {{- end -}}
@@ -51,15 +50,18 @@
</script> </script>
<script> <script>
$(window).on('load', function() {
// Seleziona tutte le immagini con la classe 'u-photo'
var images = $('img.u-photo');
$(window).load(function(){ // Itera su ogni immagine trovata
images.each(function() {
$.each($('u-photo'), function(){ // 'this' si riferisce all'elemento immagine corrente
var currentImage = $(this);
// Set the height, hard-style!
$(this).attr('height', $(this).height());
// Prende l'altezza calcolata e la imposta come attributo 'height' del tag
var imageHeight = currentImage.height();
currentImage.attr('height', imageHeight);
}); });
}); });
</script> </script>

View File

@@ -1,12 +1,15 @@
<section id="comments" class="article-content"> <section id="comments" class="article-content">
<p>With an account on the Fediverse or Mastodon, you can respond to this <a target="_blank" href="https://{{ .host }}/@{{ .username }}/{{ .id }}">post</a>. Since Mastodon is decentralized, you can use your existing account hosted by another Mastodon server or compatible platform if you don't have an account on this one. Known non-private replies are displayed below.</p> <p>With an account on the Fediverse or Mastodon, you can respond to this <a target="_blank" href="https://{{ .host }}/@{{ .username }}/{{ .id }}">post</a>.
<p>Learn how this is implemented <a target="_blank" class="link" href="https://carlschwan.eu/2020/12/29/adding-comments-to-your-static-blog-with-mastodon/">here.</a></p> Since Mastodon is decentralized, you can use your existing account hosted by another Mastodon server or compatible platform if you don't have an account on
this one. Known non-private replies are displayed below.</p>
<p>Learn how this is implemented <a target="_blank" class="link"
href="https://carlschwan.eu/2020/12/29/adding-comments-to-your-static-blog-with-mastodon/">here.</a></p>
<p id="mastodon-comments-list"></p> <p id="mastodon-comments-list"><button id="load-comment">Load comments</button></p>
<div id="comments-wrapper"> <div id="comments-wrapper">
<noscript><p>Loading comments relies on JavaScript. Try enabling JavaScript and reloading, or visit <a target="_blank" href="https://{{ .host }}/@{{ .username }}/{{ .id }}">the original post</a> on Mastodon.</p></noscript> <noscript><p>Loading comments relies on JavaScript. Try enabling JavaScript and reloading, or visit <a
href="https://{{ .host }}/@{{ .username }}/{{ .id }}">the original post</a> on Mastodon.</p></noscript>
</div> </div>
<noscript>You need JavaScript to view the comments.</noscript> <noscript>You need JavaScript to view the comments.</noscript>
<script src="/js/purify.min.js"></script> <script src="/js/purify.min.js"></script>
@@ -48,6 +51,7 @@
function loadComments() { function loadComments() {
let commentsWrapper = document.getElementById("comments-wrapper"); let commentsWrapper = document.getElementById("comments-wrapper");
document.getElementById("load-comment").innerHTML = "Loading";
fetch('https://{{ .host }}/api/v1/statuses/{{ .id }}/context') fetch('https://{{ .host }}/api/v1/statuses/{{ .id }}/context')
.then(function(response) { .then(function(response) {
return response.json(); return response.json();
@@ -185,6 +189,6 @@
} }
}); });
} }
document.addEventListener("DOMContentLoaded", loadComments); document.getElementById("load-comment").addEventListener("click", loadComments);
</script> </script>
</section> </section>

6
package-lock.json generated
View File

@@ -241,9 +241,9 @@
} }
}, },
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.5.208", "version": "1.5.210",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.208.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.210.tgz",
"integrity": "sha512-ozZyibehoe7tOhNaf16lKmljVf+3npZcJIEbJRVftVsmAg5TeA1mGS9dVCZzOwr2xT7xK15V0p7+GZqSPgkuPg==", "integrity": "sha512-20kSVv1tyNBN2VFsjCIJZfyvxqo7ylHPrJLME040f/030lzNMA7uQNpxtqJjWSNpccD8/2sqe53EAjrFPvQmjw==",
"license": "ISC" "license": "ISC"
}, },
"node_modules/emoji-regex": { "node_modules/emoji-regex": {

2
static/js/jquery-3.7.1.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -98,124 +98,134 @@ A more detailed example:
// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt // @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt
(function () { (function () {
"use strict"; "use strict";
// Shim i18next // Shim i18next
window.i18next = window.i18next || { window.i18next = window.i18next || {
t: function t(/** @type {string} */key) { return key; } t: function t(/** @type {string} */ key) {
} return key;
const t = window.i18next.t.bind(window.i18next); },
};
const t = window.i18next.t.bind(window.i18next);
/** /**
* Read the configuration value. * Read the configuration value.
* *
* @param {string} key The configuration key. * @param {string} key The configuration key.
* @param {string} dfl The default value. * @param {string} dfl The default value.
* @returns {string} * @returns {string}
*/ */
function getCfg(key, dfl) { function getCfg(key, dfl) {
return document.currentScript.getAttribute("data-" + key) || dfl; return (
} document.currentScript.getAttribute("data-" + key) ||
dfl
);
}
const refurl = getCfg("page-url", window.location.href.replace(/#.*$/, "")); const refurl = getCfg(
const addurls = getCfg("add-urls", undefined); "page-url",
const containerID = getCfg("id", "webmentions"); window.location.href.replace(/#.*$/, "")
/** @type {Number} */ );
const textMaxWords = getCfg("wordcount"); const addurls = getCfg("add-urls", undefined);
const maxWebmentions = getCfg("max-webmentions", 30); const containerID = getCfg("id", "webmentions");
const mentionSource = getCfg("prevent-spoofing") ? "wm-source" : "url"; /** @type {Number} */
const sortBy = getCfg("sort-by", "published"); const textMaxWords = getCfg("wordcount");
const sortDir = getCfg("sort-dir", "up"); const maxWebmentions = getCfg("max-webmentions", 30);
/** @type {boolean} */ const mentionSource = getCfg("prevent-spoofing") ? "wm-source" : "url";
const commentsAreReactions = getCfg("comments-are-reactions", false); const sortBy = getCfg("sort-by", "published");
const sortDir = getCfg("sort-dir", "up");
/** @type {boolean} */
const commentsAreReactions = getCfg("comments-are-reactions", false);
/** /**
* @typedef MentionType * @typedef MentionType
* @type {"in-reply-to"|"like-of"|"repost-of"|"bookmark-of"|"mention-of"|"rsvp"|"follow-of"} * @type {"in-reply-to"|"like-of"|"repost-of"|"bookmark-of"|"mention-of"|"rsvp"|"follow-of"}
*/ */
/** /**
* Maps a reaction to a hover title. * Maps a reaction to a hover title.
* *
* @type {Record<MentionType, string>} * @type {Record<MentionType, string>}
*/ */
const reactTitle = { const reactTitle = {
"in-reply-to": t("replied"), "in-reply-to": t("replied"),
"like-of": t("liked"), "like-of": t("liked"),
"repost-of": t("reposted"), "repost-of": t("reposted"),
"bookmark-of": t("bookmarked"), "bookmark-of": t("bookmarked"),
"mention-of": t("mentioned"), "mention-of": t("mentioned"),
"rsvp": t("RSVPed"), rsvp: t("RSVPed"),
"follow-of": t("followed") "follow-of": t("followed"),
}; };
/** /**
* Maps a reaction to an emoji. * Maps a reaction to an emoji.
* *
* @type {Record<MentionType, string>} * @type {Record<MentionType, string>}
*/ */
const reactEmoji = { const reactEmoji = {
"in-reply-to": "💬", "in-reply-to": "💬",
"like-of": "❤️", "like-of": "❤️",
"repost-of": "🔄", "repost-of": "🔄",
"bookmark-of": "⭐️", "bookmark-of": "⭐️",
"mention-of": "💬", "mention-of": "💬",
"rsvp": "📅", rsvp: "📅",
"follow-of": "🐜" "follow-of": "🐜",
}; };
/** /**
* @typedef RSVPEmoji * @typedef RSVPEmoji
* @type {"yes"|"no"|"interested"|"maybe"|null} * @type {"yes"|"no"|"interested"|"maybe"|null}
*/ */
/** /**
* Maps a RSVP to an emoji. * Maps a RSVP to an emoji.
* *
* @type {Record<RSVPEmoji, string>} * @type {Record<RSVPEmoji, string>}
*/ */
const rsvpEmoji = { const rsvpEmoji = {
"yes": "✅", yes: "✅",
"no": "❌", no: "❌",
"interested": "💡", interested: "💡",
"maybe": "💭" maybe: "💭",
}; };
/** /**
* HTML escapes the string. * HTML escapes the string.
* *
* @param {string} text The string to be escaped. * @param {string} text The string to be escaped.
* @returns {string} * @returns {string}
*/ */
function entities(text) { function entities(text) {
return text.replace(/[&<>"]/g, (tag) => ({ return text.replace(
'&': '&amp;', /[&<>"]/g,
'<': '&lt;', (tag) =>
'>': '&gt;', ({
'"': '&quot;', "&": "&amp;",
}[tag] || tag)); "<": "&lt;",
} ">": "&gt;",
'"': "&quot;",
}[tag] || tag)
);
}
/** /**
* Creates the markup for an reaction image. * Creates the markup for an reaction image.
* *
* @param {Reaction} r * @param {Reaction} r
* @param {boolean} isComment * @param {boolean} isComment
* @returns {string} * @returns {string}
*/ */
function reactImage(r, isComment) { function reactImage(r, isComment) {
const who = entities( const who = entities(r.author?.name || r.url.split("/")[2]);
r.author?.name || r.url.split("/")[2] /** @type {string} */
); let response = reactTitle[r["wm-property"]] || t("reacted");
/** @type {string} */ if (!isComment && r.content && r.content.text) {
let response = reactTitle[r["wm-property"]] || t("reacted"); response += ": " + extractComment(r);
if (!isComment && r.content && r.content.text) { }
response += ": " + extractComment(r);
}
let authorPhoto = ''; let authorPhoto = "";
if (r.author && r.author.photo) { if (r.author && r.author.photo) {
authorPhoto = ` authorPhoto = `
<img <img
src="${entities(r.author.photo)}" src="${entities(r.author.photo)}"
loading="lazy" loading="lazy"
@@ -223,22 +233,22 @@ A more detailed example:
alt="${who}" alt="${who}"
> >
`; `;
} else { } else {
authorPhoto = ` authorPhoto = `
<img <img
class="missing" class="missing"
src="data:image/webp;base64,UklGRkoCAABXRUJQVlA4TD4CAAAvP8APAIV0WduUOLr/m/iqY6SokDJSMD5xYX23SQizRsVdZmIj/f6goYUbiOj/BED7MOPReuBNT3vBesSzIex+SeqMFFkjebFmzH3S7POxDSJ1yaCbCmMnS2R46cRMPyQLw4GBK4esdK60pYwsZakecUCl5zsHv/5cPH08nx9/7i6rEEVCg2hR8VSd30PxMZpVoJZQO6Dixgg6X5oKFCmlVHIDmmMFShWumAXgCuyqVN8hHff/k+9fj8+ei7BVjpxBmZCUJv+6DhWGZwWvs+UoLHFCKsPYpfJtIcEXBTopEEsKwedZUv4ku1FZErKULLyQwFGgnmTs2vBD5qu44xwnG9uyjgrFOd+KRVlXyQfwQlauydaU6AVI7OjKXLUEqNtxJBmQegNDZgV7lxxqYMOMrDyC1NdAGbdiH9Ij0skjG+oTyfO0lmjdgvoH8iIgreuBMRYLSH+R3sAztXgL+XfS7E2bmfo6gnS0TrpnzHT7kL+skj7PgHuBwv/zpN8LDLQg7zfJZLBubMKnyeh6ZGyfDEfc2LYpnlUtG7JqsSHq1WoASbUS4KVaLwB8be5mfsGMDwBcm5VxbuxWxx3nkFanB6lYqsqSkOGkKicoDvXsneR7BkKU7DtaEuT7+pxBGVwx+9gVyqf2pVA9sC2CsmjZ1RJqEJHS4Tj/pCcS0JoyBYOsB91Xjh3OFfQPQhvCAYyeLJlaOoFp0XNNuD0BC8exr8uPx7D1JWkwFdZIXmD3MOPReuDNzHjBesSzIbQD" src="data:image/webp;base64,UklGRkoCAABXRUJQVlA4TD4CAAAvP8APAIV0WduUOLr/m/iqY6SokDJSMD5xYX23SQizRsVdZmIj/f6goYUbiOj/BED7MOPReuBNT3vBesSzIex+SeqMFFkjebFmzH3S7POxDSJ1yaCbCmMnS2R46cRMPyQLw4GBK4esdK60pYwsZakecUCl5zsHv/5cPH08nx9/7i6rEEVCg2hR8VSd30PxMZpVoJZQO6Dixgg6X5oKFCmlVHIDmmMFShWumAXgCuyqVN8hHff/k+9fj8+ei7BVjpxBmZCUJv+6DhWGZwWvs+UoLHFCKsPYpfJtIcEXBTopEEsKwedZUv4ku1FZErKULLyQwFGgnmTs2vBD5qu44xwnG9uyjgrFOd+KRVlXyQfwQlauydaU6AVI7OjKXLUEqNtxJBmQegNDZgV7lxxqYMOMrDyC1NdAGbdiH9Ij0skjG+oTyfO0lmjdgvoH8iIgreuBMRYLSH+R3sAztXgL+XfS7E2bmfo6gnS0TrpnzHT7kL+skj7PgHuBwv/zpN8LDLQg7zfJZLBubMKnyeh6ZGyfDEfc2LYpnlUtG7JqsSHq1WoASbUS4KVaLwB8be5mfsGMDwBcm5VxbuxWxx3nkFanB6lYqsqSkOGkKicoDvXsneR7BkKU7DtaEuT7+pxBGVwx+9gVyqf2pVA9sC2CsmjZ1RJqEJHS4Tj/pCcS0JoyBYOsB91Xjh3OFfQPQhvCAYyeLJlaOoFp0XNNuD0BC8exr8uPx7D1JWkwFdZIXmD3MOPReuDNzHjBesSzIbQD"
alt="${who}$" alt="${who}$"
> >
`; `;
} }
let rsvp = ''; let rsvp = "";
if (r.rsvp && rsvpEmoji[r.rsvp]) { if (r.rsvp && rsvpEmoji[r.rsvp]) {
rsvp = `<sub>${rsvpEmoji[r.rsvp]}</sub>`; rsvp = `<sub>${rsvpEmoji[r.rsvp]}</sub>`;
} }
return` return `
<a <a
class="reaction" class="reaction"
rel="nofollow ugc" rel="nofollow ugc"
@@ -246,223 +256,227 @@ A more detailed example:
href="${r[mentionSource]}" href="${r[mentionSource]}"
> >
${authorPhoto} ${authorPhoto}
${(reactEmoji[r['wm-property']] || '💥')} ${reactEmoji[r["wm-property"]] || "💥"}
${rsvp} ${rsvp}
</a> </a>
`; `;
} }
/** /**
* Strip the protocol off a URL. * Strip the protocol off a URL.
* *
* @param {string} url The URL to strip protocol off. * @param {string} url The URL to strip protocol off.
* @returns {string} * @returns {string}
*/ */
function stripurl(url) { function stripurl(url) {
return url.substr(url.indexOf('//')); return url.substr(url.indexOf("//"));
} }
/** /**
* Deduplicate multiple mentions from the same source URL. * Deduplicate multiple mentions from the same source URL.
* *
* @param {Array<Reaction>} mentions Mentions of the source URL. * @param {Array<Reaction>} mentions Mentions of the source URL.
* @return {Array<Reaction>} * @return {Array<Reaction>}
*/ */
function dedupe(mentions) { function dedupe(mentions) {
/** @type {Array<Reaction>} */ /** @type {Array<Reaction>} */
const filtered = []; const filtered = [];
/** @type {Record<string, boolean>} */ /** @type {Record<string, boolean>} */
const seen = {}; const seen = {};
mentions.forEach(function(r) { mentions.forEach(function (r) {
// Strip off the protocol (i.e. treat http and https the same) // Strip off the protocol (i.e. treat http and https the same)
const source = stripurl(r.url); const source = stripurl(r.url);
if (!seen[source]) { if (!seen[source]) {
filtered.push(r); filtered.push(r);
seen[source] = true; seen[source] = true;
} }
}); });
return filtered; return filtered;
} }
/** /**
* Extract comments from a reaction. * Extract comments from a reaction.
* *
* @param {Reactions} c * @param {Reactions} c
* @returns string * @returns string
*/ */
function extractComment(c) { function extractComment(c) {
let text = entities(c.content.text); let text = entities(c.content.text);
if (textMaxWords) { if (textMaxWords) {
let words = text.replace(/\s+/g,' ').split(' ', textMaxWords + 1); let words = text
if (words.length > textMaxWords) { .replace(/\s+/g, " ")
words[textMaxWords - 1] += '&hellip;'; .split(" ", textMaxWords + 1);
words = words.slice(0, textMaxWords); if (words.length > textMaxWords) {
text = words.join(' '); words[textMaxWords - 1] += "&hellip;";
} words = words.slice(0, textMaxWords);
} text = words.join(" ");
}
}
return text; return text;
} }
/** /**
* Format comments as HTML. * Format comments as HTML.
* *
* @param {Array<Reaction>} comments The comments to format. * @param {Array<Reaction>} comments The comments to format.
* @returns string * @returns string
*/ */
function formatComments(comments) { function formatComments(comments) {
const headline = `<h3>${t('Responses')}</h3>`; const headline = `<h2>${t("Responses")}</h2>`;
const markup = comments const markup = comments
.map((c) => { .map((c) => {
const image = reactImage(c, true); const image = reactImage(c, true);
let source = entities(c.url.split('/')[2]); let source = entities(c.url.split("/")[2]);
if (c.author && c.author.name) { if (c.author && c.author.name) {
source = entities(c.author.name); source = entities(c.author.name);
} }
const link = `<a class="source" rel="nofollow ugc" href="${c[mentionSource]}">${source}</a>`; const link = `<a class="source" rel="nofollow ugc" href="${c[mentionSource]}">${source}</a>`;
let linkclass = "name"; let linkclass = "name";
let linktext = `(${t("mention")})`; let linktext = `(${t("mention")})`;
if (c.name) { if (c.name) {
linkclass = "name"; linkclass = "name";
linktext = entities(c.name); linktext = entities(c.name);
} else if (c.content && c.content.text) { } else if (c.content && c.content.text) {
linkclass = "text"; linkclass = "text";
linktext = extractComment(c); linktext = extractComment(c);
} }
const type = `<span class="${linkclass}">${linktext}</span>`; const type = `<span class="${linkclass}">${linktext}</span>`;
return `<li>${image} ${link} ${type}</li>`; return `<li>${image} ${link} ${type}</li>`;
}) })
.join(''); .join("");
return ` return `
${headline} ${headline}
<ul class="comments">${markup}</ul> <ul class="comments">${markup}</ul>
`; `;
} }
/** /**
* @typedef {Object} Reaction * @typedef {Object} Reaction
* @property {string} url * @property {string} url
* @property {Object?} author * @property {Object?} author
* @property {string?} author.name * @property {string?} author.name
* @property {string?} author.photo * @property {string?} author.photo
* @property {Object?} content * @property {Object?} content
* @property {string?} content.text * @property {string?} content.text
* @property {RSVPEmoji?} rsvp * @property {RSVPEmoji?} rsvp
* @property {MentionType?} wm-property * @property {MentionType?} wm-property
* @property {string?} wm-source * @property {string?} wm-source
*/ */
/** /**
* Formats a list of reactions as HTML. * Formats a list of reactions as HTML.
* *
* @param {Array<Reaction>} reacts List of reactions to format * @param {Array<Reaction>} reacts List of reactions to format
* @returns string * @returns string
*/ */
function formatReactions(reacts) { function formatReactions(reacts) {
const headline = `<h3>${t('Reactions')}</h3>`; const headline = `<h2>${t("Reactions")}</h2>`;
const markup = reacts.map((r) => reactImage(r)).join(''); const markup = reacts.map((r) => reactImage(r)).join("");
return ` return `
${headline} ${headline}
<ul class="reacts">${markup}</ul> <ul class="reacts">${markup}</ul>
`; `;
} }
/** /**
* @typedef WebmentionResponse * @typedef WebmentionResponse
* @type {Object} * @type {Object}
* @property {Array<Reaction>} children * @property {Array<Reaction>} children
*/ */
/** /**
* Register event listener. * Register event listener.
*/ */
window.addEventListener("load", async function () { window.addEventListener("load", async function () {
const container = document.getElementById(containerID); const container = document.getElementById(containerID);
if (!container) { if (!container) {
// no container, so do nothing // no container, so do nothing
return; return;
} }
const pages = [stripurl(refurl)]; const pages = [stripurl(refurl)];
if (!!addurls) { if (!!addurls) {
addurls.split('|').forEach(function (url) { addurls.split("|").forEach(function (url) {
pages.push(stripurl(url)); pages.push(stripurl(url));
}); });
} }
let apiURL = `https://webmention.io/api/mentions.jf2?per-page=${maxWebmentions}&sort-by=${sortBy}&sort-dir=${sortDir}`; let apiURL = `https://webmention.io/api/mentions.jf2?per-page=${maxWebmentions}&sort-by=${sortBy}&sort-dir=${sortDir}`;
pages.forEach(function (path) { pages.forEach(function (path) {
apiURL += `&target[]=${encodeURIComponent('http:' + path)}&target[]=${encodeURIComponent('https:' + path)}`; apiURL += `&target[]=${encodeURIComponent(
}); "http:" + path
)}&target[]=${encodeURIComponent("https:" + path)}`;
});
/** @type {WebmentionResponse} */ /** @type {WebmentionResponse} */
let json = {}; let json = {};
try { try {
const response = await window.fetch(apiURL); const response = await window.fetch(apiURL);
if (response.status >= 200 && response.status < 300) { if (response.status >= 200 && response.status < 300) {
json = await response.json(); json = await response.json();
} else { } else {
console.error("Could not parse response"); console.error("Could not parse response");
new Error(response.statusText); new Error(response.statusText);
} }
} catch(error) { } catch (error) {
// Purposefully not escalate further, i.e. no UI update // Purposefully not escalate further, i.e. no UI update
console.error("Request failed", error); console.error("Request failed", error);
} }
/** @type {Array<Reaction>} */ /** @type {Array<Reaction>} */
let comments = []; let comments = [];
/** @type {Array<Reaction>} */ /** @type {Array<Reaction>} */
const collects = []; const collects = [];
if (commentsAreReactions) { if (commentsAreReactions) {
comments = collects; comments = collects;
} }
/** @type {Record<MentionType, Array<Reaction>>} */ /** @type {Record<MentionType, Array<Reaction>>} */
const mapping = { const mapping = {
"in-reply-to": comments, "in-reply-to": comments,
"like-of": collects, "like-of": collects,
"repost-of": collects, "repost-of": collects,
"bookmark-of": collects, "bookmark-of": collects,
"follow-of": collects, "follow-of": collects,
"mention-of": comments, "mention-of": comments,
"rsvp": comments rsvp: comments,
}; };
json.children.forEach(function(child) { json.children.forEach(function (child) {
// Map each mention into its respective container // Map each mention into its respective container
const store = mapping[child['wm-property']]; const store = mapping[child["wm-property"]];
if (store) { if (store) {
store.push(child); store.push(child);
} }
}); });
// format the comment-type things // format the comment-type things
let formattedComments = ''; let formattedComments = "";
if (comments.length > 0 && comments !== collects) { if (comments.length > 0 && comments !== collects) {
formattedComments = formatComments(dedupe(comments)); formattedComments = formatComments(dedupe(comments));
} }
// format the other reactions // format the other reactions
let reactions = ''; let reactions = "";
if (collects.length > 0) { if (collects.length > 0) {
reactions = formatReactions(dedupe(collects)); reactions = formatReactions(dedupe(collects));
} }
container.innerHTML = `${formattedComments}${reactions}`; container.innerHTML = `${formattedComments}${reactions}`;
}); });
}()); })();
// End-of-file marker for LibreJS // End-of-file marker for LibreJS
// @license-end // @license-end

View File

@@ -1,3 +1,4 @@
// @ts-nocheck
// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt // @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt
!function(){"use strict";window.i18next=window.i18next||{t:function(n){return n}};const n=window.i18next.t.bind(window.i18next);function t(n,t){return document.currentScript.getAttribute("data-"+n)||t}const e=t("page-url",window.location.href.replace(/#.*$/,"")),o=t("add-urls",void 0),r=t("id","webmentions"),s=t("wordcount"),i=t("max-webmentions",30),l=t("prevent-spoofing")?"wm-source":"url",a=t("sort-by","published"),c=t("sort-dir","up"),u=t("comments-are-reactions",!1),p={"in-reply-to":n("replied"),"like-of":n("liked"),"repost-of":n("reposted"),"bookmark-of":n("bookmarked"),"mention-of":n("mentioned"),rsvp:n("RSVPed"),"follow-of":n("followed")},f={"in-reply-to":"💬","like-of":"❤️","repost-of":"🔄","bookmark-of":"⭐️","mention-of":"💬",rsvp:"📅","follow-of":"🐜"},m={yes:"✅",no:"❌",interested:"💡",maybe:"💭"};function d(n){return n.replace(/[&<>"]/g,(n=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;"}[n]||n)))}function w(t,e){const o=d(t.author?.name||t.url.split("/")[2]);let r=p[t["wm-property"]]||n("reacted");!e&&t.content&&t.content.text&&(r+=": "+x(t));let s="";s=t.author&&t.author.photo?`\n <img\n src="${d(t.author.photo)}"\n loading="lazy"\n decoding="async"\n alt="${o}"\n >\n `:`\n <img\n class="missing"\n src="data:image/webp;base64,UklGRkoCAABXRUJQVlA4TD4CAAAvP8APAIV0WduUOLr/m/iqY6SokDJSMD5xYX23SQizRsVdZmIj/f6goYUbiOj/BED7MOPReuBNT3vBesSzIex+SeqMFFkjebFmzH3S7POxDSJ1yaCbCmMnS2R46cRMPyQLw4GBK4esdK60pYwsZakecUCl5zsHv/5cPH08nx9/7i6rEEVCg2hR8VSd30PxMZpVoJZQO6Dixgg6X5oKFCmlVHIDmmMFShWumAXgCuyqVN8hHff/k+9fj8+ei7BVjpxBmZCUJv+6DhWGZwWvs+UoLHFCKsPYpfJtIcEXBTopEEsKwedZUv4ku1FZErKULLyQwFGgnmTs2vBD5qu44xwnG9uyjgrFOd+KRVlXyQfwQlauydaU6AVI7OjKXLUEqNtxJBmQegNDZgV7lxxqYMOMrDyC1NdAGbdiH9Ij0skjG+oTyfO0lmjdgvoH8iIgreuBMRYLSH+R3sAztXgL+XfS7E2bmfo6gnS0TrpnzHT7kL+skj7PgHuBwv/zpN8LDLQg7zfJZLBubMKnyeh6ZGyfDEfc2LYpnlUtG7JqsSHq1WoASbUS4KVaLwB8be5mfsGMDwBcm5VxbuxWxx3nkFanB6lYqsqSkOGkKicoDvXsneR7BkKU7DtaEuT7+pxBGVwx+9gVyqf2pVA9sC2CsmjZ1RJqEJHS4Tj/pCcS0JoyBYOsB91Xjh3OFfQPQhvCAYyeLJlaOoFp0XNNuD0BC8exr8uPx7D1JWkwFdZIXmD3MOPReuDNzHjBesSzIbQD"\n alt="${o}$"\n >\n `;let i="";return t.rsvp&&m[t.rsvp]&&(i=`<sub>${m[t.rsvp]}</sub>`),`\n <a\n class="reaction"\n rel="nofollow ugc"\n title="${o} ${r}"\n href="${t[l]}"\n >\n ${s}\n ${f[t["wm-property"]]||"💥"}\n ${i}\n </a>\n `}function h(n){return n.substr(n.indexOf("//"))}function g(n){const t=[],e={};return n.forEach((function(n){const o=h(n.url);e[o]||(t.push(n),e[o]=!0)})),t}function x(n){let t=d(n.content.text);if(s){let n=t.replace(/\s+/g," ").split(" ",s+1);n.length>s&&(n[s-1]+="&hellip;",n=n.slice(0,s),t=n.join(" "))}return t}window.addEventListener("load",(async function(){const t=document.getElementById(r);if(!t)return;const s=[h(e)];o&&o.split("|").forEach((function(n){s.push(h(n))}));let p=`https://webmention.io/api/mentions.jf2?per-page=${i}&sort-by=${a}&sort-dir=${c}`;s.forEach((function(n){p+=`&target[]=${encodeURIComponent("http:"+n)}&target[]=${encodeURIComponent("https:"+n)}`}));let f={};try{const n=await window.fetch(p);n.status>=200&&n.status<300?f=await n.json():(console.error("Could not parse response"),new Error(n.statusText))}catch(n){console.error("Request failed",n)}let m=[];const $=[];u&&(m=$);const y={"in-reply-to":m,"like-of":$,"repost-of":$,"bookmark-of":$,"follow-of":$,"mention-of":m,rsvp:m};f.children.forEach((function(n){const t=y[n["wm-property"]];t&&t.push(n)}));let b="";m.length>0&&m!==$&&(b=function(t){return`\n <h2>${n("Responses")}</h2>\n <ul class="comments">${t.map((t=>{const e=w(t,!0);let o=d(t.url.split("/")[2]);t.author&&t.author.name&&(o=d(t.author.name));const r=`<a class="source" rel="nofollow ugc" href="${t[l]}">${o}</a>`;let s="name",i=`(${n("mention")})`;return t.name?(s="name",i=d(t.name)):t.content&&t.content.text&&(s="text",i=x(t)),`<li>${e} ${r} <span class="${s}">${i}</span></li>`})).join("")}</ul>\n `}(g(m)));let k="";var B;$.length>0&&(B=g($),k=`\n <h2>${n("Reactions")}</h2>\n <ul class="reacts">${B.map((n=>w(n))).join("")}</ul>\n `),t.innerHTML=`${b}${k}`}))}(); !function(){"use strict";window.i18next=window.i18next||{t:function(n){return n}};const n=window.i18next.t.bind(window.i18next);function t(n,t){return document.currentScript.getAttribute("data-"+n)||t}const e=t("page-url",window.location.href.replace(/#.*$/,"")),o=t("add-urls",void 0),r=t("id","webmentions"),s=t("wordcount"),i=t("max-webmentions",30),l=t("prevent-spoofing")?"wm-source":"url",a=t("sort-by","published"),c=t("sort-dir","up"),u=t("comments-are-reactions",!1),p={"in-reply-to":n("replied"),"like-of":n("liked"),"repost-of":n("reposted"),"bookmark-of":n("bookmarked"),"mention-of":n("mentioned"),rsvp:n("RSVPed"),"follow-of":n("followed")},f={"in-reply-to":"💬","like-of":"❤️","repost-of":"🔄","bookmark-of":"⭐️","mention-of":"💬",rsvp:"📅","follow-of":"🐜"},m={yes:"✅",no:"❌",interested:"💡",maybe:"💭"};function d(n){return n.replace(/[&<>"]/g,(n=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;"}[n]||n)))}function w(t,e){const o=d(t.author?.name||t.url.split("/")[2]);let r=p[t["wm-property"]]||n("reacted");!e&&t.content&&t.content.text&&(r+=": "+x(t));let s="";s=t.author&&t.author.photo?`\n <img\n src="${d(t.author.photo)}"\n loading="lazy"\n decoding="async"\n alt="${o}"\n >\n `:`\n <img\n class="missing"\n src="data:image/webp;base64,UklGRkoCAABXRUJQVlA4TD4CAAAvP8APAIV0WduUOLr/m/iqY6SokDJSMD5xYX23SQizRsVdZmIj/f6goYUbiOj/BED7MOPReuBNT3vBesSzIex+SeqMFFkjebFmzH3S7POxDSJ1yaCbCmMnS2R46cRMPyQLw4GBK4esdK60pYwsZakecUCl5zsHv/5cPH08nx9/7i6rEEVCg2hR8VSd30PxMZpVoJZQO6Dixgg6X5oKFCmlVHIDmmMFShWumAXgCuyqVN8hHff/k+9fj8+ei7BVjpxBmZCUJv+6DhWGZwWvs+UoLHFCKsPYpfJtIcEXBTopEEsKwedZUv4ku1FZErKULLyQwFGgnmTs2vBD5qu44xwnG9uyjgrFOd+KRVlXyQfwQlauydaU6AVI7OjKXLUEqNtxJBmQegNDZgV7lxxqYMOMrDyC1NdAGbdiH9Ij0skjG+oTyfO0lmjdgvoH8iIgreuBMRYLSH+R3sAztXgL+XfS7E2bmfo6gnS0TrpnzHT7kL+skj7PgHuBwv/zpN8LDLQg7zfJZLBubMKnyeh6ZGyfDEfc2LYpnlUtG7JqsSHq1WoASbUS4KVaLwB8be5mfsGMDwBcm5VxbuxWxx3nkFanB6lYqsqSkOGkKicoDvXsneR7BkKU7DtaEuT7+pxBGVwx+9gVyqf2pVA9sC2CsmjZ1RJqEJHS4Tj/pCcS0JoyBYOsB91Xjh3OFfQPQhvCAYyeLJlaOoFp0XNNuD0BC8exr8uPx7D1JWkwFdZIXmD3MOPReuDNzHjBesSzIbQD"\n alt="${o}$"\n >\n `;let i="";return t.rsvp&&m[t.rsvp]&&(i=`<sub>${m[t.rsvp]}</sub>`),`\n <a\n class="reaction"\n rel="nofollow ugc"\n title="${o} ${r}"\n href="${t[l]}"\n >\n ${s}\n ${f[t["wm-property"]]||"💥"}\n ${i}\n </a>\n `}function h(n){return n.substr(n.indexOf("//"))}function g(n){const t=[],e={};return n.forEach((function(n){const o=h(n.url);e[o]||(t.push(n),e[o]=!0)})),t}function x(n){let t=d(n.content.text);if(s){let n=t.replace(/\s+/g," ").split(" ",s+1);n.length>s&&(n[s-1]+="&hellip;",n=n.slice(0,s),t=n.join(" "))}return t}window.addEventListener("load",(async function(){const t=document.getElementById(r);if(!t)return;const s=[h(e)];o&&o.split("|").forEach((function(n){s.push(h(n))}));let p=`https://webmention.io/api/mentions.jf2?per-page=${i}&sort-by=${a}&sort-dir=${c}`;s.forEach((function(n){p+=`&target[]=${encodeURIComponent("http:"+n)}&target[]=${encodeURIComponent("https:"+n)}`}));let f={};try{const n=await window.fetch(p);n.status>=200&&n.status<300?f=await n.json():(console.error("Could not parse response"),new Error(n.statusText))}catch(n){console.error("Request failed",n)}let m=[];const $=[];u&&(m=$);const y={"in-reply-to":m,"like-of":$,"repost-of":$,"bookmark-of":$,"follow-of":$,"mention-of":m,rsvp:m};f.children.forEach((function(n){const t=y[n["wm-property"]];t&&t.push(n)}));let b="";m.length>0&&m!==$&&(b=function(t){return`\n <h2>${n("Responses")}</h2>\n <ul class="comments">${t.map((t=>{const e=w(t,!0);let o=d(t.url.split("/")[2]);t.author&&t.author.name&&(o=d(t.author.name));const r=`<a class="source" rel="nofollow ugc" href="${t[l]}">${o}</a>`;let s="name",i=`(${n("mention")})`;return t.name?(s="name",i=d(t.name)):t.content&&t.content.text&&(s="text",i=x(t)),`<li>${e} ${r} <span class="${s}">${i}</span></li>`})).join("")}</ul>\n `}(g(m)));let k="";var B;$.length>0&&(B=g($),k=`\n <h2>${n("Reactions")}</h2>\n <ul class="reacts">${B.map((n=>w(n))).join("")}</ul>\n `),t.innerHTML=`${b}${k}`}))}();
// @license-end // @license-end