Compare commits

...

29 commits

Author SHA1 Message Date
62036d3e5b update link to projects 2026-04-01 18:09:50 +03:00
d4be88097e update opensource link 2026-04-01 16:59:01 +03:00
b60c207e4c update imgs 2026-04-01 16:44:02 +03:00
df778d1957 update preview 2026-04-01 16:39:36 +03:00
8aa077c506 update imgs 2026-04-01 16:37:06 +03:00
38f8fe6597 deteted unwanted fonts 2026-03-30 20:22:05 +03:00
bfa18d6e17 optimize performance 2026-03-30 20:12:36 +03:00
8a398fbed0 update nav link for performance optimization 2026-03-30 19:38:31 +03:00
4e406bb85b fix rss with correct format 2026-03-30 18:09:49 +03:00
511e7b8e41 fix rss 2026-03-30 18:04:35 +03:00
a207b7284d Merge branch 'master' of https://github.com/ClovertaTheTrilobita/SanYeCao-blog 2026-03-30 18:01:41 +03:00
d6d0f529b8 fix rss 2026-03-30 18:01:38 +03:00
ClovertaTheTrilobita
dc177ec8c2
Update README-en.md 2026-03-30 12:34:49 +03:00
ClovertaTheTrilobita
11222dec20
Update README.md 2026-03-30 12:32:59 +03:00
bcb93c906c update bg opacity while in phone 2026-03-29 23:47:01 +03:00
67a574e8d9 update timeline 2026-03-29 23:35:27 +03:00
f1dd997c9a added translated slot for posts 2026-03-29 22:23:23 +03:00
754717c280 udpated bg opacity 2026-03-29 12:36:07 +03:00
9d56874c4b add 404 page 2026-03-29 01:20:06 +02:00
357b283ef6 deleted animation to optimize performance 2026-03-28 23:04:57 +02:00
f346e64c2d update banner and background
update seo header
2026-03-28 22:42:16 +02:00
ec6086e605 Merge branch 'master' of https://github.com/ClovertaTheTrilobita/SanYeCao-blog 2026-03-28 21:17:15 +02:00
7811dfe44b added background 2026-03-28 21:17:09 +02:00
ClovertaTheTrilobita
1588a5addc
Format license names in README
Updated license section to format license names in code style.
2026-03-27 19:12:11 +02:00
ClovertaTheTrilobita
ff60298315
Format license information in README.md 2026-03-27 19:11:51 +02:00
ClovertaTheTrilobita
3ff69b65c8
Update license section emoji in README 2026-03-27 19:10:06 +02:00
ClovertaTheTrilobita
ae26f36b78
Update README to include license section
Add license information to the README file.
2026-03-27 19:09:52 +02:00
ClovertaTheTrilobita
1ced484e81
Update README with license details
Add licensing information for the repository.
2026-03-27 19:08:46 +02:00
ClovertaTheTrilobita
aae1fb2b2f
Add MIT License to the project 2026-03-27 19:06:30 +02:00
44 changed files with 344 additions and 147 deletions

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 ClovertaTheTrilobita
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -14,7 +14,13 @@
<br>
<img width="1670" height="889" alt="image" src="https://github.com/user-attachments/assets/e98092b4-c97c-48cc-b905-961b24874b2b" />
<p align="center">
<img
src="./docs/preview-en.png"
alt="preview-en"
style="max-width: 700px; width: 100%; height: auto;"
/>
</p>
<br>
@ -62,3 +68,10 @@ For details, see: <b>[GithubActions-en.md](docs/GithubActions-en.md)</b>.
Upload the generated `dist/` directory to your server, and configure `NGINX` to point to `index.html`.
<hr>
## ⚖️ License
The source code in this repository is licensed under the `MIT License`.
Unless otherwise stated, all blog posts and other original non-code content in this repository are licensed under `CC BY-NC-ND 4.0`.

View file

@ -15,7 +15,13 @@
<br>
<img width="1670" height="889" alt="image" src="https://github.com/user-attachments/assets/ded8f5ae-7f48-4b62-a79d-6b482fc77764" />
<p align="center">
<img
src="./docs/preview-zh.png"
alt="preview-zh"
style="max-width: 700px; width: 100%; height: auto;"
/>
</p>
<br>
@ -62,3 +68,11 @@
#### 手动部署
将生成的`dist/`目录上传至你的服务器,使用`NGINX`指向index.html。
<hr>
## ⚖️ 许可
本仓库中的源代码部分采用 `MIT License` 开源。
除非另有说明,本仓库中的博客文章、其他原创的非代码内容采用 `CC BY-NC-ND 4.0` 协议。

