fix(comments): fix comments disappear after lang switc

feat(friends): added friendly links
This commit is contained in:
ClovertaTheTrilobita 2026-03-25 12:06:37 +02:00
parent 5554f25352
commit a4279b1a59
23 changed files with 178 additions and 15 deletions

View file

@ -1,5 +1,5 @@
--- ---
title: 'My First Blog Post' title: '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试'
pubDate: 2022-07-01 pubDate: 2022-07-01
description: 'This is the first post of my new Astro blog.' description: 'This is the first post of my new Astro blog.'
author: 'Astro Learner' author: 'Astro Learner'

View file

@ -0,0 +1,81 @@
---
import "@/styles/global.css";
const { name, description, avatar, url } = Astro.props;
---
<a
href={url}
class="friendly-link-card"
target="_blank"
rel="noopener noreferrer"
>
<div class="friendly-link-text">
<div class="friendly-link-title">{name}</div>
<div class="friendly-link-description">{description}</div>
</div>
<img src={avatar} alt={name} class="friendly-link-avatar" />
</a>
<style>
.friendly-link-card {
display: flex;
justify-content: space-between;
align-items: center;
gap: 1rem;
padding: 0.1rem 0.5rem;
background: #fffcf1;
border: 2px solid #ede3d0;
text-decoration: none;
color: inherit;
}
.friendly-link-text {
flex: 1;
min-width: 0;
}
.friendly-link-title {
font-weight: 700;
font-size: 1rem;
line-height: 1.4;
color: #2f2a22;
margin-bottom: 0.25rem;
overflow-wrap: anywhere;
}
.friendly-link-description {
font-size: 0.9rem;
line-height: 1.5;
color: #6f6a5f;
font-style: italic;
overflow-wrap: anywhere;
}
.friendly-link-avatar {
width: 72px;
height: 72px;
object-fit: cover;
object-position: center;
padding: 0.3rem 0.3rem;
display: block;
flex-shrink: 0;
}
.friendly-link-card:hover {
background: #efe2be;
}
:global(.dark) .friendly-link-card {
background: #3a352b;
border-color: #8f8268;
}
:global(.dark) .friendly-link-title {
color: #f0e6cf;
}
:global(.dark) .friendly-link-description {
color: #c8bfae;
}
</style>

View file

@ -0,0 +1,37 @@
---
import FriendlyLinkItem from "./FriendlyLinkItem.astro";
import { getCollection } from "astro:content";
import { getLangFromUrl } from "@/i18n";
const lang = getLangFromUrl(Astro.url);
const links = await getCollection("friends");
// const { links = [] } = Astro.props;
---
<div class="friendly-link-list">
{
links.map((link: any) => (
<FriendlyLinkItem
name={link.data.name}
description={link.data.description}
avatar={link.data.avatar}
url={link.data.url}
/>
))
}
</div>
<style>
.friendly-link-list {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 1rem;
align-items: start;
}
@media (max-width: 720px) {
.friendly-link-list {
grid-template-columns: 1fr;
}
}
</style>

View file

@ -1,5 +1,5 @@
--- ---
const { term } = Astro.props;
--- ---
<section class="comments"> <section class="comments">
@ -11,8 +11,9 @@
data-repo-id="R_kgDORvuVpA" data-repo-id="R_kgDORvuVpA"
data-category="Comments" data-category="Comments"
data-category-id="DIC_kwDORvuVpM4C5MDE" data-category-id="DIC_kwDORvuVpM4C5MDE"
data-mapping="pathname" data-mapping="specific"
data-strict="0" data-term={term}
data-strict="1"
data-reactions-enabled="1" data-reactions-enabled="1"
data-emit-metadata="0" data-emit-metadata="0"
data-input-position="bottom" data-input-position="bottom"
@ -20,8 +21,7 @@
data-lang="en" data-lang="en"
data-loading="lazy" data-loading="lazy"
crossorigin="anonymous" crossorigin="anonymous"
async async></script>
></script>
<script is:inline> <script is:inline>
function setGiscusTheme(theme) { function setGiscusTheme(theme) {

View file

@ -10,6 +10,7 @@ const t = getTranslations(lang);
<a href={`/${lang}/about`}>{t.nav.about}</a> <a href={`/${lang}/about`}>{t.nav.about}</a>
<a href={`/${lang}/tags`}>{t.nav.tags}</a> <a href={`/${lang}/tags`}>{t.nav.tags}</a>
<a href={`/${lang}/timeline`}>{t.nav.timeline}</a> <a href={`/${lang}/timeline`}>{t.nav.timeline}</a>
<a href={`/${lang}/friends`}>{t.nav.friends}</a>
</nav> </nav>
<style> <style>

View file

@ -52,7 +52,7 @@ const data = Astro.props;
} }
.post-title { .post-title {
font-family: "Recursive Mono", "Maple Mono"; font-family: "Recursive Mono", "Maple Mono CN";
color: inherit; color: inherit;
font-weight: 700; font-weight: 700;
font-size: 1.34rem; font-size: 1.34rem;

View file

@ -82,7 +82,7 @@ const discussions = await fetchDiscussionStats();
.toISOString() .toISOString()
.split("T")[0]; .split("T")[0];
const pathname = `/${lang}/posts/${post.id}/`; const pathname = `/${post.id}/`;
const matchedDiscussion = discussions.find((d: DiscussionNode) => { const matchedDiscussion = discussions.find((d: DiscussionNode) => {
return normalizePath(d.title) === normalizePath(pathname); return normalizePath(d.title) === normalizePath(pathname);

View file

@ -34,7 +34,7 @@ const switchHref = "/" + segments.join("/");
</svg> </svg>
</button> </button>
<a class="lang-switch" href={switchHref}> <a class="lang-switch" href={switchHref} data-astro-reload>
{switchLabel} {switchLabel}
</a> </a>
</div> </div>

View file

@ -19,5 +19,16 @@ const blog = defineCollection({
tags: z.array(z.string()) tags: z.array(z.string())
}) })
}); });
const friends = defineCollection({
loader: glob({ pattern: '**/[^_]*.md', base: "./src/friends" }),
schema: z.object({
name: z.string(),
description: z.string(),
url: z.string(),
avatar: z.string()
})
});
// Export a single `collections` object to register your collection(s) // Export a single `collections` object to register your collection(s)
export const collections = { blog }; export const collections = { blog, friends };

