2022-12-10 18:15:32 +00:00
|
|
|
let commentsLoaded = false;
|
|
|
|
const details = document.getElementById("comments-container");
|
|
|
|
details.addEventListener("toggle", (even) => {
|
|
|
|
if (details.open && !commentsLoaded) {
|
|
|
|
fetchComments().then(() => {
|
|
|
|
commentsLoaded = true;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
async function fetchComments() {
|
2023-01-05 20:58:08 +00:00
|
|
|
const res = await fetch(`/comments?id=${articlePermalink}`);
|
2022-12-10 18:15:32 +00:00
|
|
|
const comments = await res.json();
|
2023-01-05 20:58:08 +00:00
|
|
|
const rootId = new URL(`https://${articleDomain}${articlePermalink}`);
|
|
|
|
const [tree, _] = buildCommentsTree(comments, rootId);
|
2022-12-10 18:15:32 +00:00
|
|
|
const html = renderCommentList(tree);
|
|
|
|
document.getElementById("comments-container").innerHTML += html;
|
|
|
|
}
|
|
|
|
|
|
|
|
function buildCommentsTree(comments, parent) {
|
|
|
|
console.log(`Building tree for ${parent}`);
|
|
|
|
let [children, rem] = partition(comments, it => {
|
|
|
|
const inReplyTo = new URL(it.inReplyTo);
|
|
|
|
return inReplyTo.hostname === parent.hostname && inReplyTo.pathname === parent.pathname;
|
|
|
|
});
|
|
|
|
for (const child of children) {
|
|
|
|
const [subChildren, subRem] = buildCommentsTree(rem, new URL(child.id));
|
|
|
|
rem = subRem;
|
|
|
|
child.children = subChildren;
|
|
|
|
}
|
|
|
|
return [children, rem]
|
|
|
|
}
|
|
|
|
|
|
|
|
function partition(array, fn) {
|
|
|
|
const trueArr = [];
|
|
|
|
const falseArr = [];
|
|
|
|
for (const el of array) {
|
|
|
|
(fn(el) ? trueArr : falseArr).push(el);
|
|
|
|
}
|
|
|
|
return [trueArr, falseArr];
|
|
|
|
}
|
|
|
|
|
|
|
|
function renderCommentList(comments) {
|
|
|
|
const rendered = comments.map(renderComment).join("\n");
|
|
|
|
return `<ul class="comments-list">` + rendered + `</ul>`;
|
|
|
|
}
|
|
|
|
|
|
|
|
function renderComment(comment) {
|
|
|
|
const formattedDate = new Date(comment.published).toLocaleString("en-us", {
|
|
|
|
month: "short",
|
|
|
|
day: "numeric",
|
|
|
|
year: "numeric",
|
|
|
|
hour: "numeric",
|
|
|
|
minute: "numeric"
|
|
|
|
});
|
|
|
|
let children;
|
|
|
|
if (comment.children.length > 0) {
|
|
|
|
children = `<div class="comment-children">${renderCommentList(comment.children)}</div>`;
|
|
|
|
} else {
|
|
|
|
children = "";
|
|
|
|
}
|
|
|
|
return `
|
|
|
|
<div class="comment">
|
|
|
|
<img class="comment-user-avatar" src="${comment.author.icon}">
|
|
|
|
<div class="comment-main">
|
|
|
|
<p class="comment-info">
|
|
|
|
<a class="comment-user-name" href="${comment.author.id}">${comment.author.name}</a>
|
|
|
|
on
|
|
|
|
<a class="comment-date" href="${comment.id}">${formattedDate}</a>
|
|
|
|
</p>
|
|
|
|
<div class="comment-body">
|
|
|
|
${comment.content}
|
|
|
|
</div>
|
|
|
|
${children}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
`;
|
|
|
|
}
|