From cdc90d98022f15f09eb6b65ead0040573d07d255 Mon Sep 17 00:00:00 2001 From: Marcus Forsberg Date: Tue, 4 Jun 2024 11:57:46 +0200 Subject: [PATCH] feat: allow hrefResolver to return UrlObject instead of string Allows easier usage of eg. localized slugs in next-intl, which requires an UrlObject. --- src/helpers/generateHref.ts | 42 +++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/src/helpers/generateHref.ts b/src/helpers/generateHref.ts index d7a9330..8197257 100644 --- a/src/helpers/generateHref.ts +++ b/src/helpers/generateHref.ts @@ -1,19 +1,43 @@ +import {type UrlObject} from 'url' + import {InternalLink, LinkValue} from '../types' import {isCustomLink, isEmailLink, isExternalLink, isPhoneLink} from './typeGuards' export const generateHref = { - internal: (link: LinkValue, hrefResolver?: (link: InternalLink) => string) => { + internal: (link: LinkValue, hrefResolver?: (link: InternalLink) => string | UrlObject) => { const internalLink = link as InternalLink + const resolvedHref = + internalLink.internalLink && hrefResolver ? hrefResolver(internalLink) : undefined + + // Support UrlObjects, e.g. from Next.js + if (typeof resolvedHref === 'object' && 'pathname' in resolvedHref) { + resolvedHref.hash = internalLink.anchor?.replace(/^#/, '') + + if (internalLink.parameters) { + const params = new URLSearchParams(internalLink.parameters) + const resolvedParams = new URLSearchParams(resolvedHref.query?.toString()) + + for (const [key, value] of params.entries()) { + resolvedParams.set(key, value) + } + + resolvedHref.query = resolvedParams.toString() + } + + return resolvedHref + } + + let href = + resolvedHref || + (internalLink.internalLink?.slug?.current + ? `/${internalLink.internalLink.slug.current.replace(/^\//, '')}` + : undefined) - const href = internalLink.internalLink - ? hrefResolver - ? hrefResolver(internalLink) - : `/${internalLink.internalLink.slug?.current?.replace(/^\//, '')}` - : undefined + if (href && typeof href === 'string') { + href += (internalLink.parameters?.trim() || '') + (internalLink.anchor?.trim() || '') + } - return href - ? href + (internalLink.parameters?.trim() || '') + (internalLink.anchor?.trim() || '') - : '#' + return href || '#' }, external: (link: LinkValue) => isExternalLink(link) && link.url