Skip to content

Commit 52cfbc3

Browse files
zonemeenbrc-dd
andauthored
feat(theme): option to show icon for external links (#2501)
Co-authored-by: Divyansh Singh <[email protected]>
1 parent 00d94e9 commit 52cfbc3

File tree

6 files changed

+50
-30
lines changed

6 files changed

+50
-30
lines changed

docs/reference/default-theme-config.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,3 +398,10 @@ Can be used to customize the label of the return to top button. This label is on
398398
- Default: `Change language`
399399

400400
Can be used to customize the aria-label of the language toggle button in navbar. This is only used if you're using [i18n](../guide/i18n).
401+
402+
## externalLinkIcon
403+
404+
- Type: `boolean`
405+
- Default: `false`
406+
407+
Whether to show an external link icon next to external links in markdown.

src/client/theme-default/components/VPDoc.vue

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22
import { useRoute } from 'vitepress'
33
import { useSidebar } from 'vitepress/theme'
44
import { computed } from 'vue'
5+
import { useData } from '../composables/data'
56
import VPDocAside from './VPDocAside.vue'
67
import VPDocFooter from './VPDocFooter.vue'
78
import VPDocOutlineDropdown from './VPDocOutlineDropdown.vue'
89
10+
const { theme } = useData()
11+
912
const route = useRoute()
1013
const { hasSidebar, hasAside, leftAside } = useSidebar()
1114
@@ -42,7 +45,13 @@ const pageName = computed(() =>
4245
<slot name="doc-before" />
4346
<VPDocOutlineDropdown />
4447
<main class="main">
45-
<Content class="vp-doc" :class="pageName" />
48+
<Content
49+
class="vp-doc"
50+
:class="[
51+
pageName,
52+
theme.externalLinkIcon && 'external-link-icon-enabled'
53+
]"
54+
/>
4655
</main>
4756
<VPDocFooter>
4857
<template #doc-footer-before><slot name="doc-footer-before" /></template>
@@ -193,4 +202,8 @@ const pageName = computed(() =>
193202
.VPDoc.has-aside .content-container {
194203
max-width: 688px;
195204
}
205+
206+
.external-link-icon-enabled :is(.vp-doc a[href*='://'], .vp-doc a[target='_blank'])::after {
207+
content: '';
208+
}
196209
</style>
Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
<script lang="ts" setup>
22
import { computed } from 'vue'
33
import { normalizeLink } from '../support/utils'
4-
import VPIconExternalLink from './icons/VPIconExternalLink.vue'
54
import { EXTERNAL_URL_RE } from '../../shared'
65
76
const props = defineProps<{
@@ -20,25 +19,11 @@ const isExternal = computed(() => props.href && EXTERNAL_URL_RE.test(props.href)
2019
<component
2120
:is="tag"
2221
class="VPLink"
23-
:class="{ link: href }"
22+
:class="{ link: href, 'vp-external-link-icon': isExternal && !noIcon }"
2423
:href="href ? normalizeLink(href) : undefined"
2524
:target="target || (isExternal ? '_blank' : undefined)"
2625
:rel="rel || (isExternal ? 'noreferrer' : undefined)"
2726
>
2827
<slot />
29-
<VPIconExternalLink v-if="isExternal && !noIcon" class="icon" />
3028
</component>
3129
</template>
32-
33-
<style scoped>
34-
.icon {
35-
display: inline-block;
36-
margin-top: -1px;
37-
margin-left: 4px;
38-
width: 11px;
39-
height: 11px;
40-
fill: var(--vp-c-text-3);
41-
transition: fill 0.25s;
42-
flex-shrink: 0;
43-
}
44-
</style>

src/client/theme-default/components/icons/VPIconExternalLink.vue

Lines changed: 0 additions & 13 deletions
This file was deleted.

src/client/theme-default/styles/components/vp-doc.css

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,3 +522,24 @@
522522
margin: 0 !important;
523523
max-width: calc((100% - 24px) / 2) !important;
524524
}
525+
526+
:is(
527+
.vp-external-link-icon,
528+
.vp-doc a[href*='://'],
529+
.vp-doc a[target='_blank']
530+
)::after {
531+
display: inline-block;
532+
margin-top: -1px;
533+
margin-left: 4px;
534+
width: 11px;
535+
height: 11px;
536+
background: currentColor;
537+
flex-shrink: 0;
538+
--icon: url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath d='M0 0h24v24H0V0z' fill='none' /%3E%3Cpath d='M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5H9z' /%3E%3C/svg%3E");
539+
-webkit-mask-image: var(--icon);
540+
mask-image: var(--icon);
541+
}
542+
543+
.vp-external-link-icon::after {
544+
content: '';
545+
}

types/default-theme.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,13 @@ export namespace DefaultTheme {
122122
* @default true
123123
*/
124124
i18nRouting?: boolean
125+
126+
/**
127+
* Show external link icon in Markdown links.
128+
*
129+
* @default false
130+
*/
131+
externalLinkIcon?: boolean
125132
}
126133

127134
// nav -----------------------------------------------------------------------

0 commit comments

Comments
 (0)