Template interpolation

An inline shortcode carries its Go template in the page, so the preview pane has the template right there. It can’t run it, since there’s no Hugo in the browser, but it can do the next best thing: find the places where the template reads its parameters, drop the values in and throw away whatever’s left. This page is about how far that gets you.

It only applies to inline shortcodes. Block shortcodes use the {{field}} preview templates from site.yaml, and Emet never reads your layouts/shortcodes/*.html files in the preview.

What gets resolved#

Emet makes several passes over the template text:

  1. Variable assignments from parameters, {{ $src := .Get "src" }} and {{ $first := .Get 0 }}, are recorded and removed.
  2. References to those variables, {{ $src }}, are replaced with the recorded value.
  3. Direct reads, {{ .Get "src" }} and {{ .Get 0 }}, are replaced with the value.
  4. Reads inside parentheses, (.Get "src"), are replaced with the value wherever they appear.
  5. Every remaining {{ ... }} is deleted, and runs of blank lines are collapsed.

Whitespace-trimming delimiters ({{- and -}}) are fine throughout. A parameter that wasn’t given comes out empty.

So this template, used as {{< img.inline src="/images/cat.jpg" alt="A cat" >}}:

{{ $src := .Get "src" }}
<figure>
  <img src="{{ $src }}" alt="{{ .Get "alt" }}">
  {{ with .Get "caption" }}<figcaption>{{ . }}</figcaption>{{ end }}
</figure>

previews as:

<figure>
  <img src="/images/cat.jpg" alt="A cat">
</figure>

The with block disappeared entirely, which is right in this case because no caption was given. It would also disappear if one had been, which is the limitation.

What doesn’t#

Anything that isn’t a plain parameter read is deleted in pass 5, along with the text inside it:

Template What happens
{{ if .Get "wide" }}...{{ end }} The if and end go; the text between them stays, condition or no condition
{{ range ... }}...{{ end }} Same: the body is kept once, unrolled
{{ .Get "title" | upper }} Deleted. A pipe makes the whole directive unrecognisable, so you don’t even get the untransformed value
{{ printf "%s!" (.Get "name") }} The (.Get "name") is replaced by the value, then the whole printf directive is deleted, value and all
{{ .Inner }}, {{ .Page.Title }}, {{ .Site.Params.x }} Deleted
{{ partial "x" . }}, {{ template "x" }} Deleted

In other words, a template that does nothing cleverer than echo its parameters previews well, and the more Go you put in it the more the preview turns into a skeleton. The structure and the parameter values survive; the logic doesn’t.

If nothing survives at all, the box says “Empty template”. A usage whose definition isn’t in the page says “Definition not found”.

How it’s shown#

Each inline shortcode becomes a box in the preview with a header giving the name and a def or use badge, and the interpolated HTML beneath it. The HTML is sanitised like everything else in the preview frame: scripts and event handlers are stripped.

For the real rendering, you want the Hugo server preview.