BIN
docs/preview-en.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 587 KiB

BIN
docs/preview-zh.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 565 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 19 KiB

61
src/blog/en/post-3.md Normal file
View file

@ -0,0 +1,61 @@
---
title: "[Study Notes] A Step-by-Step Analysis of Why Peterson's Algorithm Does Not Deadlock"
pubDate: 2025-06-10
description: "Study notes on Peterson's Algorithm"
author: "Cloverta"
image:
url: "https://files.seeusercontent.com/2026/03/25/sTq9/pasted-image-1774456630694.webp"
alt: "zako2"
tags: ["Peterson's algorithm", "Operating System"]
---
In my OS course, I came across an interesting algorithm — Peterson's Algorithm. So why does Peterson's Algorithm satisfy the three conditions: "mutual exclusion", "progress", and "bounded waiting"?
First, here is the pseudocode:
```cpp
bool flag[2]; // Array indicating intention to enter critical section, initially false
int turn = 0; // turn indicates which process is given priority to enter the critical section
// Process P0
flag[0] = true; // First set its own flag to true, declaring it needs the critical section
turn = 1; // Let P1 execute first if P1 needs the critical section
while (flag[1] && turn == 1); // Check if P1 needs the critical section
CRITICAL_SECTION;
flag[0] = false;
REMAINDER_SECTION;
// Process P1
flag[1] = true;
turn = 0;
while (flag[0] && turn == 0);
CRITICAL_SECTION;
flag[1] = false;
REMAINDER_SECTION;
```
Let's analyze it case by case.
Assume that P0 and P1 are executing concurrently, and coincidentally they both complete the first step together — both of their flags are false.
At this point:
> **[Case 1]**
> If P0 gets on the CPU first, it sets turn = 1;
> P1 gets on the CPU, sets turn = 0;
> P0 gets on the CPU, checks flag and turn — finds turn has been changed to 0, the waiting condition is not met, so P0 enters the critical section;
> P1 gets on the CPU, checks flag and turn — finds flag[0] is true and turn is unchanged, so P1 waits.
> P0 gets on the CPU and finishes using the critical section, sets flag[1] = false;
> P1 gets on the CPU, finds flag[0] is false, stops waiting and enters the critical section;
>
> **[Case 2]**
> If P0 gets on the CPU first, sets turn = 1;
> P0 continues using the CPU, finds flag[0] is true and turn is still 1, the waiting condition is met, so P0 waits;
> P1 gets on the CPU, sets turn = 0;
> P1 continues using the CPU, finds flag[1] is true and turn is still 0, the waiting condition is met, so P1 waits;
> P0 gets on the CPU, finds turn has become 0, the waiting condition is not met, so P0 exits the wait and enters the critical section;
> P1 gets on the CPU, finds the waiting condition still holds, so P1 continues waiting;
> P0 gets on the CPU and finishes using the CPU, sets flag[0] = false;
> P1 gets on the CPU, finds flag[0] == false, the waiting condition is not met, stops waiting and enters the critical section;
_YES, IT WORKS ON MY MACHINE._

24
src/blog/zh/post-1.md Normal file
View file

@ -0,0 +1,24 @@
---
title: '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试'
pubDate: 2022-07-01
description: 'This is the first post of my new Astro blog.'
author: 'Astro Learner'
image:
url: 'https://s2.loli.net/2022/05/01/UNzy8c6pTHBSuMO.jpg'
alt: 'The Astro logo on a dark background with a pink glow.'
tags: ["astro", "blogging", "learning in public", "Hello"]
---
Welcome to my _new blog_ about learning Astro! Here, I will share my learning journey as I build a new website.
## What I've accomplished
1. **Installing Astro**: First, I created a new Astro project and set up my online accounts.
2. **Making Pages**: I then learned how to make pages by creating new `.astro` files and placing them in the `src/pages/` folder.
3. **Making Blog Posts**: This is my first blog post! I now have Astro pages and Markdown posts!
## What's next
I will finish the Astro tutorial, and then keep adding more posts. Watch this space for more to come.

24
src/blog/zh/post-2.md Normal file
View file

