From f234e63eb468e2f554cd3623b1acb271d7de1113 Mon Sep 17 00:00:00 2001 From: prototypa Date: Sun, 14 Apr 2024 13:20:55 -0400 Subject: [PATCH] Fix #397: Adjust URL for Chinese Categories and Tags --- package-lock.json | 4 +- package.json | 2 +- src/components/blog/ListItem.astro | 16 +++-- src/components/blog/SinglePost.astro | 4 +- src/components/blog/Tags.astro | 6 +- .../[...blog]/[category]/[...page].astro | 6 +- src/pages/[...blog]/[tag]/[...page].astro | 4 +- src/types.d.ts | 9 ++- src/utils/blog.ts | 59 +++++++++++++------ 9 files changed, 71 insertions(+), 39 deletions(-) diff --git a/package-lock.json b/package-lock.json index a586de1..98043a8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@onwidget/astrowind", - "version": "1.0.0-beta.29", + "version": "1.0.0-beta.30", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@onwidget/astrowind", - "version": "1.0.0-beta.28", + "version": "1.0.0-beta.30", "dependencies": { "@astrojs/rss": "^4.0.5", "@astrojs/sitemap": "^3.1.2", diff --git a/package.json b/package.json index 1f00648..6ae1319 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onwidget/astrowind", - "version": "1.0.0-beta.29", + "version": "1.0.0-beta.30", "description": "AstroWind: A free template using Astro 4.0 and Tailwind CSS. Astro starter theme.", "type": "module", "private": true, diff --git a/src/components/blog/ListItem.astro b/src/components/blog/ListItem.astro index 3945062..dc964d2 100644 --- a/src/components/blog/ListItem.astro +++ b/src/components/blog/ListItem.astro @@ -64,8 +64,8 @@ const link = APP_BLOG?.post?.isEnabled ? getPermalink(post.permalink, 'post') : <> {' '} ·{' '} - - {post.category.replaceAll('-', ' ')} + + {post.category.title} ) @@ -87,8 +87,14 @@ const link = APP_BLOG?.post?.isEnabled ? getPermalink(post.permalink, 'post') : {post.excerpt &&

