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