Skip to content

Commit

Permalink
feat(theme): support custom target and rel in navbar links (#1993)
Browse files Browse the repository at this point in the history
Co-authored-by: Kev1nzh37 <[email protected]>
  • Loading branch information
brc-dd and kev1nzh37 authored Feb 25, 2023
1 parent 8e6e8d9 commit e2d4edf
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 7 deletions.
11 changes: 9 additions & 2 deletions docs/config/theme-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,22 @@ export default {
```ts
type NavItem = NavItemWithLink | NavItemWithChildren

type NavItemWithLink = {
interface NavItemWithLink {
text: string
link: string
activeMatch?: string
target?: string
rel?: string
}

interface NavItemWithChildren {
interface NavItemChildren {
text?: string
items: NavItemWithLink[]
}

interface NavItemWithChildren {
text?: string
items: (NavItemChildren | NavItemWithLink)[]
activeMatch?: string
}
```
Expand Down
19 changes: 19 additions & 0 deletions docs/guide/theme-nav.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,25 @@ export default {
`activeMatch` is expected to be a regex string, but you must define it as a string. We can't use actual RegExp object here because it isn't serializable during the build time.
:::

### Customize link's "target" and "rel" attributes

By default, VitePress automatically determines `target` and `rel` attributes based on whether the link is an external link. But if you want, you can customize them too.

```js
export default {
themeConfig: {
nav: [
{
text: 'Merchandise',
link: 'https://www.thegithubshop.com/',
target: '_self',
rel: 'sponsored'
}
]
}
}
```

## Social Links

Refer [`socialLinks`](../config/theme-config#sociallinks).
6 changes: 4 additions & 2 deletions src/client/theme-default/components/VPLink.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ const props = defineProps<{
tag?: string
href?: string
noIcon?: boolean
target?: string
rel?: string
}>()
const tag = computed(() => props.tag ?? props.href ? 'a' : 'span')
Expand All @@ -20,8 +22,8 @@ const isExternal = computed(() => props.href && EXTERNAL_URL_RE.test(props.href)
class="VPLink"
:class="{ link: href }"
:href="href ? normalizeLink(href) : undefined"
:target="isExternal ? '_blank' : undefined"
:rel="isExternal ? 'noreferrer' : undefined"
:target="target || (isExternal ? '_blank' : undefined)"
:rel="rel || (isExternal ? 'noreferrer' : undefined)"
>
<slot />
<VPIconExternalLink v-if="isExternal && !noIcon" class="icon" />
Expand Down
5 changes: 4 additions & 1 deletion src/client/theme-default/components/VPMenuLink.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<script lang="ts" setup>
import type { DefaultTheme } from 'vitepress/theme'
import { useData } from '../composables/data.js'
import { isActive } from '../support/utils.js'
import VPLink from './VPLink.vue'
defineProps<{
item: any
item: DefaultTheme.NavItemWithLink
}>()
const { page } = useData()
Expand All @@ -15,6 +16,8 @@ const { page } = useData()
<VPLink
:class="{ active: isActive(page.relativePath, item.activeMatch || item.link, !!item.activeMatch) }"
:href="item.link"
:target="item.target"
:rel="item.rel"
>
{{ item.text }}
</VPLink>
Expand Down
2 changes: 2 additions & 0 deletions src/client/theme-default/components/VPNavBarMenuLink.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ const { page } = useData()
)
}"
:href="item.link"
:target="item.target"
:rel="item.rel"
>
{{ item.text }}
</VPLink>
Expand Down
6 changes: 4 additions & 2 deletions types/default-theme.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export namespace DefaultTheme {

export type NavItem = NavItemWithLink | NavItemWithChildren

export type NavItemWithLink = {
export interface NavItemWithLink {
text: string
link: string

Expand All @@ -129,9 +129,11 @@ export namespace DefaultTheme {
* RegExp object here because it isn't serializable
*/
activeMatch?: string
target?: string
rel?: string
}

export type NavItemChildren = {
export interface NavItemChildren {
text?: string
items: NavItemWithLink[]
}
Expand Down

0 comments on commit e2d4edf

Please sign in to comment.