Repository: nuxt/nuxt
File: packages/nuxt/src/app/components/nuxt-link.ts (TypeScript)

Code before:
            isExternal: isExternal.value || hasTarget.value,
            isActive: false,
            isExactActive: false,
          } satisfies NuxtLinkDefaultSlotProps<true>)
        }

        return h('a', {
          ref: el,
          href: href.value || null, // converts `""` to `null` to prevent the attribute from being added as empty (`href=""`)
          rel,
          target,
          onClick: async (event) => {
            if (isExternal.value || hasTarget.value) {
              return
            }

            event.preventDefault()

            try {
              return await (props.replace ? router.replace(href.value) : router.push(href.value))
            } finally {
              // Focus the target element for hash links to restore accessibility behavior
              // that was prevented by event.preventDefault()
              if (import.meta.client && isHashLinkWithoutHashMode(to.value)) {
                const hash = (to.value as string).slice(1)
                const el = document.getElementById(hash)
                el?.focus()
              }
            }
          },
        }, slots.default?.())
      }
    },
  }) as unknown as (new<CustomProp extends boolean = false>(props: NuxtLinkProps<CustomProp> & VNodeProps & AllowedComponentProps & Omit<AnchorHTMLAttributes, keyof NuxtLinkProps<CustomProp>>) => InstanceType<DefineSetupFnComponent<
    NuxtLinkProps<CustomProp> & VNodeProps & AllowedComponentProps & Omit<AnchorHTMLAttributes, keyof NuxtLinkProps<CustomProp>>,
    [],
    SlotsType<NuxtLinkSlots<CustomProp>>
  >>) & Record<string, any>
}

export default defineNuxtLink(nuxtLinkDefaults)

// -- NuxtLink utils --
function applyTrailingSlashBehavior (to: string, trailingSlash: NuxtLinkOptions['trailingSlash']): string {
  const normalizeFn = trailingSlash === 'append' ? withTrailingSlash : withoutTrailingSlash
  // Until https://github.com/unjs/ufo/issues/189 is resolved
  const hasProtocolDifferentFromHttp = hasProtocol(to) && !to.startsWith('http')
  if (hasProtocolDifferentFromHttp) {
    return to
  }
  return normalizeFn(to, true)

Review comment (suggestion):
```suggestion
                const rawHash = (to.value as string).slice(1)
                let hash = rawHash
                try {
                  hash = decodeURIComponent(rawHash)
                } catch {
                  // ignore errors
                }
                const el = document.getElementById(hash)
```

Code after:
            isExternal: isExternal.value || hasTarget.value,
            isActive: false,
            isExactActive: false,
          } satisfies NuxtLinkDefaultSlotProps<true>)
        }

        return h('a', {
          ref: el,
          href: href.value || null, // converts `""` to `null` to prevent the attribute from being added as empty (`href=""`)
          rel,
          target,
          onClick: async (event) => {
            if (isExternal.value || hasTarget.value) {
              return
            }

            event.preventDefault()

            try {
              return await (props.replace ? router.replace(href.value) : router.push(href.value))
            } finally {
              // Focus the target element for hash links to restore accessibility behavior
              // that was prevented by event.preventDefault()
              if (import.meta.client && isHashLinkWithoutHashMode(to.value)) {
                const rawHash = (to.value as string).slice(1)
                let hash = rawHash
                try {
                  hash = decodeURIComponent(rawHash)
                } catch {
                  // ignore errors
                }
                const el = document.getElementById(hash)
                el?.focus()
              }
            }
          },
        }, slots.default?.())
      }
    },
  }) as unknown as (new<CustomProp extends boolean = false>(props: NuxtLinkProps<CustomProp> & VNodeProps & AllowedComponentProps & Omit<AnchorHTMLAttributes, keyof NuxtLinkProps<CustomProp>>) => InstanceType<DefineSetupFnComponent<
    NuxtLinkProps<CustomProp> & VNodeProps & AllowedComponentProps & Omit<AnchorHTMLAttributes, keyof NuxtLinkProps<CustomProp>>,
    [],
    SlotsType<NuxtLinkSlots<CustomProp>>
  >>) & Record<string, any>
}

export default defineNuxtLink(nuxtLinkDefaults)

// -- NuxtLink utils --
function applyTrailingSlashBehavior (to: string, trailingSlash: NuxtLinkOptions['trailingSlash']): string {
  const normalizeFn = trailingSlash === 'append' ? withTrailingSlash : withoutTrailingSlash