更换到Astro #9
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
import type { BlogPost } from '@/lib/posts';
|
import { getCategoryHref, type BlogPost } from '@/lib/posts';
|
||||||
|
|
||||||
type TocItem = {
|
type TocItem = {
|
||||||
depth: number;
|
depth: number;
|
||||||
@@ -38,7 +38,7 @@ const tocSections = toc.reduce<TocSection[]>((sections, item) => {
|
|||||||
<div class="profile-name">biss</div>
|
<div class="profile-name">biss</div>
|
||||||
<div class="article-author-meta">
|
<div class="article-author-meta">
|
||||||
<span>{post.dateText}</span>
|
<span>{post.dateText}</span>
|
||||||
{post.categories[0] && <a href={`/categories/${encodeURIComponent(post.categories[0])}/`}>{post.categories[0]}</a>}
|
{post.categories[0] && <a href={getCategoryHref(post.categories[0])}>{post.categories[0]}</a>}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
import type { BlogPost } from '@/lib/posts';
|
import { getCategoryHref, type BlogPost } from '@/lib/posts';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
post: BlogPost;
|
post: BlogPost;
|
||||||
@@ -15,7 +15,7 @@ const { post } = Astro.props;
|
|||||||
{post.summary && <p>{post.summary}</p>}
|
{post.summary && <p>{post.summary}</p>}
|
||||||
</a>
|
</a>
|
||||||
<div class="meta-list">
|
<div class="meta-list">
|
||||||
{post.categories.map((category) => <a href={`/categories/${encodeURIComponent(category)}/`}>{category}</a>)}
|
{post.categories.map((category) => <a href={getCategoryHref(category)}>{category}</a>)}
|
||||||
{post.tags.map((tag) => <a href={`/tags/${encodeURIComponent(tag)}/`}>#{tag}</a>)}
|
{post.tags.map((tag) => <a href={`/tags/${encodeURIComponent(tag)}/`}>#{tag}</a>)}
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|||||||
@@ -16,6 +16,14 @@ export type BlogPost = {
|
|||||||
body: string;
|
body: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const categorySlugMap: Record<string, string> = {
|
||||||
|
'技术': 'tech',
|
||||||
|
'建站手札': 'site-notes',
|
||||||
|
'学习': 'study',
|
||||||
|
'生活': 'life',
|
||||||
|
'杂谈': 'notes',
|
||||||
|
};
|
||||||
|
|
||||||
function asArray(value: unknown): string[] {
|
function asArray(value: unknown): string[] {
|
||||||
if (Array.isArray(value)) return value.map(String).filter(Boolean);
|
if (Array.isArray(value)) return value.map(String).filter(Boolean);
|
||||||
if (typeof value === 'string' && value.trim()) return [value.trim()];
|
if (typeof value === 'string' && value.trim()) return [value.trim()];
|
||||||
@@ -94,3 +102,22 @@ export async function getAllTags(): Promise<string[]> {
|
|||||||
export async function getAllCategories(): Promise<string[]> {
|
export async function getAllCategories(): Promise<string[]> {
|
||||||
return [...new Set((await getAllPosts()).flatMap((post) => post.categories))].sort((a, b) => a.localeCompare(b, 'zh-CN'));
|
return [...new Set((await getAllPosts()).flatMap((post) => post.categories))].sort((a, b) => a.localeCompare(b, 'zh-CN'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getCategorySlug(category: string): string {
|
||||||
|
const mapped = categorySlugMap[category];
|
||||||
|
if (mapped) return mapped;
|
||||||
|
|
||||||
|
const slug = category
|
||||||
|
.trim()
|
||||||
|
.toLowerCase()
|
||||||
|
.normalize('NFKD')
|
||||||
|
.replace(/[\u0300-\u036f]/g, '')
|
||||||
|
.replace(/[^a-z0-9]+/g, '-')
|
||||||
|
.replace(/^-|-$/g, '');
|
||||||
|
|
||||||
|
return slug || 'category';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCategoryHref(category: string): string {
|
||||||
|
return `/categories/${getCategorySlug(category)}/`;
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
import BaseLayout from '@/layouts/BaseLayout.astro';
|
import BaseLayout from '@/layouts/BaseLayout.astro';
|
||||||
import PageHeaderCard from '@/components/PageHeaderCard.astro';
|
import PageHeaderCard from '@/components/PageHeaderCard.astro';
|
||||||
import PostCard from '@/components/PostCard.astro';
|
import PostCard from '@/components/PostCard.astro';
|
||||||
import { getAllCategories, getAllPosts } from '@/lib/posts';
|
import { getAllCategories, getAllPosts, getCategorySlug } from '@/lib/posts';
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
return (await getAllCategories()).map((category) => ({
|
return (await getAllCategories()).map((category) => ({
|
||||||
params: { category },
|
params: { category: getCategorySlug(category) },
|
||||||
props: { category },
|
props: { category },
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
import BaseLayout from '@/layouts/BaseLayout.astro';
|
import BaseLayout from '@/layouts/BaseLayout.astro';
|
||||||
import PageHeaderCard from '@/components/PageHeaderCard.astro';
|
import PageHeaderCard from '@/components/PageHeaderCard.astro';
|
||||||
import { getAllCategories, getAllPosts } from '@/lib/posts';
|
import { getAllCategories, getAllPosts, getCategoryHref } from '@/lib/posts';
|
||||||
|
|
||||||
const posts = await getAllPosts();
|
const posts = await getAllPosts();
|
||||||
const categories = await getAllCategories();
|
const categories = await getAllCategories();
|
||||||
@@ -12,7 +12,7 @@ const categories = await getAllCategories();
|
|||||||
<PageHeaderCard title="分类" subtitle={`共 ${categories.length} 个分类`} />
|
<PageHeaderCard title="分类" subtitle={`共 ${categories.length} 个分类`} />
|
||||||
<div class="term-grid">
|
<div class="term-grid">
|
||||||
{categories.map((category) => (
|
{categories.map((category) => (
|
||||||
<a href={`/categories/${encodeURIComponent(category)}/`}>
|
<a href={getCategoryHref(category)}>
|
||||||
<span>{category}</span>
|
<span>{category}</span>
|
||||||
<strong>{posts.filter((post) => post.categories.includes(category)).length}</strong>
|
<strong>{posts.filter((post) => post.categories.includes(category)).length}</strong>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import PostCopyrightCard from '@/components/PostCopyrightCard.astro';
|
|||||||
import TwikooComments from '@/components/TwikooComments.astro';
|
import TwikooComments from '@/components/TwikooComments.astro';
|
||||||
import BaseLayout from '@/layouts/BaseLayout.astro';
|
import BaseLayout from '@/layouts/BaseLayout.astro';
|
||||||
import { render } from 'astro:content';
|
import { render } from 'astro:content';
|
||||||
import { getAllPosts } from '@/lib/posts';
|
import { getAllPosts, getCategoryHref } from '@/lib/posts';
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
return (await getAllPosts()).map((post) => ({
|
return (await getAllPosts()).map((post) => ({
|
||||||
@@ -89,13 +89,13 @@ const twikooEnvId = 'https://comment.biss.click';
|
|||||||
{post.cover ? (
|
{post.cover ? (
|
||||||
<div class="article-hero-meta" aria-label="文章信息">
|
<div class="article-hero-meta" aria-label="文章信息">
|
||||||
<span>发布于 {post.dateText}</span>
|
<span>发布于 {post.dateText}</span>
|
||||||
{post.categories[0] && <a href={`/categories/${encodeURIComponent(post.categories[0])}/`}>{post.categories[0]}</a>}
|
{post.categories[0] && <a href={getCategoryHref(post.categories[0])}>{post.categories[0]}</a>}
|
||||||
<span>总字数:{wordCountText}</span>
|
<span>总字数:{wordCountText}</span>
|
||||||
<span>阅读时长:{readingMinutes} 分钟</span>
|
<span>阅读时长:{readingMinutes} 分钟</span>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div class="meta-list">
|
<div class="meta-list">
|
||||||
{post.categories.map((category) => <a href={`/categories/${encodeURIComponent(category)}/`}>{category}</a>)}
|
{post.categories.map((category) => <a href={getCategoryHref(category)}>{category}</a>)}
|
||||||
{post.tags.map((tag) => <a href={`/tags/${encodeURIComponent(tag)}/`}>#{tag}</a>)}
|
{post.tags.map((tag) => <a href={`/tags/${encodeURIComponent(tag)}/`}>#{tag}</a>)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user