Search code examples
javascriptreactjsmarkdowndocusaurus

Docusaurus - how to open external links in new tab?


I am using Docusaurus and would like to open external links in new tabs.

I would prefer to use code for this rather than the solution of writing html code in my markdown document as per this answer.

I have tried this answer:

[link](url){:target="_blank"}

As well as this answer:

[Google](https://google.com" target="_blank)

I think this post would probably do what I want, I tried adding the code to _index.js, but Docusaurus stopped building.

(function() {
  var links = document.getElementsByTagName('a');
  for (var i = 0; i < links.length; i++) {
    if (/^(https?:)?\/\//.test(links[i].getAttribute('href'))) {
      links[i].target = '_blank';
    }
  }
})();

I uploaded the JavaScript code to GitHub and added it to siteConfig.js:

// Add custom scripts here that would be placed in <script> tags.
  scripts: [
    "https://buttons.github.io/buttons.js",
    "https://msdcanderson.github.io/docusaurus-open-link-new-tab.github.io/open-link-new-tab.js"
  ],

The script seems to load, but doesn't work as expected.

I expect a link written in Markdown to open in a new browser tab:

[the rmarkdown website](https://rmarkdown.rstudio.com)

Any ideas would be great - thanks


Solution

  • NOTE: This answer is for Docusaurus v1

    Docusaurus maintainer here!

    You're right that Docusaurus doesn't support this out of the box. The probable reason that your script above doesn't work is because Docusaurus injects the <script> tags are above the <body> and when the script runs, the <body> hasn't loaded and there are no <a> tags to operate on. Try wrapping your code in document.addEventListener('DOMContentLoaded', ...) like this:

    document.addEventListener('DOMContentLoaded', function() {
      var links = document.getElementsByTagName('a');
      for (var i = 0; i < links.length; i++) {
        if (/^(https?:)?\/\//.test(links[i].getAttribute('href'))) {
          links[i].target = '_blank';
        }
      }
    });
    

    However, I recommend that you don't use that script and instead achieve the effect in a few other ways:

    1. Remarkable Plugins

    Customize this using Remarkable plugins. Remarkable is the Markdown engine that converts the Markdown to HTML.

    This remarkable-extlink plugin seems to be what you need. Try adding it into your siteConfig! Refer to the siteConfig documentation here.

    // siteConfig.js
    const extlink = require('remarkable-extlink');
    
    const siteConfig = {
      ...
      markdownPlugins: [
        function(md) {
          extlink(md, {
            host: 'yourhost.com', // The hrefs that you DON'T want to be external
          });
        },
      ],
      ...
    }
    

    2. Remarkable Options

    Remarkable supports making all links external by customizing the linkTarget option and Docusaurus exposes that in siteConfig (but isn't documented) and isn't working at the moment. I've submitted a PR to fix this, so look out for it in the next release. However, I wouldn't recommend this approach since it makes All your links open in new tab, not just the external ones.

    3. Use HTML in your Markdown

    Personally I would just use this option as it's the fastest. Also there's nothing wrong/bad about doing this and I love that I can fallback on HTML.

    4. Write your own Remarkable Plugin

    Write your own plugin that understands such a [link](url){:target="_blank"} syntax and generates the HTML that you want. This could be the best option if you don't want to use HTML but it requires the most effort.