refactor: improve tag handling and encoding in Tags and [tag] components https://github.com/saicaca/fuwari/issues/462

This commit is contained in:
L4Ph
2025-05-26 05:51:34 +09:00
parent c5d95736ac
commit 3f5ca8d943
3 changed files with 24 additions and 43 deletions

View File

@@ -3,7 +3,8 @@
import I18nKey from "../../i18n/i18nKey";
import { i18n } from "../../i18n/translation";
import { getTagList } from "../../utils/content-utils";
import { getTagUrl } from "../../utils/url-utils";
import { encodePathSegment } from "../../utils/encoding-utils";
import { url as url_util } from "../../utils/url-utils";
import ButtonTag from "../control/ButtonTag.astro";
import WidgetLayout from "./WidgetLayout.astro";
@@ -22,10 +23,13 @@ const style = Astro.props.style;
---
<WidgetLayout name={i18n(I18nKey.tags)} id="tags" isCollapsed={isCollapsed} collapsedHeight={COLLAPSED_HEIGHT} class={className} style={style}>
<div class="flex gap-2 flex-wrap">
{tags.map(t => (
<ButtonTag href={getTagUrl(t.name.trim())} label={`View all posts with the ${t.name.trim()} tag`}>
{t.name.trim()}
</ButtonTag>
))}
{tags.map(t => {
const encodedTag = encodePathSegment(t.name);
return (
<ButtonTag href={url_util(`/archive/tag/${encodedTag}/`)} label={`View all posts with the ${t.name} tag`}>
{t.name}
</ButtonTag>
);
})}
</div>
</WidgetLayout>

View File

@@ -10,47 +10,33 @@ export async function getStaticPaths() {
const posts = await getSortedPosts();
const allTags = posts.reduce<Set<string>>((acc, post) => {
if (Array.isArray(post.data.tags)) {
// biome-ignore lint/complexity/noForEach: <explanation>
post.data.tags.forEach((tag) => {
if (typeof tag === "string") {
acc.add(tag.trim());
} else {
acc.add(String(tag).trim());
}
});
} else if (post.data.tags && typeof post.data.tags === "string") {
// biome-ignore lint/complexity/noForEach: <explanation>
(post.data.tags as string)
.split(",")
.forEach((tag) => acc.add(tag.trim()));
for (const tag of post.data.tags) {
acc.add(tag);
}
return acc;
}, new Set());
const allTagsArray = Array.from(allTags);
// judge if the string is CJK
const isCJK = (str: string) =>
/[\u3000-\u9fff\uac00-\ud7af\u4e00-\u9faf]/.test(str);
const standardPaths = allTagsArray.map((tag) => ({
params: {
tag: encodePathSegment(tag),
},
props: {
decodedTag: tag,
decodedTag: tag.trim(),
},
}));
const nonEncodedCJKPaths = allTagsArray.filter(isCJK).map((tag) => ({
params: {
tag: tag, // keep CJK characters unencoded
},
props: {
decodedTag: tag,
},
}));
const nonEncodedCJKPaths = allTagsArray
.filter((tag) => /[\u3000-\u9fff\uac00-\ud7af\u4e00-\u9faf]/.test(tag))
.map((tag) => ({
params: {
tag: tag.trim(), // Do not encode CJK characters
},
props: {
decodedTag: tag.trim(),
},
}));
return [...standardPaths, ...nonEncodedCJKPaths];
}

View File

@@ -9,8 +9,6 @@
* @returns The encoded string
*/
export function encodePathSegment(value: string): string {
if (!value) return "";
return encodeURIComponent(value.trim());
}
@@ -21,12 +19,5 @@ export function encodePathSegment(value: string): string {
* @returns Decoded string
*/
export function decodePathSegment(value: string): string {
if (!value) return "";
try {
return decodeURIComponent(value);
} catch (e) {
console.error(`Failed to decode path segment: ${value}`, e);
return value;
}
return decodeURIComponent(value);
}