mirror of
https://github.com/saicaca/fuwari.git
synced 2026-01-11 14:52:52 +01:00
refactor: improve tag handling and encoding in Tags and [tag] components https://github.com/saicaca/fuwari/issues/462
This commit is contained in:
@@ -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>
|
||||||
@@ -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];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user