fix(nuxt): don't use <RouterLink> for links starting with # (#30190)

This commit is contained in:
Vuk Marjanovic 2024-12-19 00:39:54 +01:00 committed by GitHub
parent 1f09e69335
commit 03f0d1aec3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 28 additions and 2 deletions

View File

@ -18,6 +18,8 @@ import { cancelIdleCallback, requestIdleCallback } from '../compat/idle-callback
// @ts-expect-error virtual file
import { nuxtLinkDefaults } from '#build/nuxt.config.mjs'
import { hashMode } from '#build/router.options'
const firstNonUndefined = <T> (...args: (T | undefined)[]) => args.find(arg => arg !== undefined)
const NuxtLinkDevKeySymbol: InjectionKey<boolean> = Symbol('nuxt-link-dev-key')
@ -110,6 +112,10 @@ export function defineNuxtLink (options: NuxtLinkOptions) {
}
}
function isHashLinkWithoutHashMode (link: unknown): boolean {
return !hashMode && typeof link === 'string' && link.startsWith('#')
}
function resolveTrailingSlashBehavior (to: string, resolve: Router['resolve']): string
function resolveTrailingSlashBehavior (to: RouteLocationRaw, resolve: Router['resolve']): Exclude<RouteLocationRaw, string>
function resolveTrailingSlashBehavior (to: RouteLocationRaw | undefined, resolve: Router['resolve']): RouteLocationRaw | RouteLocation | undefined {
@ -176,7 +182,9 @@ export function defineNuxtLink (options: NuxtLinkOptions) {
// Resolves `to` value if it's a route location object
const href = computed(() => {
if (!to.value || isAbsoluteUrl.value) { return to.value as string }
if (!to.value || isAbsoluteUrl.value || isHashLinkWithoutHashMode(to.value)) {
return to.value as string
}
if (isExternal.value) {
const path = typeof to.value === 'object' && 'path' in to.value ? resolveRouteObject(to.value) : to.value
@ -373,7 +381,7 @@ export function defineNuxtLink (options: NuxtLinkOptions) {
}
return () => {
if (!isExternal.value && !hasTarget.value) {
if (!isExternal.value && !hasTarget.value && !isHashLinkWithoutHashMode(to.value)) {
const routerLinkProps: RouterLinkProps & VNodeProps & AllowedComponentProps & AnchorHTMLAttributes = {
ref: elRef,
to: to.value,

View File

@ -129,6 +129,16 @@ export default defineNuxtModule({
'export const START_LOCATION = Symbol(\'router:start-location\')',
].join('\n'),
})
// used by `<NuxtLink>`
addTemplate({
filename: 'router.options.mjs',
getContents: () => {
return [
'export const hashMode = false',
'export default {}',
].join('\n')
},
})
addTypeTemplate({
filename: 'types/middleware.d.ts',
getContents: () => [

View File

@ -119,6 +119,11 @@ describe('nuxt-link:isExternal', () => {
expect(nuxtLink({ to: '/foo/bar', target: '_blank' }).type).toBe(EXTERNAL)
expect(nuxtLink({ to: '/foo/bar?baz=qux', target: '_blank' }).type).toBe(EXTERNAL)
})
it('returns `true` if link starts with hash', () => {
expect(nuxtLink({ href: '#hash' }).type).toBe(EXTERNAL)
expect(nuxtLink({ to: '#hash' }).type).toBe(EXTERNAL)
})
})
describe('nuxt-link:propsOrAttributes', () => {

View File

@ -0,0 +1,2 @@
export default {}
export const hashMode = false

View File

@ -8,6 +8,7 @@ export default defineConfig({
resolve: {
alias: {
'#build/nuxt.config.mjs': resolve('./test/mocks/nuxt-config'),
'#build/router.options': resolve('./test/mocks/router-options'),
'#internal/nuxt/paths': resolve('./test/mocks/paths'),
'#build/app.config.mjs': resolve('./test/mocks/app-config'),
'#app': resolve('./packages/nuxt/dist/app'),