perf:  导航栏链接支持传入文件路径

This commit is contained in:
pengzhanbo 2024-03-24 01:59:41 +08:00
parent e6357fc992
commit c1a9868ead
4 changed files with 36 additions and 52 deletions

View File

@ -1,7 +1,7 @@
<script lang="ts" setup>
import { computed } from 'vue'
import { useRouter } from 'vuepress/client'
import { EXTERNAL_URL_RE, normalizeLink } from '../utils/index.js'
import { resolveRoutePath, useRouter, withBase } from 'vuepress/client'
import { EXTERNAL_URL_RE } from '../utils/index.js'
import IconExternalLink from './icons/IconExternalLink.vue'
const props = defineProps<{
@ -18,12 +18,19 @@ const tag = computed(() => props.tag ?? (props.href ? 'a' : 'span'))
const isExternal = computed(
() => props.href && EXTERNAL_URL_RE.test(props.href),
)
const link = computed(() => {
if (!props.href)
return undefined
if (isExternal.value)
return props.href
return withBase(resolveRoutePath(props.href))
})
function linkTo(e: Event) {
if (!isExternal.value) {
e.preventDefault()
if (props.href)
router.push({ path: props.href })
if (link.value)
router.push({ path: link.value })
}
}
</script>
@ -32,8 +39,8 @@ function linkTo(e: Event) {
<Component
:is="tag"
class="auto-link"
:class="{ link: href }"
:href="href ? normalizeLink(href) : undefined"
:class="{ link }"
:href="link"
:target="target ?? (isExternal ? '_blank' : undefined)"
:rel="rel ?? (isExternal ? 'noreferrer' : undefined)"
@click="linkTo($event)"

View File

@ -1,7 +1,7 @@
export * from './darkMode.js'
export * from './useScrollPromise.js'
export * from './themeData.js'
export * from './useResolveRouteWithRedirect.js'
export * from './useNavLink.js'
export * from './sidebar.js'
export * from './aside.js'
export * from './page.js'

View File

@ -0,0 +1,22 @@
import { resolveRoute } from 'vuepress/client'
import type { NavItemWithLink } from '../../shared/index.js'
/**
* Resolve NavLink props from string
*
* @example
* - Input: '/README.md'
* - Output: { text: 'Home', link: '/' }
*/
export function useNavLink(config: string): NavItemWithLink {
const { notFound, meta, path } = resolveRoute<{
title?: string
}>(config)
return notFound
? { text: path, link: path }
: {
text: meta.title || path,
link: path,
}
}

View File

@ -1,45 +0,0 @@
import { isFunction, isString } from 'vuepress/shared'
import { useRouter } from 'vuepress/client'
import type { Router } from 'vuepress/client'
import type { NavItemWithLink } from '../../shared/index.js'
/**
* Resolve a route with redirection
*/
export function useResolveRouteWithRedirect(...args: Parameters<Router['resolve']>): ReturnType<Router['resolve']> {
const router = useRouter()
const route = router.resolve(...args)
const lastMatched = route.matched[route.matched.length - 1]
if (!lastMatched?.redirect)
return route
const { redirect } = lastMatched
const resolvedRedirect = isFunction(redirect) ? redirect(route) : redirect
const resolvedRedirectObj = isString(resolvedRedirect)
? { path: resolvedRedirect }
: resolvedRedirect
return useResolveRouteWithRedirect({
hash: route.hash,
query: route.query,
params: route.params,
...resolvedRedirectObj,
})
}
/**
* Resolve NavLink props from string
*
* @example
* - Input: '/README.md'
* - Output: { text: 'Home', link: '/' }
*/
export function useNavLink(item: string): NavItemWithLink {
// the route path of vue-router is url-encoded, and we expect users are using
// non-url-encoded string in theme config, so we need to url-encode it first to
// resolve the route correctly
const resolved = useResolveRouteWithRedirect(encodeURI(item))
return {
text: (resolved.meta as any).title || item,
link: resolved.name === '404' ? item : resolved.fullPath,
}
}