← back

Wikilinks

2 min read

If you happen to use Obsidian, you'll be very familiar with [[wikilinks]]. This feature is a DIY implementation that, client-side, transforms raw [[link]] into <a> tags. It's very bad for SEO, and I don't necessarily recommend using it. But it's there, for the period of time that Zola doesn't yet have official wikilink support.

The Details

The implementation for wikilinks lives in static/js/wikilinks.js. It works as follows:

  1. For each node in the DOM, if it's a text node and its parent is not a script, style, code, pre, or textarea element, do:
  2. Check for a match with a wikilink regex pattern.
  3. If we match, construct a document fragment, where we replace the wikilink syntax with an anchor tag. The URL of the anchor tag is generated by a simple slugification of the page name, and the display text is either the page name or the custom display text if provided.
  4. Replace the original text node with the constructed document fragment.

The interesting part of the implementation is shown below, where we convert a page name, e.g. chicken for [[chicken]], into a URL, e.g. /chicken/. The slugification process is very basic, and simply lowercases the page name, trims whitespace, and replaces spaces with dashes. There are also special cases for home (which links to the root) and for in-page anchors (which start with #).

    const pageNameToUrl = (pageName) => {
        const slug = pageName
            .toLowerCase()
            .trim()
            .replaceAll(/\s+/g, '-');

        // Special case: "home" links to root
        if (slug === 'home') {
            return '/';
        }

        // Special case: #some-header links to in-page anchor
        if (slug.startsWith('#')) {
            const currentPage = globalThis.location.pathname.replace(/\/?$/, '/'); // Ensure trailing slash
            return currentPage + slug;
        }

        // Ensure leading slash, trailing slash
        const url = '/' + slug.replaceAll(/^\/+|\/+$/g, '') + '/';
        // Ensure we respect the base URL
        const base = document.querySelector('base')?.getAttribute('href') || '/';
        return base + url;
    };

Go back to read [[#The Details]] (made with wikilink syntax, e.g. [[#The Details]]) or alternatively The Details with regular anchor link syntax.