Emacs, scripting and anything text oriented.

Sidenotes using ox-hugo

Kaushal Modi

Adding sidenotes using a Hugo shortcode and ox-hugo.

This is a post in the “Sidenotes” series.

2022-02-05Sidenotes using ox-hugo
2022-02-03Sidenotes using only CSS

The main focus of my previous post was the CSS for sidenotes. I also showed the companion HTML wrapper needed for that CSS to work. Here it is again for convenience:

<span class="sidenote-number">
  <small class="sidenote">
    sidenote content
  </small>
</span>
Code Snippet 1: Sidenote HTML example

Hugo shortcode #

Now .. You might be thinking that it’s not too practical to type that thing for each new sidenote. And you are right! That’s where we use the Hugo Shortcode feature.  Hugo Shortcodes are like Org Macros that are typically used to insert some HTML template around the user entered content. If you look at the above snippet, the outer span and small tags are just HTML boilerplate that the user will need to type mechanically around each sidenote. So the shortcodes are perfect for solving this annoyance.

If we design a paired shortcode for this, the above HTML example will change to below:

{{% sidenote %}}
sidenote content
{{% /sidenote %}}
Code Snippet 2: Example use of the sidenote shortcode

As you can see, this shortcode  This is a markdown-rendering shortcode i.e. a shortcode with {{​% .. %}} instead of {{​< .. >}}. So the insides of this shortcode will passed on to the Hugo Markdown renderer. now enables the user to focus on content writing than on writing boilerplate HTML. And the definition of that shortcode is pretty simple as well:

<span class="sidenote-number"><small class="sidenote">{{ .Inner }}</small></span>
Code Snippet 3: "sidenote.html" Hugo shortcode

The only Hugo-templating syntax used here is {{ .Inner }}. You can read more about it here, but the tl;dr is that the .Inner holds whatever content the user entered inside the {{​% sidenote %}} and {{​% /sidenote %}} tags.

Once you save that shortcode snippet to a layouts/sidenote.html file in your Hugo site’s directory, you are ready to use it.

        🛑 But wait! 🛑

Org mode special block #

It would be a shame to populate the Org source of this blog with Hugo-specific shortcodes when I am using ox-hugo 😄.

So instead, we just use the plain-old Org special blocks and tell ox-hugo that this “sidenote” special block be exported as a markdown-rendering Hugo shortcode. I do that by just placing this at the top of my Org file  See the Hugo Paired Shortcodes section in the ox-hugo manual to learn more about this. :

#+hugo_paired_shortcodes: %sidenote
Code Snippet 4: #+hugo_paired_shortcodes keyword for specifying "shortcode" special blocks

.. and then writing a “sidenote” type Org special block:

abc
#+begin_sidenote
example sidenote content
#+end_sidenote
def
Code Snippet 5: Example use of the sidenote special block

Normally, Org mode would insert a paragraph break where any Org block (like that sidenote special block) is used. So above would render as:

abc

  example sidenote content

def

But I am pretty sure that nobody would render sidenote references in their main text as above—instead, below is more normal 😄.

abc  example sidenote content def

In that normal example of the sidenote, ox-hugo trims the whitespace around the sidenote block. That is configured by customizing the org-hugo-special-block-type-properties variable:

(with-eval-after-load 'ox-hugo
  (add-to-list 'org-hugo-special-block-type-properties '("sidenote" . (:trim-pre t :trim-post t))))
Code Snippet 6: Whitespace trimming enabled by default for sidenote special blocks

You can read more about this whitespace trimming feature in the ox-hugo manual.

Summary #

One-time configuration #

  1. Create and save a “sidenote” Hugo shortcode as shown here.
  2. Configure ox-hugo to export “sidenote” special block as a markdown-rendering shortcode.
  3. Configure whitespace to be trimmed around those blocks using org-hugo-special-block-type-properties customization variable.

Org special block: sidenote #

Now just use the #+begin_sidenote .. #+end_sidenote Org special blocks wherever you need sidenotes.