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 I18nKey from "../../i18n/i18nKey";
import { i18n } from "../../i18n/translation"; import { i18n } from "../../i18n/translation";
import { getTagList } from "../../utils/content-utils"; 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 ButtonTag from "../control/ButtonTag.astro";
import WidgetLayout from "./WidgetLayout.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}> <WidgetLayout name={i18n(I18nKey.tags)} id="tags" isCollapsed={isCollapsed} collapsedHeight={COLLAPSED_HEIGHT} class={className} style={style}>
<div class="flex gap-2 flex-wrap"> <div class="flex gap-2 flex-wrap">
{tags.map(t => ( {tags.map(t => {
<ButtonTag href={getTagUrl(t.name.trim())} label={`View all posts with the ${t.name.trim()} tag`}> const encodedTag = encodePathSegment(t.name);
{t.name.trim()} return (
</ButtonTag> <ButtonTag href={url_util(`/archive/tag/${encodedTag}/`)} label={`View all posts with the ${t.name} tag`}>
))} {t.name}
</ButtonTag>
);
})}
</div> </div>
</WidgetLayout> </WidgetLayout>

View File

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

View File

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