@ -0,0 +1,24 @@
---
title: 'My Second Blog Post'
pubDate: 2022-07-01
description: 'This is the first post of my new Astro blog.'
author: 'Astro Learner'
image:
url: 'https://files.seeusercontent.com/2026/03/25/0rSi/rikka-manga.jpeg'
alt: 'The Astro logo on a dark background with a pink glow.'
tags: ["astro", "blogging", "learning in public"]
---
Welcome to my _new blog_ about learning Astro! Here, I will share my learning journey as I build a new website.
## What I've accomplished
1. **Installing Astro**: First, I created a new Astro project and set up my online accounts.
2. **Making Pages**: I then learned how to make pages by creating new `.astro` files and placing them in the `src/pages/` folder.
3. **Making Blog Posts**: This is my first blog post! I now have Astro pages and Markdown posts!
## What's next
I will finish the Astro tutorial, and then keep adding more posts. Watch this space for more to come.

View file

@ -13,7 +13,7 @@ tags: ["peterson算法", "操作系统"]
先上伪代码:
```
```cpp
bool flag[2]; // 表示进入临界区意愿的数组初始值都为false
int turn = 0; // turn表示优先让哪个进程进入临界区

View file

@ -13,15 +13,39 @@ const t = getTranslations(lang);
</div>
<nav class="header-nav">
<h1>
<a href="/" data-astro-reload>{t.banner.title}</a>
</h1>
<div class="banner">
<a
href={`/${lang}/`}
data-astro-reload
class="banner-link"
aria-label="banner"
>
<span class="banner-logo"></span>
</a>
</div>
<Navigation />
</nav>
</header>
<style>
.header-nav h1 a {
.banner-link {
display: inline-block;
}
.banner-logo {
display: block;
height: 55px; /* 按你的 banner 比例改 */
background-color: #1f2328;
-webkit-mask: url("/images/banner-black.svg") no-repeat left / contain;
mask: url("/images/banner-black.svg") no-repeat left / contain;
}
:global(html.dark .banner-logo) {
background-color: #e6e6e6;
}
.header-nav .banner a {
color: inherit;
text-decoration: none;
display: block;
@ -45,13 +69,13 @@ const t = getTranslations(lang);
gap: 1rem;
}
.header-nav h1 {
.header-nav .banner {
margin: 0;
font-style: italic;
line-height: 1.1;
/* 给右上角 ThemeIcon 留空间 */
max-width: calc(100% - 4rem);
max-width: calc(100% - 7rem);
/* 桌面正常,手机自动缩小 */
font-size: clamp(1.6rem, 6vw, 2.5rem);

View file

@ -7,21 +7,21 @@ const t = getTranslations(lang);
<nav class="site-nav" aria-label="Site navigation">
<div class="site-nav-desktop">
<a href={`/${lang}`} data-astro-reload>{t.nav.home}</a>
<a href={`/${lang}/about`}>{t.nav.about}</a>
<a href={`/${lang}/tags`}>{t.nav.tags}</a>
<a href={`/${lang}/timeline`}>{t.nav.timeline}</a>
<a href={`/${lang}/friends`}>{t.nav.friends}</a>
<a href={`/${lang}/`} data-astro-reload>{t.nav.home}</a>
<a href={`/${lang}/about/`}>{t.nav.about}</a>
<a href={`/${lang}/tags/`}>{t.nav.tags}</a>
<a href={`/${lang}/timeline/`}>{t.nav.timeline}</a>
<a href={`/${lang}/friends/`}>{t.nav.friends}</a>
</div>
<details class="site-nav-mobile">
<summary>☰ {lang === "zh" ? "导航栏" : "Menu"}</summary>
<div class="dropdown-menu">
<a href={`/${lang}`} data-astro-reload>{t.nav.home}</a>
<a href={`/${lang}/about`}>{t.nav.about}</a>
<a href={`/${lang}/tags`}>{t.nav.tags}</a>
<a href={`/${lang}/timeline`}>{t.nav.timeline}</a>
<a href={`/${lang}/friends`}>{t.nav.friends}</a>
<a href={`/${lang}/`} data-astro-reload>{t.nav.home}</a>
<a href={`/${lang}/about/`}>{t.nav.about}</a>
<a href={`/${lang}/tags/`}>{t.nav.tags}</a>
<a href={`/${lang}/timeline/`}>{t.nav.timeline}</a>
<a href={`/${lang}/friends/`}>{t.nav.friends}</a>
</div>
</details>
</nav>

View file

@ -19,7 +19,7 @@ const data = Astro.props;
</div>
</div>
<img src={data.img} alt={data.title} class="post-image" />
<img src={data.img} alt={data.title} class="post-image" loading="lazy" />
</a>
</li>
@ -52,7 +52,7 @@ const data = Astro.props;
}
.post-title {
font-family: "Recursive Mono", "Maple Mono CN";
font-family: "Maple Mono", "Maple Mono CN";
color: inherit;
font-weight: 700;
font-size: 1.34rem;

View file

@ -79,7 +79,12 @@ const sortedPosts = [...allPosts].sort(
new Date(b.data.pubDate).getTime() - new Date(a.data.pubDate).getTime(),
);
const latestPosts = sortedPosts.slice(0, 5);
const filteredPosts = sortedPosts.filter((post: any) => {
const postLang = post.id.split("/")[0];
return postLang === lang;
});
const latestPosts = filteredPosts.slice(0, 5);
---
<ul>
@ -89,7 +94,10 @@ const latestPosts = sortedPosts.slice(0, 5);
.toISOString()
.split("T")[0];
const pathname = `/${post.id}/`;
const [postLang, ...slugParts] = post.id.split("/");
const slug = slugParts.join("/");
const pathname = `/${slug}/`;
const matchedDiscussion = discussions.find((d: DiscussionNode) => {
return normalizePath(d.title) === normalizePath(pathname);
@ -106,7 +114,7 @@ const latestPosts = sortedPosts.slice(0, 5);
return (
<PostItem
url={`/${lang}/posts/${post.id}/`}
url={`/${postLang}/posts/${slug}/`}
title={post.data.title}
description={post.data.description}
date={formattedDate}

View file

@ -11,7 +11,12 @@ const sortedPosts = [...allPosts].sort(
new Date(b.data.pubDate).getTime() - new Date(a.data.pubDate).getTime(),
);
const groupedPosts = sortedPosts.reduce((acc: any[], post: any) => {
const filteredPosts = sortedPosts.filter((post: any) => {
const postLang = post.id.split("/")[0];
return postLang === lang;
});
const groupedPosts = filteredPosts.reduce((acc: any[], post: any) => {
const month = new Date(post.data.pubDate).toISOString().slice(0, 7);
const lastGroup = acc[acc.length - 1];
@ -38,18 +43,25 @@ const groupedPosts = sortedPosts.reduce((acc: any[], post: any) => {
<p class="post-date">{group.month}</p>
<div class="month-posts">
{group.posts.map((post: any) => (
{group.posts.map((post: any) => {
const [postLang, ...slugParts] = post.id.split("/");
const slug = slugParts.join("/");
return (
<a
href={`/${lang}/posts/${post.id}/`}
href={`/${lang}/posts/${slug}/`}
class="timeline-card"
data-astro-reload
>
<h2 class="post-title">{post.data.title}</h2>
<h2 class="post-title">
{post.data.title}
</h2>
<p class="post-description">
{post.data.description}
</p>
</a>
))}
);
})}
</div>
</div>
</li>

View file

@ -16,7 +16,7 @@ const blog = defineCollection({
url: z.string(),
alt: z.string()
}),
tags: z.array(z.string())
tags: z.array(z.string()),
})
});

View file

@ -1,7 +1,7 @@
export default {
banner: {
title: "Cloverta's Blog",
subtitle: ""
subtitle: "More to explore here (kinda) — welcome to Cloverta's blog 🥳"
},
nav: {
home: "Home",
@ -51,7 +51,7 @@ export default {
description: "All tags that have appeared across the blog are collected here. Click a tag to jump to the corresponding list of posts."
},
footer: {
githubIntro: 'See more on <a href="https://www.github.com/ClovertaTheTrilobita">GitHub</a>!',
repoIntro: 'This blog is fully open source at <a href="https://www.github.com/ClovertaTheTrilobita/SanYeCao-blog">ClovertaTheTrilobita/SanYeCao-blog</a>'
githubIntro: 'See more on <a href="https://repo.cloverta.top/cloverta">Forgejo</a>!',
repoIntro: 'This blog is fully open source at <a href="https://repo.cloverta.top/cloverta/SanYeCao-blog">ClovertaTheTrilobita/SanYeCao-blog</a>'
}
};

View file

@ -1,7 +1,7 @@
export default {
banner: {
title: "Cloverta的博客",
subtitle: ""
subtitle: "在这里,发现更多(雾)欢迎来到三叶的博客🥳"
},
nav: {
home: "首页",
@ -51,7 +51,7 @@ export default {
description: "在这里收集着整篇博客出现过的标签,点击标签跳转对应的文章列表。",
},
footer: {
githubIntro: '在 <a href="https://www.github.com/ClovertaTheTrilobita">GitHub</a> 查看更多!',
repoIntro: '这个博客完全开源于 <a href="https://www.github.com/ClovertaTheTrilobita/SanYeCao-blog">ClovertaTheTrilobita/SanYeCao-blog</a>'
githubIntro: '在 <a href="https://repo.cloverta.top/cloverta">Forgejo</a> 查看更多!',
repoIntro: '这个博客完全开源于 <a href="https://repo.cloverta.top/cloverta/SanYeCao-blog">ClovertaTheTrilobita/SanYeCao-blog</a>'
}
};

View file

@ -21,11 +21,10 @@ const {
<link rel="icon" href="/favicon.ico" />
<meta name="generator" content={Astro.generator} />
<title>{pageTitle}</title>
<ClientRouter />
</head>
<body>
<Header />
<main class="page-content" transition:name="page">
<main class="page-content">
<slot />
</main>
<Footer />
@ -39,36 +38,4 @@ const {
width: 100%;
height: 100%;
}
::view-transition-old(page),
::view-transition-new(page) {
animation-duration: 0.05s;
animation-timing-function: ease;
}
::view-transition-old(page) {
animation-name: fade-out;
}
::view-transition-new(page) {
animation-name: fade-in;
}
@keyframes fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
</style>

View file

@ -9,7 +9,7 @@ const t = getTranslations(lang);
---
<BaseLayout
pageTitle={frontmatter.title}
pageTitle=`${frontmatter.title} - ${t.banner.title}`
description={frontmatter.description}
image={frontmatter.image?.url}
>

38
src/pages/404.astro Normal file
View file

@ -0,0 +1,38 @@
---
import BaseLayout from "@/layouts/BaseLayout.astro";
import "@/styles/global.css";
---
<BaseLayout
pageTitle="404 Not Found"
description="Sorry, the page doesn't exists"
>
<div class="not-found">
<img src="/images/marisa.png" alt="Marisa" class="marisa-404" />
<div class="hint">
<h3>对不起,您请求的页面不存在哦。</h3>
<h3>Sorry, the page you are requesting for doesn't exists.</h3>
</div>
</div>
</BaseLayout>
<style>
.not-found {
min-height: 70vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
gap: 1rem;
}
.marisa-404 {
width: 30%;
display: block;
}
.hint {
text-align: center;
}
</style>

View file

@ -13,7 +13,7 @@ const pageTitle = t.about.title;
---
<BaseLayout
pageTitle={pageTitle}
pageTitle=`${pageTitle} - ${t.banner.title}`
image={t.about.profilePicture}
>
<main class="about">

View file

@ -13,6 +13,6 @@ const t = getTranslations(lang);
const headerTitle = lang === "zh" ? "友情链接" : "Friends";
---
<BaseLayout pageTitle={headerTitle}>
<BaseLayout pageTitle=`${headerTitle} - ${t.banner.title}`>
<FriendlyLinkList />
</BaseLayout>

View file

@ -15,11 +15,11 @@ const headerTitle = lang === "zh" ? "Cloverta的博客" : "Cloverta's blog";
const pageTitle = t.home.title;
---
<BaseLayout pageTitle={headerTitle}>
<BaseLayout pageTitle=`${headerTitle} - ${t.banner.subtitle}`>
<h1 class="page-title">
<span>{pageTitle}</span>
<a
href={`${import.meta.env.SITE}/rss.xml`}
href={`/rss.xml`}
target="_blank"
rel="noopener noreferrer"
aria-label="RSS Feed"

View file

@ -4,26 +4,30 @@ import MarkdownPostLayout from "@/layouts/MarkdownPostLayout.astro";
export async function getStaticPaths() {
const posts = await getCollection("blog");
const langs = ["zh", "en"];
return langs.flatMap((lang) =>
posts.map((post) => ({
return posts.map((post) => {
const [lang, ...slugParts] = post.id.split("/");
return {
params: {
lang,
slug: post.id,
slug: slugParts.join("/"),
},
props: {
post,
lang,
},
})),
);
};
});
}
const { post, lang } = Astro.props;
const { Content } = await render(post);
const [postLang, ...slugParts] = post.id.split("/");
const slug = slugParts.join("/");
---
<MarkdownPostLayout frontmatter={post.data} lang={lang} postId={post.id}>
<MarkdownPostLayout frontmatter={post.data} lang={lang} postId={slug}>
<Content />
</MarkdownPostLayout>

View file

@ -15,7 +15,7 @@ const tags = [...new Set(allPosts.map((post: any) => post.data.tags).flat())];
const pageTitle = lang === "zh" ? "标签索引" : "Tag Index";
---
<BaseLayout pageTitle={pageTitle}>
<BaseLayout pageTitle=`${pageTitle} - ${t.banner.title}` `>
<h1>{t.tags.title}</h1>
<p>{t.tags.description}</p>

View file

@ -13,7 +13,7 @@ const t = getTranslations(lang);
const headerTitle = lang === "zh" ? "时间轴" : "Timeline";
---
<BaseLayout pageTitle={headerTitle}>
<BaseLayout pageTitle=`${headerTitle} - ${t.banner.title}` `>
<h1>{t.nav.timeline}</h1>
<PostTimeline />
</BaseLayout>

View file

@ -4,17 +4,23 @@ import { getCollection } from 'astro:content';
export async function GET(context) {
const posts = await getCollection("blog");
return rss({
title: 'Cloverta的博客',
description: '在这里,发现更多(雾)欢迎来到三叶的博客🥳',
site: context.site,
items: await pagesGlobToRssItems(import.meta.glob('./**/*.md')),
items: posts.map((post) => ({
items: posts.map((post) => {
const [postLang, ...slugParts] = post.id.split("/");
const slug = slugParts.join("/");
return ({
title: post.data.title,
pubDate: post.data.pubDate,
description: post.data.description,
link: `/posts/${post.id}/`,
})),
link: `/${postLang}/posts/${slug}/`,
})
}),
customData: `<language>en-us</language>`,
})
}

View file

@ -2,30 +2,6 @@
@import url("https://unpkg.com/@fontsource/maple-mono@5.2.6/400-italic.css");
@import url("https://unpkg.com/@fontsource/maple-mono@5.2.6/700.css");
/* @font-face {
font-family: "Maple Mono";
src: url("/fonts/MapleMono-Regular.ttf.woff2") format("woff2");
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Maple Mono";
src: url("/fonts/MapleMono-Italic.ttf.woff2") format("woff2");
font-weight: 400;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: "Maple Mono";
src: url("/fonts/MapleMono-Bold.ttf.woff2") format("woff2");
font-weight: 700;
font-style: normal;
font-display: swap;
} */
@font-face {
font-family: "Maple Mono CN";
src: url("/fonts/subset/MapleMono-CN-Regular.woff2") format("woff2");
@ -50,30 +26,6 @@
font-display: swap;
}
@font-face {
font-family: "Recursive Mono";
src: url("/fonts/RecursiveMonoCslSt-Bold.woff2") format("woff2");
font-weight: 700;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Recursive Mono";
src: url("/fonts/RecursiveMonoCslSt-Regular.woff2") format("woff2");
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Recursive Mono";
src: url("/fonts/RecursiveMonoCslSt-Italic.woff2") format("woff2");
font-weight: 400;
font-style: italic;
font-display: swap;
}
pre {
padding: 1rem;
border-radius: 0.5rem;
@ -111,6 +63,34 @@ body {
line-height: 1.7;
}
body::after {
content: "";
position: fixed;
right: 0;
bottom: 0;
width: 400px;
/* 按需调整大小 */
height: 400px;
/* 按需调整大小 */
background-image: url("https://files.seeusercontent.com/2026/03/30/4Xfr/bc7e804dc2c8ecaf407c9d665414ff72.webp");
background-repeat: no-repeat;
background-position: right bottom;
background-size: contain;
opacity: 0.35;
pointer-events: none;
z-index: -1;
}
html.dark body::after {
background-image: url("https://files.seeusercontent.com/2026/03/30/vd8W/touhou___alice_margatroid_x_kiri.webp");
}
@media (max-width: 768px) {
body::after {
opacity: 0.06;
}
}
* {
box-sizing: border-box;
}
@ -123,7 +103,7 @@ h1 {
a {
color: #7fb3ff;
color: #416bd6;
font-weight: 700;
text-decoration: none;
}