feat(blog): add tagId and categoryId for multilingual routing support
- Add tagId and categoryId fields to blog post frontmatter and interfaces - Update blog list, category, and tag pages to use IDs for routing - Implement fallback to regular tags/categories when IDs are not available - Improve tag and category links with hover effects and proper encoding - Update post meta component to support multilingual routing
This commit is contained in:
@@ -9,11 +9,22 @@ import { type BlogPost } from '@/types';
|
||||
export async function getStaticPaths() {
|
||||
const allPosts = await Astro.glob('../posts/*.md');
|
||||
|
||||
// 收集所有分类
|
||||
// 收集所有分类ID或分类
|
||||
const uniqueCategories = new Set<string>();
|
||||
|
||||
allPosts.forEach(post => {
|
||||
if (post.frontmatter?.category) {
|
||||
// 优先使用 categoryId 作为路由标识符
|
||||
if (post.frontmatter?.categoryId) {
|
||||
const categoryIds = Array.isArray(post.frontmatter.categoryId)
|
||||
? post.frontmatter.categoryId
|
||||
: [post.frontmatter.categoryId];
|
||||
|
||||
categoryIds.forEach(categoryId => {
|
||||
if (categoryId) uniqueCategories.add(categoryId.toLowerCase());
|
||||
});
|
||||
}
|
||||
// 如果没有 categoryId,则使用 category 作为后备
|
||||
else if (post.frontmatter?.category) {
|
||||
const categories = Array.isArray(post.frontmatter.category)
|
||||
? post.frontmatter.category
|
||||
: [post.frontmatter.category];
|
||||
@@ -49,8 +60,18 @@ const allPosts = await Astro.glob('../posts/*.md');
|
||||
// 处理博客文章数据
|
||||
const blogPosts: BlogPost[] = allPosts
|
||||
.filter(post => {
|
||||
// 检查文章是否属于当前分类
|
||||
if (post.frontmatter?.category) {
|
||||
// 优先检查文章是否包含当前分类ID
|
||||
if (post.frontmatter?.categoryId) {
|
||||
const postCategoryIds = Array.isArray(post.frontmatter.categoryId)
|
||||
? post.frontmatter.categoryId
|
||||
: [post.frontmatter.categoryId];
|
||||
|
||||
return postCategoryIds.some(catId =>
|
||||
catId.toLowerCase() === decodedCategory.toLowerCase()
|
||||
);
|
||||
}
|
||||
// 如果没有 categoryId,则检查 category
|
||||
else if (post.frontmatter?.category) {
|
||||
const postCategories = Array.isArray(post.frontmatter.category)
|
||||
? post.frontmatter.category
|
||||
: [post.frontmatter.category];
|
||||
@@ -114,7 +135,7 @@ allPosts.forEach(post => {
|
||||
|
||||
// 转换为数组并排序
|
||||
const categories = Array.from(allCategories).sort();
|
||||
const tags = Array.from(allTags).map(tag => `#${tag}`).sort();
|
||||
const tags = Array.from(allTags).map(tag => `# ${tag}`).sort();
|
||||
|
||||
// 获取当前分类的格式化名称(首字母大写)
|
||||
const formattedCategory = decodedCategory.charAt(0).toUpperCase() + decodedCategory.slice(1);
|
||||
@@ -171,7 +192,7 @@ const pageDescription = `Explore articles about ${formattedCategory}. Dive into
|
||||
</h3>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
{tags.map((tag) => (
|
||||
<a href={`/blog/tags/${encodeURIComponent(tag.slice(1).toLowerCase())}`}
|
||||
<a href={`/blog/tags/${encodeURIComponent(tag.slice(2).toLowerCase())}`}
|
||||
class="inline-block px-3 py-1 text-sm bg-muted text-muted-foreground rounded-full hover:bg-purple-500/20 hover:text-purple-500 transition-all duration-200">
|
||||
{tag}
|
||||
</a>
|
||||
|
||||
@@ -24,6 +24,9 @@ const blogPosts: BlogPost[] = allPosts.map((post) => {
|
||||
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',
|
||||
};
|
||||
@@ -65,7 +68,7 @@ allPosts.forEach(post => {
|
||||
|
||||
// 转换为数组并排序
|
||||
const categories = Array.from(allCategories).sort();
|
||||
const tags = Array.from(allTags).map(tag => `#${tag}`).sort();
|
||||
const tags = Array.from(allTags).map(tag => `# ${tag}`).sort();
|
||||
|
||||
---
|
||||
|
||||
@@ -98,7 +101,7 @@ const tags = Array.from(allTags).map(tag => `#${tag}`).sort();
|
||||
</h3>
|
||||
<div class="space-y-2">
|
||||
{categories.map((category) => (
|
||||
<a href={`/blog/categories/${category.toLowerCase()}`}
|
||||
<a href={`/blog/categories/${encodeURIComponent(category.toLowerCase())}`}
|
||||
class="block text-muted-foreground hover:text-purple-500 transition-colors duration-200">
|
||||
{category}
|
||||
</a>
|
||||
@@ -116,7 +119,7 @@ const tags = Array.from(allTags).map(tag => `#${tag}`).sort();
|
||||
</h3>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
{tags.map((tag) => (
|
||||
<a href={`/blog/tags/${tag.slice(1).toLowerCase()}`}
|
||||
<a href={`/blog/tags/${encodeURIComponent(tag.slice(2).toLowerCase())}`}
|
||||
class="inline-block px-3 py-1 text-sm bg-muted text-muted-foreground rounded-full hover:bg-purple-500/20 hover:text-purple-500 transition-all duration-200">
|
||||
{tag}
|
||||
</a>
|
||||
|
||||
@@ -5,7 +5,9 @@ image: "https://images.unsplash.com/photo-1633356122544-f134324a6cee?w=400&h=250
|
||||
date: "May 10, 2025"
|
||||
readTime: "5 min read"
|
||||
tags: ["React", "JavaScript", "Frontend"]
|
||||
tagId: ["react", "javascript", "frontend"]
|
||||
category: ["React", "Frontend"]
|
||||
categoryId: ["react", "frontend"]
|
||||
slug: "mastering-react-hooks"
|
||||
layout: "../../../layouts/BlogPostLayout.astro"
|
||||
---
|
||||
|
||||
@@ -9,11 +9,18 @@ import { type BlogPost } from '@/types';
|
||||
export async function getStaticPaths() {
|
||||
const allPosts = await Astro.glob('../posts/*.md');
|
||||
|
||||
// 收集所有标签
|
||||
// 收集所有标签ID或标签
|
||||
const uniqueTags = new Set<string>();
|
||||
|
||||
allPosts.forEach(post => {
|
||||
if (post.frontmatter?.tags && Array.isArray(post.frontmatter.tags)) {
|
||||
// 优先使用 tagId 作为路由标识符
|
||||
if (post.frontmatter?.tagId && Array.isArray(post.frontmatter.tagId)) {
|
||||
post.frontmatter.tagId.forEach(tagId => {
|
||||
if (tagId) uniqueTags.add(tagId.toLowerCase());
|
||||
});
|
||||
}
|
||||
// 如果没有 tagId,则使用 tags 作为后备
|
||||
else if (post.frontmatter?.tags && Array.isArray(post.frontmatter.tags)) {
|
||||
post.frontmatter.tags.forEach(tag => {
|
||||
if (tag) uniqueTags.add(tag.toLowerCase());
|
||||
});
|
||||
@@ -45,8 +52,14 @@ const allPosts = await Astro.glob('../posts/*.md');
|
||||
// 处理博客文章数据
|
||||
const blogPosts: BlogPost[] = allPosts
|
||||
.filter(post => {
|
||||
// 检查文章是否包含当前标签
|
||||
if (post.frontmatter?.tags && Array.isArray(post.frontmatter.tags)) {
|
||||
// 优先检查文章是否包含当前标签ID
|
||||
if (post.frontmatter?.tagId && Array.isArray(post.frontmatter.tagId)) {
|
||||
return post.frontmatter.tagId.some(postTagId =>
|
||||
postTagId.toLowerCase() === decodedTag.toLowerCase()
|
||||
);
|
||||
}
|
||||
// 如果没有 tagId,则检查 tags
|
||||
else if (post.frontmatter?.tags && Array.isArray(post.frontmatter.tags)) {
|
||||
return post.frontmatter.tags.some(postTag =>
|
||||
postTag.toLowerCase() === decodedTag.toLowerCase()
|
||||
);
|
||||
@@ -102,18 +115,22 @@ allPosts.forEach(post => {
|
||||
if (postTag) allTags.add(postTag);
|
||||
});
|
||||
}
|
||||
// 同时收集标签ID(用于内部路由)
|
||||
if (post.frontmatter?.tagId && Array.isArray(post.frontmatter.tagId)) {
|
||||
// 这里我们不添加到 allTags 中,因为 tagId 只用于路由,不用于显示
|
||||
}
|
||||
});
|
||||
|
||||
// 转换为数组并排序
|
||||
const categories = Array.from(allCategories).sort();
|
||||
const tags = Array.from(allTags).map(postTag => `#${postTag}`).sort();
|
||||
const tags = Array.from(allTags).map(postTag => `# ${postTag}`).sort();
|
||||
|
||||
// 获取当前标签的格式化名称(首字母大写)
|
||||
const formattedTag = decodedTag.charAt(0).toUpperCase() + decodedTag.slice(1);
|
||||
|
||||
// 动态生成页面标题和描述
|
||||
const pageTitle = `#${formattedTag} - Blog | Joy Zhao`;
|
||||
const pageDescription = `Explore articles tagged with #${formattedTag}. Dive into my thoughts on ${formattedTag} and related topics.`;
|
||||
const pageTitle = `# ${formattedTag} - Blog | Joy Zhao`;
|
||||
const pageDescription = `Explore articles tagged with # ${formattedTag}. Dive into my thoughts on ${formattedTag} and related topics.`;
|
||||
---
|
||||
|
||||
<BlogLayout title={pageTitle} description={pageDescription}>
|
||||
@@ -122,10 +139,10 @@ const pageDescription = `Explore articles tagged with #${formattedTag}. Dive int
|
||||
<div class="container mx-auto px-4 pt-24 pb-12">
|
||||
<div class="text-center mb-16">
|
||||
<h1 class="text-5xl md:text-6xl font-bold bg-gradient-to-r from-foreground via-purple-600 to-purple-800 dark:from-foreground dark:via-purple-200 dark:to-purple-300 bg-clip-text text-transparent mb-6">
|
||||
Tag: <span class="text-purple-500">#{formattedTag}</span>
|
||||
Tag: <span class="text-purple-500"># {formattedTag}</span>
|
||||
</h1>
|
||||
<p class="text-xl text-muted-foreground max-w-3xl mx-auto">
|
||||
Explore articles tagged with #{formattedTag}. Found {sortedBlogPosts.length} article{sortedBlogPosts.length !== 1 ? 's' : ''}.
|
||||
Explore articles tagged with # {formattedTag}. Found {sortedBlogPosts.length} article{sortedBlogPosts.length !== 1 ? 's' : ''}.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -163,7 +180,7 @@ const pageDescription = `Explore articles tagged with #${formattedTag}. Dive int
|
||||
</h3>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
{tags.map((tagItem) => {
|
||||
const tagName = tagItem.slice(1).toLowerCase();
|
||||
const tagName = tagItem.slice(2).toLowerCase();
|
||||
const isCurrentTag = tagName === decodedTag.toLowerCase();
|
||||
return (
|
||||
<a href={`/blog/tags/${encodeURIComponent(tagName)}`}
|
||||
|
||||
@@ -9,11 +9,22 @@ import { type BlogPost } from '@/types';
|
||||
export async function getStaticPaths() {
|
||||
const allPosts = await Astro.glob('../posts/*.md');
|
||||
|
||||
// 收集所有分类
|
||||
// 收集所有分类ID或分类
|
||||
const uniqueCategories = new Set<string>();
|
||||
|
||||
allPosts.forEach(post => {
|
||||
if (post.frontmatter?.category) {
|
||||
// 优先使用 categoryId 作为路由标识符
|
||||
if (post.frontmatter?.categoryId) {
|
||||
const categoryIds = Array.isArray(post.frontmatter.categoryId)
|
||||
? post.frontmatter.categoryId
|
||||
: [post.frontmatter.categoryId];
|
||||
|
||||
categoryIds.forEach(categoryId => {
|
||||
if (categoryId) uniqueCategories.add(categoryId.toLowerCase());
|
||||
});
|
||||
}
|
||||
// 如果没有 categoryId,则使用 category 作为后备
|
||||
else if (post.frontmatter?.category) {
|
||||
const categories = Array.isArray(post.frontmatter.category)
|
||||
? post.frontmatter.category
|
||||
: [post.frontmatter.category];
|
||||
@@ -49,8 +60,18 @@ const allPosts = await Astro.glob('../posts/*.md');
|
||||
// 处理博客文章数据
|
||||
const blogPosts: BlogPost[] = allPosts
|
||||
.filter(post => {
|
||||
// 检查文章是否属于当前分类
|
||||
if (post.frontmatter?.category) {
|
||||
// 优先检查文章是否包含当前分类ID
|
||||
if (post.frontmatter?.categoryId) {
|
||||
const postCategoryIds = Array.isArray(post.frontmatter.categoryId)
|
||||
? post.frontmatter.categoryId
|
||||
: [post.frontmatter.categoryId];
|
||||
|
||||
return postCategoryIds.some(catId =>
|
||||
catId.toLowerCase() === decodedCategory.toLowerCase()
|
||||
);
|
||||
}
|
||||
// 如果没有 categoryId,则检查 category
|
||||
else if (post.frontmatter?.category) {
|
||||
const postCategories = Array.isArray(post.frontmatter.category)
|
||||
? post.frontmatter.category
|
||||
: [post.frontmatter.category];
|
||||
@@ -114,7 +135,7 @@ allPosts.forEach(post => {
|
||||
|
||||
// 转换为数组并排序
|
||||
const categories = Array.from(allCategories).sort();
|
||||
const tags = Array.from(allTags).map(tag => `#${tag}`).sort();
|
||||
const tags = Array.from(allTags).map(tag => `# ${tag}`).sort();
|
||||
|
||||
// 获取当前分类的格式化名称(首字母大写)
|
||||
const formattedCategory = decodedCategory.charAt(0).toUpperCase() + decodedCategory.slice(1);
|
||||
@@ -171,7 +192,7 @@ const pageDescription = `探索关于${formattedCategory}的文章。深入了
|
||||
</h3>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
{tags.map((tag) => (
|
||||
<a href={`/zh/blog/tags/${encodeURIComponent(tag.slice(1).toLowerCase())}`}
|
||||
<a href={`/zh/blog/tags/${encodeURIComponent(tag.slice(2).toLowerCase())}`}
|
||||
class="inline-block px-3 py-1 text-sm bg-muted text-muted-foreground rounded-full hover:bg-purple-500/20 hover:text-purple-500 transition-all duration-200">
|
||||
{tag}
|
||||
</a>
|
||||
|
||||
@@ -24,6 +24,9 @@ const blogPosts: BlogPost[] = allPosts.map((post) => {
|
||||
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分钟阅读',
|
||||
};
|
||||
@@ -65,7 +68,7 @@ allPosts.forEach(post => {
|
||||
|
||||
// 转换为数组并排序
|
||||
const categories = Array.from(allCategories).sort();
|
||||
const tags = Array.from(allTags).map(tag => `#${tag}`).sort();
|
||||
const tags = Array.from(allTags).map(tag => `# ${tag}`).sort();
|
||||
|
||||
---
|
||||
|
||||
@@ -98,7 +101,7 @@ const tags = Array.from(allTags).map(tag => `#${tag}`).sort();
|
||||
</h3>
|
||||
<div class="space-y-2">
|
||||
{categories.map((category) => (
|
||||
<a href={`/zh/blog/categories/${category.toLowerCase()}`}
|
||||
<a href={`/zh/blog/categories/${encodeURIComponent(category.toLowerCase())}`}
|
||||
class="block text-muted-foreground hover:text-purple-500 transition-colors duration-200">
|
||||
{category}
|
||||
</a>
|
||||
@@ -116,7 +119,7 @@ const tags = Array.from(allTags).map(tag => `#${tag}`).sort();
|
||||
</h3>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
{tags.map((tag) => (
|
||||
<a href={`/zh/blog/tags/${tag.slice(1).toLowerCase()}`}
|
||||
<a href={`/zh/blog/tags/${encodeURIComponent(tag.slice(2).toLowerCase())}`}
|
||||
class="inline-block px-3 py-1 text-sm bg-muted text-muted-foreground rounded-full hover:bg-purple-500/20 hover:text-purple-500 transition-all duration-200">
|
||||
{tag}
|
||||
</a>
|
||||
|
||||
@@ -4,7 +4,10 @@ description: "探索 React Hooks 在函数组件中管理状态和副作用的
|
||||
image: "https://images.unsplash.com/photo-1633356122544-f134324a6cee?w=400&h=250&fit=crop&crop=center"
|
||||
date: "2025年5月10日"
|
||||
readTime: "5分钟阅读"
|
||||
tags: ["React", "JavaScript", "前端"]
|
||||
tags: ["React", "JavaScript", "前端开发"]
|
||||
tagId: ["react", "javascript", "frontend"]
|
||||
category: ["React", "前端"]
|
||||
categoryId: ["react", "frontend"]
|
||||
slug: "mastering-react-hooks"
|
||||
layout: "../../../../layouts/BlogPostLayout.astro"
|
||||
---
|
||||
|
||||
@@ -4,7 +4,7 @@ description: "掌握 TypeScript 在企业级应用中的高级技巧,提升代
|
||||
image: "https://images.unsplash.com/photo-1516116216624-53e697fedbea?w=400&h=250&fit=crop&crop=center"
|
||||
date: "2025年4月15日"
|
||||
readTime: "8分钟阅读"
|
||||
tags: ["TypeScript", "架构", "最佳实践"]
|
||||
tags: ["TypeScript", "JavaScript", "Architecture"]
|
||||
slug: "typescript-best-practices"
|
||||
layout: "../../../../layouts/BlogPostLayout.astro"
|
||||
---
|
||||
|
||||
@@ -9,11 +9,18 @@ import { type BlogPost } from '@/types';
|
||||
export async function getStaticPaths() {
|
||||
const allPosts = await Astro.glob('../posts/*.md');
|
||||
|
||||
// 收集所有标签
|
||||
// 收集所有标签ID或标签
|
||||
const uniqueTags = new Set<string>();
|
||||
|
||||
allPosts.forEach(post => {
|
||||
if (post.frontmatter?.tags && Array.isArray(post.frontmatter.tags)) {
|
||||
// 优先使用 tagId 作为路由标识符
|
||||
if (post.frontmatter?.tagId && Array.isArray(post.frontmatter.tagId)) {
|
||||
post.frontmatter.tagId.forEach(tagId => {
|
||||
if (tagId) uniqueTags.add(tagId.toLowerCase());
|
||||
});
|
||||
}
|
||||
// 如果没有 tagId,则使用 tags 作为后备
|
||||
else if (post.frontmatter?.tags && Array.isArray(post.frontmatter.tags)) {
|
||||
post.frontmatter.tags.forEach(tag => {
|
||||
if (tag) uniqueTags.add(tag.toLowerCase());
|
||||
});
|
||||
@@ -45,8 +52,14 @@ const allPosts = await Astro.glob('../posts/*.md');
|
||||
// 处理博客文章数据
|
||||
const blogPosts: BlogPost[] = allPosts
|
||||
.filter(post => {
|
||||
// 检查文章是否包含当前标签
|
||||
if (post.frontmatter?.tags && Array.isArray(post.frontmatter.tags)) {
|
||||
// 优先检查文章是否包含当前标签ID
|
||||
if (post.frontmatter?.tagId && Array.isArray(post.frontmatter.tagId)) {
|
||||
return post.frontmatter.tagId.some(postTagId =>
|
||||
postTagId.toLowerCase() === decodedTag.toLowerCase()
|
||||
);
|
||||
}
|
||||
// 如果没有 tagId,则检查 tags
|
||||
else if (post.frontmatter?.tags && Array.isArray(post.frontmatter.tags)) {
|
||||
return post.frontmatter.tags.some(postTag =>
|
||||
postTag.toLowerCase() === decodedTag.toLowerCase()
|
||||
);
|
||||
@@ -102,18 +115,22 @@ allPosts.forEach(post => {
|
||||
if (postTag) allTags.add(postTag);
|
||||
});
|
||||
}
|
||||
// 同时收集标签ID(用于内部路由)
|
||||
if (post.frontmatter?.tagId && Array.isArray(post.frontmatter.tagId)) {
|
||||
// 这里我们不添加到 allTags 中,因为 tagId 只用于路由,不用于显示
|
||||
}
|
||||
});
|
||||
|
||||
// 转换为数组并排序
|
||||
const categories = Array.from(allCategories).sort();
|
||||
const tags = Array.from(allTags).map(postTag => `#${postTag}`).sort();
|
||||
const tags = Array.from(allTags).map(postTag => `# ${postTag}`).sort();
|
||||
|
||||
// 获取当前标签的格式化名称(首字母大写)
|
||||
const formattedTag = decodedTag.charAt(0).toUpperCase() + decodedTag.slice(1);
|
||||
|
||||
// 动态生成页面标题和描述
|
||||
const pageTitle = `#${formattedTag} - 博客 | Joy Zhao`;
|
||||
const pageDescription = `浏览带有 #${formattedTag} 标签的文章。深入了解我关于 ${formattedTag} 及相关主题的想法。`;
|
||||
const pageTitle = `# ${formattedTag} - 博客 | Joy Zhao`;
|
||||
const pageDescription = `浏览带有 # ${formattedTag} 标签的文章。深入了解我关于 ${formattedTag} 及相关主题的想法。`;
|
||||
---
|
||||
|
||||
<BlogLayout title={pageTitle} description={pageDescription}>
|
||||
@@ -122,10 +139,10 @@ const pageDescription = `浏览带有 #${formattedTag} 标签的文章。深入
|
||||
<div class="container mx-auto px-4 pt-24 pb-12">
|
||||
<div class="text-center mb-16">
|
||||
<h1 class="text-5xl md:text-6xl font-bold bg-gradient-to-r from-foreground via-purple-600 to-purple-800 dark:from-foreground dark:via-purple-200 dark:to-purple-300 bg-clip-text text-transparent mb-6">
|
||||
标签: <span class="text-purple-500">#{formattedTag}</span>
|
||||
标签: <span class="text-purple-500"># {formattedTag}</span>
|
||||
</h1>
|
||||
<p class="text-xl text-muted-foreground max-w-3xl mx-auto">
|
||||
浏览带有 #{formattedTag} 标签的文章。找到 {sortedBlogPosts.length} 篇文章。
|
||||
浏览带有 # {formattedTag} 标签的文章。找到 {sortedBlogPosts.length} 篇文章。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -163,7 +180,7 @@ const pageDescription = `浏览带有 #${formattedTag} 标签的文章。深入
|
||||
</h3>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
{tags.map((tagItem) => {
|
||||
const tagName = tagItem.slice(1).toLowerCase();
|
||||
const tagName = tagItem.slice(2).toLowerCase();
|
||||
const isCurrentTag = tagName === decodedTag.toLowerCase();
|
||||
return (
|
||||
<a href={`/zh/blog/tags/${encodeURIComponent(tagName)}`}
|
||||
|
||||
Reference in New Issue
Block a user