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,
      }
    },
},