6
src/friends/example.md Normal file
View file

@ -0,0 +1,6 @@
---
name: 'CLovertaTheTrilobita'
description: "This is Cloverta's blog"
url: "https://cloverta.top"
avatar: 'https://docs.astro.build/assets/rose.webp'
---

6
src/friends/example2.md Normal file
View file

@ -0,0 +1,6 @@
---
name: 'CLovertaTheTrilobita'
description: "This is Cloverta's blog"
url: 'https://docs.astro.build/assets/rose.webp'
avatar: 'https://docs.astro.build/assets/rose.webp'
---

View file

@ -9,6 +9,7 @@ export default {
tags: "Tags", tags: "Tags",
about: "About", about: "About",
timeline: "Timeline", timeline: "Timeline",
friends: "Friends"
}, },
post: { post: {
writtenBy: "Written by", writtenBy: "Written by",

View file

@ -8,7 +8,8 @@ export default {
posts: "文章", posts: "文章",
tags: "标签", tags: "标签",
about: "关于", about: "关于",
timeline: "时间轴" timeline: "时间轴",
friends: "友链"
}, },
post: { post: {
writtenBy: "作者", writtenBy: "作者",

View file

@ -4,8 +4,8 @@ import Giscus from "@/components/Giscus.astro";
import { getLangFromUrl, getTranslations } from "@/i18n"; import { getLangFromUrl, getTranslations } from "@/i18n";
import "@/styles/global.css"; import "@/styles/global.css";
const { frontmatter } = Astro.props; const { frontmatter, lang, postId } = Astro.props;
const lang = getLangFromUrl(Astro.url); // const lang = getLangFromUrl(Astro.url);
const t = getTranslations(lang); const t = getTranslations(lang);
--- ---
@ -41,7 +41,7 @@ const t = getTranslations(lang);
<slot /> <slot />
<Giscus /> <Giscus term={postId} />
</BaseLayout> </BaseLayout>
<style> <style>

View file

@ -0,0 +1,18 @@
---
import BaseLayout from "@/layouts/BaseLayout.astro";
import FriendlyLinkList from "@/components/FriendlyLinks/FriendlyLinkList.astro";
import { getLangFromUrl, getTranslations } from "@/i18n";
import "@/styles/global.css";
export function getStaticPaths() {
return [{ params: { lang: "zh" } }, { params: { lang: "en" } }];
}
const lang = getLangFromUrl(Astro.url);
const t = getTranslations(lang);
const headerTitle = lang === "zh" ? "友情链接" : "Friends";
---
<BaseLayout pageTitle={headerTitle}>
<FriendlyLinkList />
</BaseLayout>

View file

@ -24,6 +24,6 @@ const { post, lang } = Astro.props;
const { Content } = await render(post); const { Content } = await render(post);
--- ---
<MarkdownPostLayout frontmatter={post.data} lang={lang}> <MarkdownPostLayout frontmatter={post.data} lang={lang} postId={post.id}>
<Content /> <Content />
</MarkdownPostLayout> </MarkdownPostLayout>

View file

@ -14,5 +14,6 @@ const headerTitle = lang === "zh" ? "时间轴" : "Timeline";
--- ---
<BaseLayout pageTitle={headerTitle}> <BaseLayout pageTitle={headerTitle}>
<h1>{t.nav.timeline}</h1>
<PostTimeline /> <PostTimeline />
</BaseLayout> </BaseLayout>