GatsbyJS Markdown Plugin: Automatically Open External Links In A New Tab

I’ve been doing a little research into how I can make posts written in markdown more suited for my needs and decided to use this opportunity to develop my own Gatsby Markdown plugin. Ever since I moved to Gatsby, making my own Markdown plugin has been on my todo list as I wanted to see how I could render slightly different HTML markup based on the requirements of my blog post content.

As this is my first markdown plugin, I thought it best to start small and tackle bug-bear of mine - making external links automatically open in a new window. From what I have looked online, some have suggested to just add an HTML anchor tag to the markdown as you will then have the ability to apply all attributes you’d want - including target. I’ll quote my previous post about aligning images in markdown and why I’m not keen on mixing HTML with markdown:

HTML can be mingled alongside the markdown syntax... I wouldn't recommend this from a maintainability perspective. Markdown is platform-agnostic so your content is not tied to a specific platform. By adding HTML to markdown, you're instantly sacrificing the portability of your content.

Setup

We will need to create a local Gatsby plugin, which I’ve named gatsby-remark-auto-link-new-window. Ugly name... maybe you can come up with something more imaginative. :-)

To register this to your Gatsby project, you will need start of with the following:

  • Creating a plugin folder at the root of your project (if one hasn’t been created already).
  • Add a new folder based on the name of our plugin, in this case - /plugins/gatsby-remark-auto-link-new-window.
  • Every plugin consists of two files:

    • index.js - where the plugin code to carry out our functionality will reside.
    • package.json - contains the details of our plugin, such as name, description, dependencies etc. For the moment this can just contain an empty JSON object {}. If we were to publish our plugin, this will need to be completed in its entirety.

Now that we have our bare-bones structure, we need to register our local plugin by adding a reference to the gatsby-config.js file. Since this is a plugin to do with transforming markdown, the reference will be added inside the 'gatsby-transformer-remark options:

{
  // ...
  resolve: 'gatsby-transformer-remark',
    options: {
      plugins: [        
        {
          resolve: 'gatsby-remark-embed-gist',
          options: {
            username: 'SurinderBhomra',
          },
        },
        {
          resolve: 'gatsby-remark-auto-link-new-window',
          options: {},
        },
        'gatsby-remark-prismjs',
      ],
    },
  // ...
}

For the moment, I’ve left the options field empty as we currently have no settings to pass to our plugin. This is something I will show in another blog post.

To make sure we have registered our plugin with no errors, we need run our build using the gatsby clean && gatsby develop command. This command will always need to be run after every change made to the plugin. By adding gatsby clean, we ensure the build clears out all the previously built files prior to the next build process.

Rewriting Links In Markdown

As the plugin is relatively straight-forward, let’s go straight into the code that will be added to our index.js file.

const visit = require("unist-util-visit")

module.exports = ({ markdownAST }, pluginOptions) => {
  visit(markdownAST, "link", node => {
    // Check if link is external by checking if the "url" attribute starts with http.
    if (node.url.startsWith("http")) {
      if (!node.data) {
        // hProperties refers to the HTML attributes of the node in question.
        // Ensure this object is added to the node.
        node.data = { hProperties: {} };
      }
      
      // Assign the 'target' attribute.
      node.data.hProperties = Object.assign({}, node.data.hProperties, {
        target: "_blank",
      });
    }
  })

  return markdownAST
}

As you can see, I want to target all markdown link nodes and depending on the contents of the url property we will perform a custom transformation. If the url property starts with an "http" we will then add a new attribute, "target" using hProperties. hProperties refers to the HTML attributes of the targeted node.

To see the changes take effect, we will need to re-run gatsby clean && gatsby develop.

Now that we have understood the basics, we can beef up our plugin by adding some more functionality, such as plugin options. But that's for another post.


Leave A Comment

If you have any questions or suggestions, feel free to leave a comment. I do get inundated with messages regarding my posts via LinkedIn and leaving a comment below is a better place to have an open discussion. Your comment will not only help others, but also myself. :-)