Skip to content

Commit 69b32dc

Browse files
committed
add mastodon.js
1 parent ee06ada commit 69b32dc

File tree

1 file changed

+115
-0
lines changed

1 file changed

+115
-0
lines changed
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
const mastodonPostTemplate = document.createElement("template");
2+
3+
mastodonPostTemplate.innerHTML = `
4+
<figure>
5+
<blockquote data-key="content"></blockquote>
6+
<figcaption>
7+
<cite>
8+
<a data-key="url"><span data-key="username"></span>@<span data-key="hostname"></span></a>
9+
</cite>
10+
<dl>
11+
<dt>Reposts</dt><dd data-key="reblogs_count"></dd>
12+
<dt>Replies</dt><dd data-key="replies_count"></dd>
13+
<dt>Favourites</dt><dd data-key="favourites_count"></dd>
14+
</dl>
15+
</figcaption>
16+
</figure>
17+
`;
18+
19+
mastodonPostTemplate.id = "mastodon-post-template";
20+
21+
if (!document.getElementById(mastodonPostTemplate.id)) {
22+
document.body.appendChild(mastodonPostTemplate);
23+
}
24+
25+
class MastodonPost extends HTMLElement {
26+
static register(tagName) {
27+
if ("customElements" in window) {
28+
customElements.define(tagName || "mastodon-post", MastodonPost);
29+
}
30+
}
31+
32+
async connectedCallback() {
33+
this.append(this.template);
34+
35+
const data = { ...(await this.data), ...this.linkData };
36+
37+
this.slots.forEach((slot) => {
38+
slot.dataset.key.split(",").forEach((keyItem) => {
39+
const value = this.getValue(keyItem, data);
40+
if (keyItem === "content") {
41+
slot.innerHTML = value;
42+
} else {
43+
this.populateSlot(slot, value);
44+
}
45+
});
46+
});
47+
}
48+
49+
populateSlot(slot, value) {
50+
if (typeof value == "string" && value.startsWith("http")) {
51+
if (slot.localName === "img") slot.src = value;
52+
if (slot.localName === "a") slot.href = value;
53+
} else {
54+
slot.textContent = value;
55+
}
56+
}
57+
58+
handleKey(object, key) {
59+
const parsedKeyInt = parseFloat(key);
60+
61+
if (Number.isNaN(parsedKeyInt)) {
62+
return object[key];
63+
}
64+
65+
return object[parsedKeyInt];
66+
}
67+
68+
getValue(string, data) {
69+
let keys = string.trim().split(/\.|\[|\]/g);
70+
keys = keys.filter((string) => string.length);
71+
72+
const value = keys.reduce(
73+
(object, key) => this.handleKey(object, key),
74+
data
75+
);
76+
return value;
77+
}
78+
79+
get template() {
80+
return document
81+
.getElementById(
82+
this.getAttribute("template") || `${this.localName}-template`
83+
)
84+
.content.cloneNode(true);
85+
}
86+
87+
get slots() {
88+
return this.querySelectorAll("[data-key]");
89+
}
90+
91+
get link() {
92+
return this.querySelector("a").href;
93+
}
94+
95+
get linkData() {
96+
const url = new URL(this.link);
97+
const paths = url.pathname.split("/").filter((string) => string.length);
98+
return {
99+
url: this.link,
100+
hostname: url.hostname,
101+
username: paths.find((path) => path.startsWith("@")),
102+
postId: paths.find((path) => !path.startsWith("@"))
103+
};
104+
}
105+
106+
get endpoint() {
107+
return `https://${this.linkData.hostname}/api/v1/statuses/${this.linkData.postId}`;
108+
}
109+
110+
get data() {
111+
return fetch(this.endpoint).then((response) => response.json());
112+
}
113+
}
114+
115+
MastodonPost.register();

0 commit comments

Comments
 (0)