2023-07-16 10:19:38 +08:00

58 lines
1.3 KiB
Vue

<script lang="ts" setup>
import { computed } from 'vue'
import { useRouter } from 'vue-router'
import { EXTERNAL_URL_RE, normalizeLink } from '../utils/index.js'
import IconExternalLink from './icons/IconExternalLink.vue'
const props = defineProps<{
tag?: string
href?: string
noIcon?: boolean
target?: string
rel?: string
}>()
const router = useRouter()
const tag = computed(() => props.tag ?? (props.href ? 'a' : 'span'))
const isExternal = computed(
() => props.href && EXTERNAL_URL_RE.test(props.href)
)
const linkTo = (e: Event) => {
if (!isExternal.value) {
e.preventDefault()
if (props.href) {
router.push({ path: props.href })
}
}
}
</script>
<template>
<Component :is="tag" class="auto-link" :class="{ link: href }" :href="href ? normalizeLink(href) : undefined"
:target="target || (isExternal ? '_blank' : undefined)" :rel="rel || (isExternal ? 'noreferrer' : undefined)"
@click="linkTo($event)">
<slot />
<IconExternalLink v-if="isExternal && !noIcon" class="icon" />
</Component>
</template>
<style scoped>
.icon {
display: inline-block;
margin-top: -1px;
margin-left: 4px;
width: 11px;
height: 11px;
fill: var(--vp-c-text-3);
transition: fill 0.25s;
}
.auto-link :deep(i) {
font-style: normal;
font-weight: inherit;
line-height: normal;
}
</style>