Core: fix edge case for Dynamic Link

This commit is contained in:
Fuma Nama
2026-02-20 23:28:28 +08:00
parent 4192b69d15
commit 6ab6692bf6
3 changed files with 27 additions and 9 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'fumadocs-core': patch
---
fix edge case for Dynamic Link
+12 -9
View File
@@ -16,15 +16,7 @@ export const DynamicLink = forwardRef<HTMLAnchorElement, DynamicLinkProps>(
({ href, ...props }, ref) => {
const params = useParams();
const url = useMemo(() => {
return href?.replace(/\[.*]/, (key) => {
const mappedKey = key.slice(1, -1);
const value = mappedKey in params ? params[mappedKey] : undefined;
if (!value) return '';
return typeof value === 'string' ? value : value.join('/');
});
}, [params, href]);
const url = useMemo(() => (href ? updateHref(href, params) : href), [params, href]);
return <Link ref={ref} href={url} {...props} />;
},
@@ -32,4 +24,15 @@ export const DynamicLink = forwardRef<HTMLAnchorElement, DynamicLinkProps>(
DynamicLink.displayName = 'DynamicLink';
export function updateHref(href: string, params: Record<string, string | string[]>) {
return href.replace(/\[(.*)]\/?/, (match, key) => {
const hasEndingSlash = match[match.length - 1] === '/';
const value = key in params ? params[key] : undefined;
if (!value) return '';
const replacement = typeof value === 'string' ? value : value.join('/');
return hasEndingSlash ? `${replacement}/` : replacement;
});
}
export default DynamicLink;
+10
View File
@@ -5,6 +5,7 @@ import { findNeighbour, findSiblings } from '@/page-tree/utils';
import { getBreadcrumbItems } from '@/breadcrumb';
import { DefaultFormatter } from '@/i18n/middleware';
import { NextURL } from 'next/dist/server/web/next-url';
import { updateHref } from '@/dynamic-link';
test('Find Neighbours', () => {
const tree: Root = {
@@ -199,3 +200,12 @@ test('findSiblings', () => {
]
`);
});
test('Dynamic Link: update href', () => {
expect(updateHref('/[lang]/test', {})).toBe('/test');
expect(updateHref('/[lang]/test', { lang: 'en' })).toBe('/en/test');
expect(updateHref('/[lang]/test', { lang: ['en', 'cn'] })).toBe('/en/cn/test');
// relative -> relative
expect(updateHref('[lang]/test', {})).toBe('test');
});