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
This commit is contained in:
@@ -204,4 +204,106 @@ export function extractTags(posts: any[]): Map<string, string> {
|
||||
*/
|
||||
export function getBlogBaseUrl(lang: Lang): string {
|
||||
return lang === defaultLang ? '/blog' : `/${lang}/blog`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process raw blog post data from import.meta.glob
|
||||
* @param allPosts - Raw posts data from import.meta.glob
|
||||
* @param lang - Current language
|
||||
* @returns Processed blog posts array
|
||||
*/
|
||||
export function processRawBlogPosts(allPosts: Record<string, any>[] | any[], lang: Lang): BlogPost[] {
|
||||
// Process blog post data
|
||||
const posts: BlogPost[] = 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";
|
||||
|
||||
// Default read time text based on language
|
||||
const defaultReadTime = lang === 'zh' ? '5 分钟阅读' : '5 min read';
|
||||
|
||||
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 || defaultReadTime,
|
||||
url: post.url || '',
|
||||
};
|
||||
});
|
||||
|
||||
return posts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract post metadata for categories and tags
|
||||
* @param posts - Array of blog posts
|
||||
* @returns Array of post metadata
|
||||
*/
|
||||
export function extractPostMetadata(posts: any[]) {
|
||||
return posts.map((post: any) => ({
|
||||
category: post.frontmatter?.category || [],
|
||||
categoryId: post.frontmatter?.categoryId || [],
|
||||
tags: post.frontmatter?.tags || [],
|
||||
tagId: post.frontmatter?.tagId || []
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all blog posts with processing for a taxonomy page (category or tag)
|
||||
* @param lang - Current language
|
||||
* @param options - Additional options for processing
|
||||
* @returns Object containing processed posts and metadata
|
||||
*/
|
||||
export async function getTaxonomyPageData(lang: Lang, options?: {
|
||||
category?: string;
|
||||
tag?: string;
|
||||
}) {
|
||||
// Read all blog posts
|
||||
// Note: import.meta.glob only accepts literal strings, not variables
|
||||
let allPosts;
|
||||
|
||||
// Use specific glob patterns based on language
|
||||
if (lang === 'zh') {
|
||||
allPosts = await import.meta.glob('/src/pages/zh/blog/posts/*.{md,mdx}', { eager: true });
|
||||
} else {
|
||||
allPosts = await import.meta.glob('/src/pages/blog/posts/*.{md,mdx}', { eager: true });
|
||||
}
|
||||
|
||||
// Process blog post data
|
||||
const blogPosts = processRawBlogPosts(Object.values(allPosts), lang);
|
||||
|
||||
// Apply filters if specified
|
||||
let filteredPosts = blogPosts;
|
||||
|
||||
if (options?.category) {
|
||||
filteredPosts = filterPostsByCategory(filteredPosts, options.category);
|
||||
}
|
||||
|
||||
if (options?.tag) {
|
||||
filteredPosts = filterPostsByTag(filteredPosts, options.tag);
|
||||
}
|
||||
|
||||
// Sort posts by date
|
||||
const sortedBlogPosts = sortPostsByDate(filteredPosts);
|
||||
|
||||
// Extract categories and tags from all posts for sidebar
|
||||
const allPostsMetadata = extractPostMetadata(Object.values(allPosts));
|
||||
|
||||
// Get categories and tags for sidebar
|
||||
const categories = extractCategories(allPostsMetadata);
|
||||
const tags = extractTags(allPostsMetadata);
|
||||
|
||||
return {
|
||||
posts: sortedBlogPosts,
|
||||
categories,
|
||||
tags,
|
||||
allPosts
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user