diff --git a/app/blog/[slug]/page.tsx b/app/blog/[slug]/page.tsx index d815752..58139c0 100644 --- a/app/blog/[slug]/page.tsx +++ b/app/blog/[slug]/page.tsx @@ -58,7 +58,9 @@ export default function BlogPostPage({ params }: Props) { {post.tags.map((t) => ( #{t} diff --git a/app/tags/[tag]/page.tsx b/app/tags/[tag]/page.tsx index cccbc5b..6aefb07 100644 --- a/app/tags/[tag]/page.tsx +++ b/app/tags/[tag]/page.tsx @@ -1,17 +1,18 @@ import type { Metadata } from 'next'; import { allPosts } from 'contentlayer/generated'; import { PostListItem } from '@/components/post-list-item'; +import { getTagSlug } from '@/lib/posts'; export function generateStaticParams() { - const tags = new Set(); + const slugs = new Set(); for (const post of allPosts) { if (!post.tags) continue; for (const tag of post.tags) { - tags.add(tag); + slugs.add(getTagSlug(tag)); } } - return Array.from(tags).map((tag) => ({ - tag + return Array.from(slugs).map((slug) => ({ + tag: slug })); } @@ -20,23 +21,31 @@ interface Props { } export function generateMetadata({ params }: Props): Metadata { - const tag = params.tag; + const slug = params.tag; + // Find original tag label by slug + const tag = allPosts + .flatMap((post) => post.tags ?? []) + .find((t) => getTagSlug(t) === slug); + return { - title: `標籤:${tag}` + title: tag ? `標籤:${tag}` : '標籤' }; } export default function TagPage({ params }: Props) { - const tag = params.tag; + const slug = params.tag; const posts = allPosts.filter( - (post) => post.tags && post.tags.includes(tag) + (post) => post.tags && post.tags.some((t) => getTagSlug(t) === slug) ); + const tagLabel = + posts[0]?.tags?.find((t) => getTagSlug(t) === slug) ?? params.tag; + return (

- 標籤:{tag} + 標籤:{tagLabel}

    {posts.map((post) => ( @@ -46,4 +55,3 @@ export default function TagPage({ params }: Props) {
); } - diff --git a/components/post-list-item.tsx b/components/post-list-item.tsx index 937804f..99382fb 100644 --- a/components/post-list-item.tsx +++ b/components/post-list-item.tsx @@ -45,7 +45,9 @@ export function PostListItem({ post }: Props) { {post.tags.slice(0, 4).map((t) => ( #{t} diff --git a/components/right-sidebar.tsx b/components/right-sidebar.tsx index 71a1f4d..e75f1d3 100644 --- a/components/right-sidebar.tsx +++ b/components/right-sidebar.tsx @@ -41,7 +41,7 @@ export function RightSidebar() { 標籤雲
- {tags.map(({ tag, count }) => { + {tags.map(({ tag, slug, count }) => { let sizeClass = 'text-[11px]'; if (count >= 5) sizeClass = 'text-sm font-semibold'; else if (count >= 3) sizeClass = 'text-xs font-medium'; @@ -49,7 +49,7 @@ export function RightSidebar() { return ( {tag} diff --git a/lib/posts.ts b/lib/posts.ts index 1c76a05..d9c26db 100644 --- a/lib/posts.ts +++ b/lib/posts.ts @@ -26,7 +26,11 @@ export function getPageBySlug(slug: string): Page | undefined { ); } -export function getAllTagsWithCount(): { tag: string; count: number }[] { +export function getTagSlug(tag: string): string { + return encodeURIComponent(tag.toLowerCase().replace(/\s+/g, '-')); +} + +export function getAllTagsWithCount(): { tag: string; slug: string; count: number }[] { const map = new Map(); for (const post of allPosts) { @@ -37,7 +41,7 @@ export function getAllTagsWithCount(): { tag: string; count: number }[] { } return Array.from(map.entries()) - .map(([tag, count]) => ({ tag, count })) + .map(([tag, count]) => ({ tag, slug: getTagSlug(tag), count })) .sort((a, b) => { if (b.count === a.count) return a.tag.localeCompare(b.tag); return b.count - a.count;