From 21fba08741853d76ec868bf47b2a601c7a4d6ac0 Mon Sep 17 00:00:00 2001 From: joyzhao Date: Thu, 19 Jun 2025 17:22:27 +0800 Subject: [PATCH] feat(taxonomy): add unified taxonomy page layout and utilities refactor blog category and tag pages to use new TaxonomyPageLayout add utility functions for processing taxonomy page data pass lang prop to GlassHeader component --- src/layouts/BlogLayout.astro | 2 +- src/layouts/TaxonomyPageLayout.astro | 95 +++++++++++++++ src/pages/blog/categories/[category].astro | 113 +++--------------- src/pages/blog/tags/[tag].astro | 111 +++-------------- src/pages/zh/blog/categories/[category].astro | 111 +++-------------- src/pages/zh/blog/tags/[tag].astro | 111 +++-------------- src/utils/blog-utils.ts | 102 ++++++++++++++++ 7 files changed, 262 insertions(+), 383 deletions(-) create mode 100644 src/layouts/TaxonomyPageLayout.astro diff --git a/src/layouts/BlogLayout.astro b/src/layouts/BlogLayout.astro index 4f887d3..03811d8 100644 --- a/src/layouts/BlogLayout.astro +++ b/src/layouts/BlogLayout.astro @@ -39,7 +39,7 @@ const lang = Astro.currentLocale as Lang || defaultLang;
- +
diff --git a/src/layouts/TaxonomyPageLayout.astro b/src/layouts/TaxonomyPageLayout.astro new file mode 100644 index 0000000..84bfa30 --- /dev/null +++ b/src/layouts/TaxonomyPageLayout.astro @@ -0,0 +1,95 @@ +--- +/** + * TaxonomyPageLayout component + * A unified layout for category and tag pages + */ +import BlogLayout from './BlogLayout.astro'; +import BlogList from '../components/blog/BlogList.astro'; +import CategoryCard from '../components/blog/CategoryCard.astro'; +import TagCard from '../components/blog/TagCard.astro'; +import { type Lang } from '@/i18n/utils'; +import { defaultLang } from '@/i18n/ui'; +import { type BlogPost } from '@/types'; + +interface Props { + lang: Lang; + title: string; + description?: string; + taxonomyType: 'category' | 'tag'; + currentTaxonomy: string; + displayName?: string; + posts: BlogPost[]; + categories: Map; + tags: Map; +} + +const { + lang, + title, + taxonomyType, + currentTaxonomy, + displayName, + posts, + categories, + tags +} = Astro.props; + +// Get localized text based on language and taxonomy type +const getLocalizedText = () => { + if (taxonomyType === 'category') { + return { + heading: lang === 'zh' ? '分类' : 'Category', + noResults: lang === 'zh' ? '该分类下没有文章' : 'No posts in this category', + }; + } else { + return { + heading: lang === 'zh' ? '标签' : 'Tag', + noResults: lang === 'zh' ? '该标签下没有文章' : 'No posts with this tag', + }; + } +}; + +const localizedText = getLocalizedText(); +--- + + +
+ +
+

+ {displayName || currentTaxonomy} +

+ +

+ {localizedText.heading}: {posts.length} {lang === 'zh' ? '篇文章' : 'posts'} +

+
+ + +
+ +
+ + + +
+ + +
+ {posts.length > 0 ? ( + + ) : ( +
+

{localizedText.noResults}

+
+ )} +
+
+
+
\ No newline at end of file diff --git a/src/pages/blog/categories/[category].astro b/src/pages/blog/categories/[category].astro index 4a8edc0..2ecbb01 100644 --- a/src/pages/blog/categories/[category].astro +++ b/src/pages/blog/categories/[category].astro @@ -1,12 +1,8 @@ --- -import BlogLayout from '../../../layouts/BlogLayout.astro'; -import BlogList from '../../../components/blog/BlogList.astro'; -import CategoryCard from '../../../components/blog/CategoryCard.astro'; -import TagCard from '../../../components/blog/TagCard.astro'; +import TaxonomyPageLayout from '../../../layouts/TaxonomyPageLayout.astro'; import { type Lang } from '@/i18n/utils'; import { defaultLang } from '@/i18n/ui'; -import { type BlogPost } from '@/types'; -import { filterPostsByCategory, sortPostsByDate, extractCategories, extractTags } from '@/utils/blog-utils'; +import { getTaxonomyPageData } from '@/utils/blog-utils'; // Generate static paths for dynamic routing export async function getStaticPaths() { @@ -56,35 +52,9 @@ export interface Props { const { category } = Astro.params; const decodedCategory = category ? decodeURIComponent(category) : ''; -// Read all blog posts using import.meta.glob -const allPosts = await import.meta.glob('../posts/*.md', { eager: true }); - -// Process blog post data -const blogPosts: BlogPost[] = Object.values(allPosts).map((post: any) => { - const slug = post.url?.split('/').filter(Boolean).pop() || ''; - - // Default image if not specified in frontmatter - const defaultImage = "https://images.unsplash.com/photo-1516321318423-f06f85e504b3?w=400&h=250&fit=crop&crop=center"; - - return { - title: post.frontmatter.title, - description: post.frontmatter.description || '', - image: post.frontmatter.image || defaultImage, - slug: slug, - tags: post.frontmatter.tags || [], - tagId: post.frontmatter.tagId || [], - category: Array.isArray(post.frontmatter.category) ? post.frontmatter.category : post.frontmatter.category ? [post.frontmatter.category] : [], - categoryId: Array.isArray(post.frontmatter.categoryId) ? post.frontmatter.categoryId : post.frontmatter.categoryId ? [post.frontmatter.categoryId] : [], - date: post.frontmatter.date || post.frontmatter.pubDate || '', - readTime: post.frontmatter.readTime || post.frontmatter.readingTime || '5 min read', - }; -}); - -// Filter posts by category -const filteredPosts = filterPostsByCategory(blogPosts, decodedCategory); - -// Sort posts by date -const sortedBlogPosts = sortPostsByDate(filteredPosts); +// Get taxonomy page data using the utility function +const { posts: sortedBlogPosts, categories, tags, allPosts } = + await getTaxonomyPageData(lang, { category: decodedCategory }); // Find category name matching the current category ID let categoryName = decodedCategory; @@ -118,70 +88,19 @@ Object.values(allPosts).forEach((post: any) => { // Page title and description const title = `${categoryName} - Blog | Joy Zhao`; const description = `Explore articles about ${categoryName}. Dive into my thoughts on ${categoryName} and related topics.`; - -// Extract categories and tags from all posts for sidebar -const allPostsArray = Object.values(allPosts).map((post: any) => ({ - category: post.frontmatter.category || [], - categoryId: post.frontmatter.categoryId || [], - tags: post.frontmatter.tags || [], - tagId: post.frontmatter.tagId || [] -})); - -// Get categories and tags for sidebar - -// Get categories and tags for sidebar -const categories = extractCategories(allPostsArray); -const tags = extractTags(allPostsArray); --- - -
- -
-
-

- Category: {categoryName} -

-

- Explore articles about {categoryName}. Found {sortedBlogPosts.length} article{sortedBlogPosts.length !== 1 ? 's' : ''}. -

-
-
- - -
-
- -
- - - - - - -
- - -
- {sortedBlogPosts.length > 0 ? ( - - ) : ( -
-

No articles found

-

There are no articles in this category yet. Check back later or explore other categories.

- - - - - Back to all posts - -
- )} -
-
-
-
-
+