When working with nuxt/content, you might want to have a custom template for external links. This can be useful if you want to add a custom icon or a different style to external links.
To achieve this, you can create a custom component that checks if the link is an external link and then renders the link with your custom template.
First we create a new component in our Nuxt project. nuxt/content gives us the ability to override the default components used for rendering the content by placing them in the components/content
directory. So for our custom link component, we create a new file components/content/ProseA.vue
.
Note: The component name must be ProseA.vue
to override the default link component.
<template>
<NuxtLink :href="href" :target="_target">
<slot />
</NuxtLink>
</template>
<script setup lang="ts">
withDefaults(
defineProps<{
href: string;
target?: string;
}>(),
{
target: undefined,
},
);
</script>
The code above shows the default link component.
Now that we created our custom link component, we can add a check to see if the link is an external link. To do so, we add a computed property indicating if the link is external.
<template>
<NuxtLink :href="href" :target="_target">
<slot />
</NuxtLink>
</template>
<script setup lang="ts">
withDefaults(
defineProps<{
href: string;
target?: string;
}>(),
{
target: undefined,
},
);
/**
* Check if the link is an external link
* The check here is quite simple and could be more complex depending on your needs
*
* @returns {boolean}
*/
const isExternal = computed(() => props.href.startsWith("http"));
</script>
Since we now know if the link is external, we can add a custom icon to the link. In this example, we add a small icon to the link if it is an external link.
<template>
<NuxtLink :href="href" :target="_target">
<slot />
<ArrowTopRightOnSquareIcon
v-if="isExternal"
class="ml-1 inline-block h-5 w-5 text-gray-700"
/>
</NuxtLink>
</template>
<script setup lang="ts">
import { ArrowTopRightOnSquareIcon } from "@heroicons/vue/20/solid";
withDefaults(
defineProps<{
href: string;
target?: string;
}>(),
{
target: undefined,
},
);
/**
* Check if the link is an external link
* The check here is quite simple and could be more complex depending on your needs
*
* @returns {boolean}
*/
const isExternal = computed(() => props.href.startsWith("http"));
</script>
With this setup, you can now add a custom icon or style to external links in your nuxt/content project. The check for external links is quite simple and could be more complex depending on your needs. One possible improvement could be to set the link target to _blank
if the link is external. And also make to set the rel="noopener noreferrer"
attributes to the link to improve security.
<template>
<NuxtLink
:href="href"
:target="_target"
:external="isExternal"
class="inline-flex items-center"
>
<slot />
<ArrowTopRightOnSquareIcon
v-if="isExternal"
class="ml-1 inline-block h-5 w-5 text-gray-700"
/>
</NuxtLink>
</template>
<script setup lang="ts">
import { ArrowTopRightOnSquareIcon } from "@heroicons/vue/20/solid";
const props = withDefaults(
defineProps<{
href: string;
target?: string;
}>(),
{
target: undefined,
},
);
const isExternal = computed(() => props.href.startsWith("http"));
const _target = computed(() => {
if (props.target) {
return props.target;
}
return isExternal.value ? "_blank" : undefined;
});
</script>
NuxtLink
automatically adds the rel="noopener noreferrer"
attributes to external links, if the external
attribute is set. In order for this to work correctly, you would have to disable the rehype-external-links
plugin in your Nuxt configuration.
content: {
markdown: {
rehypePlugins: {
'rehype-external-links': false,
}
},
},