In this post, I explained how I set up Obsidian and Hugo to enable one-to-one, side-by-side Markdown editing. However, this solution still did not account for image resizing.

I use a plugin called Mousewheel image zoom to make resizing images inside Obsidian easy. This plugin uses the following format for image width:

![|300](paste.png)

Hugo does not recognize this format, and instead requires a shortcode like this:

{{< figure src="paste.png" width="300" >}}

My options, were either to modify the Obsidian side (requiring unfamiliar plugin work) or to change how Hugo interpreted the Markdown image format. I chose the latter.

There are two main approaches to modifying Markdown display in Hugo: Shortcodes and Render hooks.

Shortcodes

Shortcodes are custom Go templates that you put into your Markdown. Hugo then interprets the templates at runtime and renders content. For example (), a shortcode like this: {{< bold >}} Bold this text {{< /bold >}} could render like this: Bold this text.

(While writing this post, I discovered that there is a hidden syntax for showing shortcodes on Hugo sites. Otherwise, Hugo will interpret the shortcode as a command (as it should) and it will not display as text.)

The issue with shortcodes is that they lead to the same problem I am trying to avoid: they require me to add extra formatting to the post in Obsidian that renders in a different way in Hugo. If shortcodes don’t work, the alternative is:

Render hooks

Render hooks intercept Markdown for specific types of page content (code blocks, headings, images, and links) and modify how it is converted into HTML. This seems to be exactly what I want, because custom format handling happens in Hugo instead of Obsidian.

I wrote a image render hook which lives at /layouts/_default/_markup/render-image.html. In this file, I am able to specify a regular expression to identify images with the desired .PlainText attribute (|300, for example), extract the width value, and create the HTML object with a matching width tag.

Image processing render hook:

{{ if findRE `^\|\d+$` .PlainText }}
  {{/* Custom Obsidian Format Image Rendering */}}
  {{ $width := (replaceRE `^\|` "" .PlainText) }}
  <figure>
    <img src="{{ .Destination | safeURL }}" width="{{ $width }}" alt="{{ .Text | safeHTMLAttr }}"
         {{ with .Title }} title="{{ . | safeHTMLAttr }}" {{ end }} />
  </figure>
{{ else }}
  {{/* Default Hugo Image Rendering */}}
  <figure>
  <img src="{{ .Destination | safeURL }}" alt="{{ .Text | safeHTMLAttr }}"
       {{ with .Title }} title="{{ . | safeHTMLAttr }}" {{ end }} />
  </figure>
{{ end }}