Wrap Image with Figure Tag on Hugo without Shortcode

Automatically wrap img HTML tag inside a figure and insert figcaption based on alt attribute

Recently I’ve been thinking to migrate my blog from Blogger.com to a static site. After doing some research I decided to use Hugo.

One thing I like about Hugo is that they can produce a site from Markdown files. Now this markdown file is following CommonMark spec by default, which is great. But I have a case to always wrap images of my content inside a figure tag.

I actually can do this using Hugo shortcode, but I don’t want to use that because I want to make sure my markdown files following CommonMark spec. So it must be pure Markdown content with frontmatter, without filling it with custom rule from Hugo.

The second choice is to use HTML directly in markdown file. It’s a valid move because it’s allowable in CommonMark. But writing HTML tag is too verbose and not effective.

Luckily, I finally found a way to wrap markdown image automatically using regex function from Hugo.

Objective

Based on the problem above, there is a way to turn standard markdown image with alt text wrapped with figure tag and use its alt text as figcaption. Let’s see how we usually write an image in markdown.

There are two possibilities of produced image from markdown, with or without title text. Below are two examples of how you write an image in markdown.

![Alt Text](https://www.example.com/image.png)

![Alt Text](https://www.example.com/image.png "Title Text")

Using CommonMark spec, markdown text above will turn into HTML content like following code.

<p><img src="https://www.example.com/image.png" alt="Alt Text"></p>

<p><img src="https://www.example.com/image.png" alt="Alt Text" title="Title Text"></p>

Our objective is to wrap the image with figure so it’ll look something like this.

<figure>
  <img src="https://www.example.com/image.png" alt="Alt Text">
  <figcaption>Alt Text</figcaption>
</figure>

<figure>
  <img src="https://www.example.com/image.png" alt="Alt Text" title="Title Text">
  <figcaption>Alt Text</figcaption>
</figure>

Solution

What you need to modify is layouts/_default/single.html file. For example, let’s assume the content of the file is like the code listing below.

<article>

  {{ .Content }}
  
</article>

Now we just need to execute string replacement using regex. Hugo has builtin function for that, it’s called replaceRE. So here is the code to wrap image with figure tag.

<article>

  {{ $reAltIn := "<p><img src=\"([^\"]+)\" alt=\"([^\"]+)\" /></p>" }}
  {{ $reAltOut := "<figure><img src=\"$1\" alt=\"$2\"><figcaption>$2</figcaption></figure>" }}
  {{ $altContent := .Content | replaceRE $reAltIn $reAltOut | safeHTML }}

  {{ $reAltTitleIn := "<p><img src=\"([^\"]+)\" alt=\"([^\"]+)\" title=\"([^\"]+)\" /></p>" }}
  {{ $reAltTitleOut := "<figure><img src=\"$1\" alt=\"$2\" title=\"$3\"><figcaption>$2</figcaption></figure>" }}
  {{ $finalContent := $altContent | replaceRE $reAltTitleIn $reAltTitleOut | safeHTML }}

  {{ $finalContent }}

</article>

And that’s it, your produced image HTML will be wrapped with figure tag. Also, if you don’t set alt text, the image will stay the same wrapped with p tag which is a good thing if the image isn’t meant to be used as a figure.

Summary

Ok, that’s a little research I’ve done on weekend to explore Hugo features. So far it’s been fun experience tinkering with Hugo.

I’ll write more about Hugo next time.

References