6

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

Yangshun Tay
  • 49,270
  • 33
  • 114
  • 141
RedBeard
  • 145
  • 2
  • 15

1 Answers1

7

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.

Yangshun Tay
  • 49,270
  • 33
  • 114
  • 141
  • 1
    I used the remarkable plugin - it works great, thank you Yangshun – RedBeard May 03 '19 at 08:13
  • Glad to hear that :) – Yangshun Tay May 03 '19 at 17:23
  • 1
    @YangshunTay im attempting to use the remark-external-links project in my docusaurus v2 remarkPlugins block via `require('remark-external-links')`, but it doesn't seem to be resolving. Any chance you can update this with a reference for v2? – James McShane May 19 '20 at 03:34
  • @YangshunTay @JamesMcShane I had added a remark plugin for `remark-math` with `presets: [["@docusaurus/preset-classic",{docs: {remarkPlugins: [math],...` but changing to `remarkPlugins: [math, function(md) {extlink(md, {host: 'docs.etsycorp.com',})}],` was definitely wrong, so helpful pointers would be appreciated. – dlamblin Aug 11 '22 at 17:29
  • @JamesMcShane I thought maybe something like: `remarkPlugins: [math, [extlink, {host: 'docs.site.com',}]],` would work in `docusaurus.config.js`'s presets, docs block similarly to https://github.com/facebook/docusaurus/blob/main/packages/docusaurus-remark-plugin-npm2yarn/README.md, but I get something about a url not being a string. – dlamblin Aug 11 '22 at 17:46
  • @JamesMcShane for Docusaurus 2 as it's using MDX and NOT Remarkable I had to find a remark or rehype module. https://github.com/remarkjs/remark-external-links lead me to use https://github.com/rehypejs/rehype-external-links but it wasn't fun. – dlamblin Aug 11 '22 at 19:55