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
bookmark: null
syndication:
- https://mastodon.social/@fundor333/115101269000557955
- https://mastodon.social/@fundor333/115101286930871373
comments:
host: mastodon.social
username: fundor333
id: '115101269000557955'
id: '115101286930871373'
---
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_modified": "{{ .Lastmod.Format "2006-01-02T15:04:05Z07:00" }}",
"id": "{{ .Permalink }}",
"url": "{{ .Permalink }}?utm_source=fundor333.com&utm_medium=jsonfeed&utm_campaign=blogging&ref=fundor333feed.com",
"url": "{{ .Permalink }}",
{{ with .Params.author -}}
"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">
<link rel="webmention" href="https://webmention.io/fundor333.com/webmention" />
<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://kit.fontawesome.com/2f3b6e2e4c.js" crossorigin="anonymous"></script>

View File

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

View File

@@ -1,12 +1,15 @@
<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>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>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>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">
<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>
<noscript>You need JavaScript to view the comments.</noscript>
<script src="/js/purify.min.js"></script>
@@ -48,6 +51,7 @@
function loadComments() {
let commentsWrapper = document.getElementById("comments-wrapper");
document.getElementById("load-comment").innerHTML = "Loading";
fetch('https://{{ .host }}/api/v1/statuses/{{ .id }}/context')
.then(function(response) {
return response.json();
@@ -185,6 +189,6 @@
}
});
}
document.addEventListener("DOMContentLoaded", loadComments);
document.getElementById("load-comment").addEventListener("click", loadComments);
</script>
</section>

6
package-lock.json generated
View File

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

View File

@@ -1,3 +1,4 @@
// @ts-nocheck
// @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}`}))}();
// @license-end