{post.excerpt}

} - + { + post.tags && Array.isArray(post.tags) ? ( + + ) : ( + + ) + } diff --git a/src/components/blog/SinglePost.astro b/src/components/blog/SinglePost.astro index 9c181d2..11e543c 100644 --- a/src/components/blog/SinglePost.astro +++ b/src/components/blog/SinglePost.astro @@ -40,8 +40,8 @@ const { Content } = post; <> {' '} ·{' '} - - {post.category.replaceAll('-', ' ')} + + {post.category.title} ) diff --git a/src/components/blog/Tags.astro b/src/components/blog/Tags.astro index 9dc1dc1..636a5de 100644 --- a/src/components/blog/Tags.astro +++ b/src/components/blog/Tags.astro @@ -24,13 +24,13 @@ const { tags, class: className = 'text-sm', title = undefined, isCategory = fals {tags.map((tag) => (
  • {!APP_BLOG?.tag?.isEnabled ? ( - tag + tag.title ) : ( - {tag} + {tag.title} )}
  • diff --git a/src/pages/[...blog]/[category]/[...page].astro b/src/pages/[...blog]/[category]/[...page].astro index f2e6db7..e1c4ff6 100644 --- a/src/pages/[...blog]/[category]/[...page].astro +++ b/src/pages/[...blog]/[category]/[...page].astro @@ -13,14 +13,14 @@ export const getStaticPaths = (async ({ paginate }) => { return await getStaticPathsBlogCategory({ paginate }); }) satisfies GetStaticPaths; -type Props = InferGetStaticPropsType & { category: string }; +type Props = InferGetStaticPropsType & { category: Record }; const { page, category } = Astro.props as Props; const currentPage = page.currentPage ?? 1; const metadata = { - title: `Category '${category}' ${currentPage > 1 ? ` — Page ${currentPage}` : ''}`, + title: `Category '${category.title}' ${currentPage > 1 ? ` — Page ${currentPage}` : ''}`, robots: { index: blogCategoryRobots?.index, follow: blogCategoryRobots?.follow, @@ -30,7 +30,7 @@ const metadata = {
    - {category.replaceAll('-', ' ')} + {category.title}
    diff --git a/src/pages/[...blog]/[tag]/[...page].astro b/src/pages/[...blog]/[tag]/[...page].astro index 4406560..86a767b 100644 --- a/src/pages/[...blog]/[tag]/[...page].astro +++ b/src/pages/[...blog]/[tag]/[...page].astro @@ -20,7 +20,7 @@ const { page, tag } = Astro.props as Props; const currentPage = page.currentPage ?? 1; const metadata = { - title: `Posts by tag '${tag}'${currentPage > 1 ? ` — Page ${currentPage} ` : ''}`, + title: `Posts by tag '${tag.title}'${currentPage > 1 ? ` — Page ${currentPage} ` : ''}`, robots: { index: blogTagRobots?.index, follow: blogTagRobots?.follow, @@ -30,7 +30,7 @@ const metadata = {
    - Tag: {tag} + Tag: {tag.title}
    diff --git a/src/types.d.ts b/src/types.d.ts index 31a82f4..d16bd01 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -24,9 +24,9 @@ export interface Post { image?: ImageMetadata | string; /** */ - category?: string; + category?: Taxonomy /** */ - tags?: Array; + tags?: Taxonomy[]; /** */ author?: string; @@ -44,6 +44,11 @@ export interface Post { readingTime?: number; } +export interface Taxonomy { + slug: string; + title: string; +} + export interface MetaData { title?: string; ignoreTitleTemplate?: boolean; diff --git a/src/utils/blog.ts b/src/utils/blog.ts index 7d70e19..4647de3 100644 --- a/src/utils/blog.ts +++ b/src/utils/blog.ts @@ -1,7 +1,7 @@ import type { PaginateFunction } from 'astro'; import { getCollection } from 'astro:content'; import type { CollectionEntry } from 'astro:content'; -import type { Post } from '~/types'; +import type { Post, Taxonomy } from '~/types'; import { APP_BLOG } from 'astrowind:config'; import { cleanSlug, trimSlash, BLOG_BASE, POST_PERMALINK_PATTERN, CATEGORY_BASE, TAG_BASE } from './permalinks'; @@ -60,13 +60,23 @@ const getNormalizedPost = async (post: CollectionEntry<'post'>): Promise = const slug = cleanSlug(rawSlug); // cleanSlug(rawSlug.split('/').pop()); const publishDate = new Date(rawPublishDate); const updateDate = rawUpdateDate ? new Date(rawUpdateDate) : undefined; - const category = rawCategory ? cleanSlug(rawCategory) : undefined; - const tags = rawTags.map((tag: string) => cleanSlug(tag)); + + const category = rawCategory + ? { + slug: cleanSlug(rawCategory), + title: rawCategory, + } + : undefined; + + const tags = rawTags.map((tag: string) => ({ + slug: cleanSlug(tag), + title: tag, + })); return { id: id, slug: slug, - permalink: await generatePermalink({ id, slug, publishDate, category }), + permalink: await generatePermalink({ id, slug, publishDate, category: category?.slug }), publishDate: publishDate, updateDate: updateDate, @@ -102,6 +112,17 @@ const getRandomizedPosts = (array: Post[], num: number) => { return newArray; }; +function hasMatchingTaxonomies( + arr1?: Taxonomy[], + arr2?: Taxonomy[] +): boolean { + if (!arr1 || !arr2) { + return false; + } + const slugsSet = new Set(arr1.map((item) => item.slug)); + return arr2.some((item) => slugsSet.has(item.slug)); +} + const load = async function (): Promise> { const posts = await getCollection('post'); const normalizedPosts = posts.map(async (post) => await getNormalizedPost(post)); @@ -200,18 +221,18 @@ export const getStaticPathsBlogCategory = async ({ paginate }: { paginate: Pagin if (!isBlogEnabled || !isBlogCategoryRouteEnabled) return []; const posts = await fetchPosts(); - const categories = new Set(); + const categories = {}; posts.map((post) => { - typeof post.category === 'string' && categories.add(post.category.toLowerCase()); + post.category?.slug && (categories[post.category?.slug] = post.category); }); - return Array.from(categories).flatMap((category) => + return Array.from(Object.keys(categories)).flatMap((categorySlug) => paginate( - posts.filter((post) => typeof post.category === 'string' && category === post.category.toLowerCase()), + posts.filter((post) => post.category?.slug && categorySlug === post.category?.slug), { - params: { category: category, blog: CATEGORY_BASE || undefined }, + params: { category: categorySlug, blog: CATEGORY_BASE || undefined }, pageSize: blogPostsPerPage, - props: { category }, + props: { category: categories[categorySlug] }, } ) ); @@ -222,35 +243,35 @@ export const getStaticPathsBlogTag = async ({ paginate }: { paginate: PaginateFu if (!isBlogEnabled || !isBlogTagRouteEnabled) return []; const posts = await fetchPosts(); - const tags = new Set(); + const tags = {}; posts.map((post) => { - Array.isArray(post.tags) && post.tags.map((tag) => tags.add(tag.toLowerCase())); + Array.isArray(post.tags) && post.tags.map((tag) => { tags[tag?.slug] = tag; }); }); - return Array.from(tags).flatMap((tag) => + return Array.from(Object.keys(tags)).flatMap((tagSlug) => paginate( - posts.filter((post) => Array.isArray(post.tags) && post.tags.find((elem) => elem.toLowerCase() === tag)), + posts.filter((post) => Array.isArray(post.tags) && post.tags.find((elem) => elem.slug === tagSlug)), { - params: { tag: tag, blog: TAG_BASE || undefined }, + params: { tag: tagSlug, blog: TAG_BASE || undefined }, pageSize: blogPostsPerPage, - props: { tag }, + props: { tag: tags[tagSlug] }, } ) ); }; /** */ -export function getRelatedPosts(allPosts: Post[], currentSlug: string, currentTags: string[]) { +export function getRelatedPosts(allPosts: Post[], currentSlug: string, currentTags: Array) { if (!isBlogEnabled || !isRelatedPostsEnabled) return []; const relatedPosts = getRandomizedPosts( - allPosts.filter((post) => post.slug !== currentSlug && post.tags?.some((tag) => currentTags.includes(tag))), + allPosts.filter((post) => post.slug !== currentSlug && hasMatchingTaxonomies(post.tags, currentTags)), APP_BLOG.relatedPostsCount ); if (relatedPosts.length < APP_BLOG.relatedPostsCount) { const morePosts = getRandomizedPosts( - allPosts.filter((post) => post.slug !== currentSlug && !post.tags?.some((tag) => currentTags.includes(tag))), + allPosts.filter((post) => post.slug !== currentSlug && hasMatchingTaxonomies(post.tags, currentTags)), APP_BLOG.relatedPostsCount - relatedPosts.length ); relatedPosts.push(...morePosts);