Adding some webmentions code
This commit is contained in:
parent
91110af05e
commit
d29d1fbb1b
3 changed files with 123 additions and 3 deletions
121
assets/js/webmentions.js
Normal file
121
assets/js/webmentions.js
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
/**
|
||||||
|
* Webmention utilities for ritual.sh
|
||||||
|
* Fetches and formats webmentions from the API
|
||||||
|
*/
|
||||||
|
|
||||||
|
class WebmentionUtils {
|
||||||
|
constructor() {
|
||||||
|
this.apiUrl = "https://api.ritual.sh";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch webmentions for a given target URL
|
||||||
|
* @param {string} targetUrl - The page URL to get webmentions for
|
||||||
|
* @param {number} limit - Maximum number of webmentions to fetch (default: 100)
|
||||||
|
* @returns {Promise<Array>} Array of webmention objects
|
||||||
|
*/
|
||||||
|
async fetch(targetUrl, limit = 100) {
|
||||||
|
try {
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
target: targetUrl,
|
||||||
|
limit: limit.toString(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const response = await fetch(`${this.apiUrl}/webmentions?${params}`);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
console.error(`Webmention API error: ${response.status}`);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
return data.mentions || [];
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching webmentions:", error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format webmentions as a comma-separated list of links
|
||||||
|
* @param {Array} mentions - Array of webmention objects
|
||||||
|
* @returns {string} HTML string of comma-separated links
|
||||||
|
*/
|
||||||
|
asCommaSeparatedList(mentions) {
|
||||||
|
if (!mentions || mentions.length === 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return mentions
|
||||||
|
.map((mention) => {
|
||||||
|
const url = mention.author_url || mention.source;
|
||||||
|
const domain = this.formatDomain(url);
|
||||||
|
const escapedUrl = this.escapeHtml(url);
|
||||||
|
const escapedDomain = this.escapeHtml(domain);
|
||||||
|
return `<a href="${escapedUrl}" target="_blank">${escapedDomain}</a>`;
|
||||||
|
})
|
||||||
|
.join(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a URL to display just the domain (no protocol, www, or path)
|
||||||
|
* @param {string} url - The URL to format
|
||||||
|
* @returns {string} Clean domain name
|
||||||
|
*/
|
||||||
|
formatDomain(url) {
|
||||||
|
if (!url) return "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const urlObj = new URL(url);
|
||||||
|
let domain = urlObj.hostname;
|
||||||
|
// Remove www. prefix if present
|
||||||
|
if (domain.startsWith("www.")) {
|
||||||
|
domain = domain.substring(4);
|
||||||
|
}
|
||||||
|
return domain;
|
||||||
|
} catch (e) {
|
||||||
|
// Fallback: strip protocol and www manually
|
||||||
|
return url
|
||||||
|
.replace(/^https?:\/\//, "")
|
||||||
|
.replace(/^www\./, "")
|
||||||
|
.split("/")[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escape HTML to prevent XSS
|
||||||
|
* @param {string} text - Text to escape
|
||||||
|
* @returns {string} Escaped HTML string
|
||||||
|
*/
|
||||||
|
escapeHtml(text) {
|
||||||
|
const div = document.createElement("div");
|
||||||
|
div.textContent = text;
|
||||||
|
return div.innerHTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-initialize elements with data-webmention-list attribute
|
||||||
|
*/
|
||||||
|
autoInit() {
|
||||||
|
const elements = document.querySelectorAll("[data-webmention-list]");
|
||||||
|
|
||||||
|
elements.forEach(async (element) => {
|
||||||
|
const targetUrl =
|
||||||
|
element.dataset.webmentionList || window.location.href;
|
||||||
|
const mentions = await this.fetch(targetUrl);
|
||||||
|
element.innerHTML = this.asCommaSeparatedList(mentions);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create global instance
|
||||||
|
window.WebmentionUtils = new WebmentionUtils();
|
||||||
|
|
||||||
|
// Auto-initialize on DOM ready
|
||||||
|
if (document.readyState === "loading") {
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
window.WebmentionUtils.autoInit();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
window.WebmentionUtils.autoInit();
|
||||||
|
}
|
||||||
|
|
@ -36,6 +36,6 @@ Big thanks to [neonaut's 88x31 archive](https://neonaut.neocities.org/cyber/88x3
|
||||||
[fyr.io](https://fyr.io/scrap/2026-01-09),
|
[fyr.io](https://fyr.io/scrap/2026-01-09),
|
||||||
[brennan.day](https://brennan.day/resources-for-the-personal-web-a-follow-up-guide/),
|
[brennan.day](https://brennan.day/resources-for-the-personal-web-a-follow-up-guide/),
|
||||||
[kuemmerle.name](https://kuemmerle.name/bastelglueck/),
|
[kuemmerle.name](https://kuemmerle.name/bastelglueck/),
|
||||||
[craney.uk](https://craney.uk/posts/stuff-this-week-74)
|
[craney.uk](https://craney.uk/posts/stuff-this-week-74), <span data-webmention-list></span>
|
||||||
|
|
||||||
Am I missing you? Email me or send a webmention!
|
Am I missing you? Email me or send a webmention!
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,9 @@ From: ritual.sh
|
||||||
/* THANKS */
|
/* THANKS */
|
||||||
Hugo - Static site generator
|
Hugo - Static site generator
|
||||||
The IndieWeb community
|
The IndieWeb community
|
||||||
Everyone still making personal websites in {{ now.Year }}
|
Everyone still making personal websites in 2026
|
||||||
|
|
||||||
/* SITE */
|
/* SITE */
|
||||||
Last update: {{ .Lastmod.Format "2006/01/02" }}
|
|
||||||
Standards: HTML5, CSS3, RSS
|
Standards: HTML5, CSS3, RSS
|
||||||
Components: Hugo, YAML, Markdown
|
Components: Hugo, YAML, Markdown
|
||||||
Software: Built with care
|
Software: Built with care
|
||||||
Loading…
Add table
Add a link
Reference in a new issue