diff --git a/src/components/Comments.astro b/src/components/Comments.astro index 4c8d71f..04e0776 100644 --- a/src/components/Comments.astro +++ b/src/components/Comments.astro @@ -1,301 +1,162 @@ --- -import { getCollection } from "astro:content"; import { getLangFromUrl } from "@/i18n"; -const token = import.meta.env.GITHUB_TOKEN; -const owner = import.meta.env.GISCUS_REPO_OWNER ?? "ClovertaTheTrilobita"; -const name = import.meta.env.GISCUS_REPO_NAME ?? "SanYeCao-blog"; -const categoryId = import.meta.env.GISCUS_CATEGORY_ID ?? "DIC_kwDORvuVpM4C5MDE"; const limit = Number(Astro.props.limit ?? 5); - const lang = getLangFromUrl(Astro.url); -const allPosts = await getCollection("blog"); - -type CommentAuthor = { - login?: string; - avatarUrl?: string; - url?: string; -}; - -type RawReply = { - id: string; - body?: string; - updatedAt: string; - author?: CommentAuthor | null; -}; - -type RawComment = { - id: string; - body?: string; - updatedAt: string; - author?: CommentAuthor | null; - replies?: { - nodes?: RawReply[]; - }; -}; - -type DiscussionNode = { - title: string; - comments?: { - nodes?: RawComment[]; - }; -}; - -type LatestCommentItem = { - id: string; - body?: string; - updatedAt: string; - author?: CommentAuthor | null; - postId: string; - postTitle: string; - localUrl: string; - isReply: boolean; - replyTo?: string; -}; - -function normalizePath(path: string) { - return path.replace(/^\/+|\/+$/g, ""); -} - -function excerpt(text = "", max = 110) { - const plain = text.replace(/\s+/g, " ").trim(); - if (plain.length <= max) return plain; - return plain.slice(0, max) + "…"; -} function formatDate(iso: string) { return new Date(iso).toISOString().slice(0, 10); } - -async function fetchLatestComments(): Promise { - if (!token) return []; - - const query = ` - query($owner: String!, $name: String!, $categoryId: ID!) { - repository(owner: $owner, name: $name) { - discussions( - first: 20 - categoryId: $categoryId - orderBy: { field: UPDATED_AT, direction: DESC } - ) { - nodes { - title - comments(last: 10) { - nodes { - id - body - updatedAt - author { - ... on User { - login - avatarUrl - url - } - ... on Organization { - login - avatarUrl - url - } - } - replies(first: 10) { - nodes { - id - body - updatedAt - author { - ... on User { - login - avatarUrl - url - } - ... on Organization { - login - avatarUrl - url - } - } - } - } - } - } - } - } - } - } -`; - - const res = await fetch("https://api.github.com/graphql", { - method: "POST", - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${token}`, - }, - body: JSON.stringify({ - query, - variables: { owner, name, categoryId }, - }), - }); - - const json = await res.json(); - const discussions = (json?.data?.repository?.discussions?.nodes ?? - []) as DiscussionNode[]; - - // 用 post.id 建本地文章索引 - const postMap = new Map( - allPosts.map((post: any) => [ - normalizePath(post.id), - { - title: post.data.title, - url: `/${lang}/posts/${post.id}/#comments`, - }, - ]), - ); - - const comments: LatestCommentItem[] = []; - - for (const discussion of discussions) { - const discussionKey = normalizePath(discussion.title); - - let matchedPostId: string | undefined; - - if (postMap.has(discussionKey)) { - matchedPostId = discussionKey; - } else { - matchedPostId = [...postMap.keys()].find( - (postId) => - discussionKey === postId || - discussionKey.includes(postId) || - postId.includes(discussionKey), - ); - } - - if (!matchedPostId) continue; - - const postInfo = postMap.get(matchedPostId); - if (!postInfo) continue; - - for (const comment of discussion.comments?.nodes ?? []) { - comments.push({ - id: comment.id, - body: comment.body, - updatedAt: comment.updatedAt, - author: comment.author, - postId: matchedPostId, - postTitle: postInfo.title, - localUrl: postInfo.url, - isReply: false, - }); - - for (const reply of comment.replies?.nodes ?? []) { - comments.push({ - id: reply.id, - body: reply.body, - updatedAt: reply.updatedAt, - author: reply.author, - postId: matchedPostId, - postTitle: postInfo.title, - localUrl: postInfo.url, - isReply: true, - replyTo: comment.author?.login ?? "Unknown", - }); - } - } - } - - return comments - .sort( - (a, b) => - new Date(b.updatedAt).getTime() - - new Date(a.updatedAt).getTime(), - ) - .slice(0, limit); -} - -const comments = await fetchLatestComments(); --- -
+

{lang === "zh" ? "最新评论" : "Latest Comments"}

- { - comments.length === 0 ? ( -

- {lang === "zh" ? "还没有评论。" : "No comments yet."} -

- ) : ( - - ) - } +
- diff --git a/src/components/Navigation.astro b/src/components/Navigation.astro index 8b556dd..b978f2d 100644 --- a/src/components/Navigation.astro +++ b/src/components/Navigation.astro @@ -6,7 +6,7 @@ const t = getTranslations(lang); ---