mirror of https://github.com/vuejs/vitepress
feat: add external link support for nav items (#46)
parent
583f02e488
commit
44e91bb986
@ -0,0 +1,78 @@
|
|||||||
|
// TODO dropdowns
|
||||||
|
import { defineComponent, computed, PropType } from 'vue'
|
||||||
|
import { useRoute } from 'vitepress'
|
||||||
|
import { withBase, isExternal } from '../utils'
|
||||||
|
import { DefaultTheme } from '../config'
|
||||||
|
import OutboundLink from './icons/OutboundLink.vue'
|
||||||
|
|
||||||
|
const normalizePath = (path: string): string => {
|
||||||
|
path = path
|
||||||
|
.replace(/#.*$/, '')
|
||||||
|
.replace(/\?.*$/, '')
|
||||||
|
.replace(/\.html$/, '')
|
||||||
|
if (path.endsWith('/')) {
|
||||||
|
path += 'index'
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
OutboundLink
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
item: {
|
||||||
|
type: Object as PropType<DefaultTheme.NavItemWithLink>,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setup(props) {
|
||||||
|
const item = props.item
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
const classes = computed(() => ({
|
||||||
|
active: isActiveLink.value,
|
||||||
|
external: isExternalLink.value
|
||||||
|
}))
|
||||||
|
|
||||||
|
const isActiveLink = computed(() => {
|
||||||
|
return normalizePath(withBase(item.link)) === normalizePath(route.path)
|
||||||
|
})
|
||||||
|
|
||||||
|
const isExternalLink = computed(() => {
|
||||||
|
return isExternal(item.link)
|
||||||
|
})
|
||||||
|
|
||||||
|
const href = computed(() => {
|
||||||
|
return isExternalLink.value ? item.link : withBase(item.link)
|
||||||
|
})
|
||||||
|
|
||||||
|
const target = computed(() => {
|
||||||
|
if (item.target) {
|
||||||
|
return item.target
|
||||||
|
}
|
||||||
|
|
||||||
|
return isExternalLink.value ? '_blank' : ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const rel = computed(() => {
|
||||||
|
if (item.rel) {
|
||||||
|
return item.rel
|
||||||
|
}
|
||||||
|
|
||||||
|
return isExternalLink.value ? 'noopener noreferrer' : ''
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
classes,
|
||||||
|
isActiveLink,
|
||||||
|
isExternalLink,
|
||||||
|
href,
|
||||||
|
target,
|
||||||
|
rel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
@ -0,0 +1,35 @@
|
|||||||
|
<template>
|
||||||
|
<a
|
||||||
|
class="nav-link"
|
||||||
|
:class="classes"
|
||||||
|
:href="href"
|
||||||
|
:target="target"
|
||||||
|
:rel="rel"
|
||||||
|
:aria-label="item.ariaLabel"
|
||||||
|
>
|
||||||
|
{{ item.text }}
|
||||||
|
<OutboundLink v-if="isExternalLink" />
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./NavBarLink"></script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.nav-link {
|
||||||
|
color: var(--text-color);
|
||||||
|
margin-left: 1.5rem;
|
||||||
|
font-weight: 600;
|
||||||
|
display: inline-block;
|
||||||
|
height: 1.75rem;
|
||||||
|
line-height: 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link:hover,
|
||||||
|
.nav-link.active {
|
||||||
|
border-bottom: 2px solid var(--accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link.external:hover {
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,31 @@
|
|||||||
|
<template functional>
|
||||||
|
<svg
|
||||||
|
class="icon outbound"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
aria-hidden="true"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
viewBox="0 0 100 100"
|
||||||
|
width="15"
|
||||||
|
height="15"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"
|
||||||
|
/>
|
||||||
|
<polygon
|
||||||
|
fill="currentColor"
|
||||||
|
points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.icon.outbound {
|
||||||
|
color: #aaa;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
position: relative;
|
||||||
|
top: -1px;
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in new issue