How to enable target="_blank" links in Zola

Zola is a nice static site generator. In fact, so nice that I moved this site over from Pelican a few weeks back.

The one thing I was missing though was the ability to set target="_blank" on links within the content. There is a relevant Github issue from last year which proposes this feature for Zola. But the general consensus from that thread is that this functionality should ideally be supported by pulldown-cmark, which is the Markdown rendering library that Zola uses.

While I do agree with that decision, the relevant issue from the pulldown-cmark issue tracker looks a little discouraging. It is referenced by a different issue titled Extensible rendering prototype which is currently marked as closed with a comment from the maintainer saying that it's unlikely for there to be much progress on this in the foreseeable future.

I wasn't sure what to make of the whole thing, but I do understand how hard it can be to prioritize open-source projects in between daily work and personal life. And since my Rust skills at the moment are beginner-level (at best), I tried to work my way around it using JavaScript instead.

The first step was to define a configuration option called enable_target_blank to control this setting. Zola allows arbitrary user-defined configuration options, so this was rather straight forward.

[extra]
enable_target_blank = true

I then added the following JavaScript snippet in the base HTML template.

var enableTargetBlank = function() {
    var parents = document.getElementsByClassName('with-target-blank');

    for (let parent of parents) {
        var links = parent.getElementsByTagName('a');

        for (let link of links) {
            if (link.hostname !== window.location.hostname && link.target === "") {
                link.target = "_blank";
            }
        }
    }
};

{% if config.extra.enable_target_blank %}
enableTargetBlank();
{% endif %}

This code snippet picks all the <a> elements on the page which are direct / indirect descendants of any elements containing the with-target-blank CSS class. For all such links, we set the target attribute to _blank, in case the links are external and if the target isn't set to something already. And all this code is defined in the base template so that it's also available in all the other templates (due to template inheritance).

As a result, you can now add the with-target-blank class on container elements in which you want all the links to open in a new tab. On this site, for instance, I do this only on elements containing Markdown rendered from Zola. Here's the relevant portion from the page.html template that I use.

<div class="row">
    <div class="col with-target-blank">
        {{ page.content | safe }}
    </div>
</div>

Note that for this to work, there are two pre-requisites.

  1. JavaScript needs to be enabled.
  2. You should be able to modify the template code. I'm not sure if you can put custom code in off-the-shelf themes that Zola provides. But since I use a custom theme for this site, I didn't have to look too much into this.

Other than that though, this approach is quite straight-forward and works exactly like one would expect.