diff --git a/src/assets/css/oom-styles.css b/src/assets/css/oom-styles.css deleted file mode 100644 index c4cffdd..0000000 --- a/src/assets/css/oom-styles.css +++ /dev/null @@ -1,93 +0,0 @@ -/* https://github.com/oom-components/mastodon-comments, under MIT License */ -oom-comments { - display: block; - padding: 2em; -} -oom-comments ul { - list-style: none; - margin: 0; - padding: 0; -} -oom-comments li { - margin: 32px 0; -} -oom-comments article { - max-width: 600px; -} -oom-comments ul ul { - margin-left: 64px; -} -oom-comments .comment-avatar { - width: 50px; - height: 50px; - border-radius: 6px; - float: left; - margin-right: 14px; - box-shadow: 0 0 1px #0009; -} -oom-comments .comment-user { - color: currentColor; - text-decoration: none; - display: block; - position: relative; -} -oom-comments .comment-author { - position: absolute; - left: 35px; - top: 35px; - background: white; - border-radius: 50%; - width: 20px; - height: 20px; - color: gray; -} -oom-comments .comment-user:hover .comment-username { - text-decoration: underline; -} -oom-comments .comment-username { - margin-right: 0.5em; -} -oom-comments .comment-useraddress { - color: gray; - font-size: small; - font-style: normal; -} -oom-comments .comment-time { - font-size: small; - display: flex; - align-items: center; - column-gap: 0.4em; -} -oom-comments .comment-time svg { - width: 1em; - height: 1em; - fill: gray; -} -oom-comments .comment-address { - color: currentColor; - text-decoration: none; - display: block; - margin-top: 0.25em; -} -oom-comments .comment-address:hover { - text-decoration: underline; -} -oom-comments .comment-body { - margin-top: 0.5em; - margin-left: 64px; - line-height: 1.5; -} -oom-comments .comment-body p { - margin: 0.5em 0; -} -oom-comments .comment-counts { - display: flex; - column-gap: 1em; - font-size: small; -} -oom-comments .comment-counts > span { - display: flex; - align-items: center; - column-gap: 0.3em; - color: gray; -} diff --git a/src/assets/js/oom-comments.js b/src/assets/js/oom-comments.js deleted file mode 100644 index 404a483..0000000 --- a/src/assets/js/oom-comments.js +++ /dev/null @@ -1,312 +0,0 @@ -/* https://github.com/oom-components/mastodon-comments, under MIT License */ -// © https://phosphoricons.com/ -export const icons = { - reblog: - ``, - favourite: - ``, - author: - ``, - - // @ https://simpleicons.org/ - mastodon: - `Mastodon`, - - pleroma: - `Pleroma`, - - bluesky: - `Bluesky`, -}; - -export default class SocialComments extends HTMLElement { - comments = {}; - - async connectedCallback() { - const lang = this.closest("[lang]")?.lang || navigator.language || "en"; - - this.dateTimeFormatter = new Intl.DateTimeFormat(lang, { - dateStyle: "medium", - timeStyle: "short", - }); - - const mastodon = this.getAttribute("mastodon") || this.getAttribute("src"); - const bluesky = this.getAttribute("bluesky"); - - await Promise.all([ - mastodon && this.#fetchMastodon(new URL(mastodon)), - bluesky && this.#fetchBluesky(new URL(bluesky)), - ]); - - this.refresh(); - } - - refresh() { - const comments = [ - ...this.comments.mastodon || [], - ...this.comments.bluesky || [], - ].sort( - (a, b) => new Date(a.createdAt) - new Date(b.createdAt), - ); - - if (comments.length) { - this.innerHTML = ""; - this.render(this, comments); - } - } - - async #fetchBluesky(url) { - const { pathname } = url; - - const [, handle, rkey] = pathname.match( - /\/profile\/([\w\.]+)\/post\/(\w+)/, - ); - - if (!handle || !rkey) { - return; - } - - const options = { - ttl: Number(this.getAttribute("cache") || 0), - }; - - const didData = await fetchJSON( - `https://public.api.bsky.app/xrpc/com.atproto.identity.resolveHandle?handle=${handle}`, - options, - ); - const uri = `at://${didData.did}/app.bsky.feed.post/${rkey}`; - - this.comments.bluesky = dataFromBluesky( - await fetchJSON( - `https://public.api.bsky.app/xrpc/app.bsky.feed.getPostThread?uri=${uri}`, - options, - ), - ); - } - - async #fetchMastodon(url) { - const { origin, pathname } = url; - let id; - - const source = pathname.includes("/notice/") ? "pleroma" : "mastodon"; - - if (source === "pleroma") { - [, id] = pathname.match(/^\/notice\/([^\/?#]+)/); - } else { - [, id] = pathname.match(/\/(\d+)$/); - } - - if (!id) { - return; - } - - const token = this.getAttribute("token"); - const options = { - ttl: Number(this.getAttribute("cache") || 0), - }; - if (token) { - options.headers = { - Authorization: `Bearer ${token}`, - }; - } - - const user = url.pathname.split("/")[1]; - const author = `${user}@${url.hostname}`; - - const comments = dataFromMastodon( - await fetchJSON( - new URL(`${origin}/api/v1/statuses/${id}/context`), - options, - ), - author, - source, - ); - - this.comments.mastodon = comments.filter((comment) => - comment.parent === id - ); - } - - render(container, replies) { - const ul = document.createElement("ul"); - - for (const reply of replies) { - const comment = document.createElement("li"); - comment.innerHTML = this.renderComment(reply); - - if (reply.replies.length) { - this.render(comment, reply.replies); - } - ul.appendChild(comment); - } - - container.appendChild(ul); - } - - renderComment(comment) { - return ` -
- -
- ${comment.content} - -

- ${ - comment.boosts ? `${icons.reblog} ${comment.boosts}` : "" - } - ${ - comment.likes ? `${icons.favourite} ${comment.likes}` : "" - } -

-
-
- `; - } -} - -function formatEmojis(html, emojis) { - emojis.forEach(({ shortcode, static_url, url }) => { - html = html.replace( - `:${shortcode}:`, - ` - - :${shortcode}: - `, - ); - }); - return html; -} - -async function fetchJSON(url, options = {}) { - const headers = new Headers(); - - if (options.headers) { - for (const [key, value] of Object.entries(options.headers)) { - headers.set(key, value); - } - } - - if (typeof caches === "undefined") { - return await (await fetch(url), { headers }).json(); - } - - const cache = await caches.open("mastodon-comments"); - let cached = await cache.match(url); - - if (cached && options.ttl) { - const cacheTime = new Date(cached.headers.get("x-cached-at")); - const diff = Date.now() - cacheTime.getTime(); - - if (diff <= options.ttl * 1000) { - return await cached.json(); - } - } - - try { - const response = await fetch(url, { headers }); - const body = await response.json(); - - cached = new Response(JSON.stringify(body)); - cached.headers.set("x-cached-at", new Date()); - cached.headers.set("content-type", "application/json; charset=utf-8"); - await cache.put(url, cached); - return body; - } catch { - if (cached) { - return await cached.json(); - } - } -} - -function dataFromMastodon(data, author, source) { - const comments = new Map(); - - // Transform data to a more usable format - for (const comment of data.descendants) { - if (comment.visibility !== "public") { - continue; - } - - const { account } = comment; - const handler = `@${account.username}@${new URL(account.url).hostname}`; - comments.set(comment.id, { - id: comment.id, - isMine: author === handler, - source, - url: comment.url, - parent: comment.in_reply_to_id, - createdAt: new Date(comment.created_at), - content: formatEmojis(comment.content, comment.emojis), - author: { - name: formatEmojis(account.display_name, account.emojis), - handler, - url: account.url, - avatar: account.avatar_static, - alt: account.display_name, - }, - boosts: comment.reblogs_count, - likes: comment.favourites_count, - replies: [], - }); - } - - // Group comments by parent - for (const comment of comments.values()) { - if (comment.parent && comments.has(comment.parent)) { - comments.get(comment.parent).replies.push(comment); - } - } - - return Array.from(comments.values()); -} - -function dataFromBluesky(data) { - const { thread } = data; - - return blueskyComments( - thread.post.author.did, - thread.post.cid, - thread.replies, - ); -} - -function blueskyComments(author, parent, comments) { - return comments.map((reply) => { - const { post, replies } = reply; - const rkey = post.uri.split("/").pop(); - return { - id: post.cid, - isMine: post.author.did === author, - source: "bluesky", - url: `https://bsky.app/profile/${post.author.handle}/post/${rkey}`, - parent, - createdAt: new Date(post.record.createdAt), - content: post.record.text, - author: { - name: post.author.displayName, - handler: post.author.handle, - url: `https://bsky.app/profile/${post.author.handle}`, - avatar: post.author.avatar, - alt: post.author.displayName, - }, - boosts: post.repostCount, - likes: post.likeCount, - replies: blueskyComments(author, post.cid, replies || []), - }; - }); -} diff --git a/src/components/Comments.astro b/src/components/Comments.astro index c0429bc..e6e6bd4 100644 --- a/src/components/Comments.astro +++ b/src/components/Comments.astro @@ -4,23 +4,15 @@ import FediverseComments from "./helper/comments/Fediverse.astro"; import HatsuComments from "./helper/comments/Hatsu.astro"; import Artalk from "./helper/comments/Artalk.astro"; import Giscus from "./helper/comments/Giscus.astro"; -import OomComments from "./helper/comments/OOM.astro"; const method = siteConfig.comments.type const FediverseConfig = siteConfig.comments.fediverse -interface Props { - mastodonLink?: string; - bskyLink?: string; -} - -const { mastodonLink, bskyLink } = Astro.props; --- {method === 'artalk' && } {method === 'giscus' && } {(method === 'fediverse' && !FediverseConfig.renderOnServer ) && } {(method === 'fediverse' && FediverseConfig.renderOnServer ) &&

Loading comments...

} -{method === 'hatsu' && } -{method === 'oom' && } \ No newline at end of file +{method === 'hatsu' && } \ No newline at end of file diff --git a/src/components/Navbar.astro b/src/components/Navbar.astro index 0780ee9..7bcb4bc 100644 --- a/src/components/Navbar.astro +++ b/src/components/Navbar.astro @@ -5,5 +5,5 @@ const navBarItems = siteConfig.navBarItems \ No newline at end of file diff --git a/src/components/TableOfContents.astro b/src/components/TableOfContents.astro index 4345944..6e91d7c 100644 --- a/src/components/TableOfContents.astro +++ b/src/components/TableOfContents.astro @@ -73,9 +73,6 @@ const toc = buildHierarchy(filteredHeadings); +