navLink.ts 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. import { computed, Ref } from 'vue'
  2. import { useRoute } from 'vitepress'
  3. import type { DefaultTheme } from '../config'
  4. import { isExternal as isExternalCheck } from '../utils'
  5. import { useUrl } from '../composables/url'
  6. export function useNavLink(item: Ref<DefaultTheme.NavItemWithLink>) {
  7. const route = useRoute()
  8. const { withBase } = useUrl()
  9. const isExternal = isExternalCheck(item.value.link)
  10. const props = computed(() => {
  11. const routePath = normalizePath(`/${route.data.relativePath}`)
  12. let active = false
  13. if (item.value.activeMatch) {
  14. active = new RegExp(item.value.activeMatch).test(routePath)
  15. } else {
  16. const itemPath = normalizePath(withBase(item.value.link))
  17. active =
  18. itemPath === '/'
  19. ? itemPath === routePath
  20. : routePath.startsWith(itemPath)
  21. }
  22. return {
  23. class: {
  24. active,
  25. isExternal
  26. },
  27. href: isExternal ? item.value.link : withBase(item.value.link),
  28. target: item.value.target || isExternal ? `_blank` : null,
  29. rel: item.value.rel || isExternal ? `noopener noreferrer` : null,
  30. 'aria-label': item.value.ariaLabel
  31. }
  32. })
  33. return {
  34. props,
  35. isExternal
  36. }
  37. }
  38. function normalizePath(path: string): string {
  39. return path
  40. .replace(/#.*$/, '')
  41. .replace(/\?.*$/, '')
  42. .replace(/\.(html|md)$/, '')
  43. .replace(/\/index$/, '/')
  44. }