NavLinks.vue 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. <template>
  2. <nav
  3. class="nav-links"
  4. v-if="userLinks.length || repoLink"
  5. >
  6. <!-- user links -->
  7. <div
  8. class="nav-item"
  9. v-for="item in userLinks"
  10. :key="item.link"
  11. >
  12. <DropdownLink
  13. v-if="item.type === 'links'"
  14. :item="item"
  15. />
  16. <NavLink
  17. v-else
  18. :item="item"
  19. />
  20. </div>
  21. <!-- repo link -->
  22. <a
  23. v-if="repoLink"
  24. :href="repoLink"
  25. class="repo-link"
  26. target="_blank"
  27. rel="noopener noreferrer"
  28. >
  29. {{ repoLabel }}
  30. <OutboundLink/>
  31. </a>
  32. </nav>
  33. </template>
  34. <script>
  35. import DropdownLink from '@theme/components/DropdownLink.vue'
  36. import { resolveNavLinkItem } from '../util'
  37. import NavLink from '@theme/components/NavLink.vue'
  38. export default {
  39. components: { NavLink, DropdownLink },
  40. computed: {
  41. userNav () {
  42. return this.$themeLocaleConfig.nav || this.$site.themeConfig.nav || []
  43. },
  44. nav () {
  45. const { locales } = this.$site
  46. if (locales && Object.keys(locales).length > 1) {
  47. const currentLink = this.$page.path
  48. const routes = this.$router.options.routes
  49. const themeLocales = this.$site.themeConfig.locales || {}
  50. const languageDropdown = {
  51. text: this.$themeLocaleConfig.selectText || 'Languages',
  52. ariaLabel: this.$themeLocaleConfig.ariaLabel || 'Select language',
  53. items: Object.keys(locales).map(path => {
  54. const locale = locales[path]
  55. const text = themeLocales[path] && themeLocales[path].label || locale.lang
  56. let link
  57. // Stay on the current page
  58. if (locale.lang === this.$lang) {
  59. link = currentLink
  60. } else {
  61. // Try to stay on the same page
  62. link = currentLink.replace(this.$localeConfig.path, path)
  63. // fallback to homepage
  64. if (!routes.some(route => route.path === link)) {
  65. link = path
  66. }
  67. }
  68. return { text, link }
  69. })
  70. }
  71. return [...this.userNav, languageDropdown]
  72. }
  73. return this.userNav
  74. },
  75. userLinks () {
  76. return (this.nav || []).map(link => {
  77. return Object.assign(resolveNavLinkItem(link), {
  78. items: (link.items || []).map(resolveNavLinkItem)
  79. })
  80. })
  81. },
  82. repoLink () {
  83. const { repo } = this.$site.themeConfig
  84. if (repo) {
  85. return /^https?:/.test(repo)
  86. ? repo
  87. : `https://github.com/${repo}`
  88. }
  89. return null
  90. },
  91. repoLabel () {
  92. if (!this.repoLink) return
  93. if (this.$site.themeConfig.repoLabel) {
  94. return this.$site.themeConfig.repoLabel
  95. }
  96. const repoHost = this.repoLink.match(/^https?:\/\/[^/]+/)[0]
  97. const platforms = ['GitHub', 'GitLab', 'Bitbucket']
  98. for (let i = 0; i < platforms.length; i++) {
  99. const platform = platforms[i]
  100. if (new RegExp(platform, 'i').test(repoHost)) {
  101. return platform
  102. }
  103. }
  104. return 'Source'
  105. }
  106. }
  107. }
  108. </script>
  109. <style lang="stylus">
  110. .nav-links
  111. display inline-block
  112. a
  113. line-height 1.4rem
  114. color inherit
  115. &:hover, &.router-link-active
  116. color $accentColor
  117. .nav-item
  118. position relative
  119. display inline-block
  120. margin-left 1.5rem
  121. line-height 2rem
  122. &:first-child
  123. margin-left 0
  124. .repo-link
  125. margin-left 1.5rem
  126. @media (max-width: $MQMobile)
  127. .nav-links
  128. .nav-item, .repo-link
  129. margin-left 0
  130. @media (min-width: $MQMobile)
  131. .nav-links a
  132. &:hover, &.router-link-active
  133. color $textColor
  134. .nav-item > a:not(.external)
  135. &:hover, &.router-link-active
  136. margin-bottom -2px
  137. border-bottom 2px solid lighten($accentColor, 8%)
  138. </style>