Website/content/docs/website/hugo/shortcodes.md

5.7 KiB

title date draft
Shortcodes 2024-02-04T22:22:43+01:00 true

Custom shortcodes

Hugo provides built-in shortcodes, Hextra adds some more. However, I need to embed other media sources and want to migrate some of my own HTML and CSS structures. For this purpose there is a official guide on how to create your own shortcodes.

iFrame

To embed arbitrary media layouts/shortcodes/iframe.html is created containing the following HTML code:

{{ $src := .Get "src" -}}
{{ $class := .Get "class" -}}

<div class="wrap-element{{ with $class }} {{ . }}{{ end }}">
  <iframe class="wrapped-iframe"
    {{ with $src }}src="{{ . }}"{{ end }}
    frameborder="0" allowfullscreen>
  </iframe>
</div>

The values of the named shortcode parameters src and class are saved into variables and inserted, if not null. Additionally, the file assets/css/custom.css is created and populated with:

/* Responsive iframe */

.wrap-element {
  margin-top: 1.5rem;
  position: relative;
  overflow: hidden;
  padding-top: 56.25%;
}

.wrapped-iframe {
  border-radius: 0.5rem;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

@media (min-width: 1280px) {
  .funkwhale {
    padding-top: 28.12%;
  }
}

The definitions of the CSS classes wrap-element and wrapped-iframe are applied to the div and iframeelement to make the embeded resource responsible. This idea originates from a snippet of W3Schools. The funkwhale class is used for embedding Funkwhale media in order to decrease the height of the iframe on bigger screens.

As a result the following shortcode embeds my Influenca (Official Musicvideo):

{{</* iframe src="https://libre.video/videos/embed/163971b8-dfff-4309-a579-185090ae88c5" */>}}

Raw HTML

For using raw HTML code in a Markdown the file layouts/shortcodes/rawhtml.html is created as follows:

<!-- raw html -->
{{.Inner}}

This way I can write raw HTML code between an opening {{</* rawhtml */>}} and closing {{</* /rawhtml */>}} shortcode. The idea is taken from a blog post by Ana Ulin.

Media figure

Audio and video sources can be enclosed in a <figure>1 element providing additional description in a caption and a link to the source file. My audio shortcode is inspired by the solution in the Zen theme:

{{ $caption := .Get "caption" -}}
{{ $preload := .Get "preload" | default "none" -}}
{{ $src := .Get "src" -}}
{{ $type := .Get "type" -}}

<figure class="media">
  <audio controls preload="{{ $preload }}">
    <source src="{{ $src }}" {{ with $type }}type="{{ . }}"{{ end }}>
  </audio>
{{ with $caption -}}
  <figcaption>{{ . | markdownify }}</figcaption>
{{ end }}
{{ with $src -}}
  <a href="{{ . }}">Source link</a>
{{ end -}}
</figure>

The video shortcode is extended by a poster attribute to view an image before playing back the video:

{{ $caption := .Get "caption" -}}
{{ $poster := .Get "poster" -}}
{{ $preload := .Get "preload" | default "none" -}}
{{ $src := .Get "src" -}}
{{ $type := .Get "type" -}}

<figure class="media">
  <video controls preload="{{ $preload }}" poster="{{ $poster }}">
    <source src="{{ $src }}" {{ with $type }}type="{{ . }}"{{ end }}>
  </video>
{{ with $caption -}}
  <figcaption>{{ . | markdownify }}</figcaption>
{{ end }}
{{ with $src -}}
  <a href="{{ . }}">Source link</a>
{{ end -}}
</figure>

The additional <figcaption> and <a> elements are organized by a grid2 using the following CSS code added to the assets/css/custom.css file:

/* Media figure */

figure.media {
  display: grid;
  grid-template-areas: 'player player'
                       'caption link';
  grid-template-columns: 2fr 1fr;
  margin-top: 1rem;
}

figure.media figcaption {
  margin: 1rem;
  grid-area: caption;
}

figure.media audio {
  border-radius: 0.5rem;
  grid-area: player;
  max-height: 40px;
  width: 100%;
}

figure.media video {
  border-radius: 0.5rem;
  grid-area: player;
  width: 100%;
}

figure.media a {
  margin: 1rem;
  grid-area: link;
}

Nesting

In order to nest several shortcodes using the Hextra theme, I have to explicitly set Goldmark markdown renderer to unsafe mode by including the following setting in the hugo.yaml configuration file.

markup:
  goldmark:
    renderer:
      unsafe: true

Shortcode adaption

Sometimes built-in shortcodes just need a slight adaption to work for me.

Custom CSS class

The figure shortcode already provides the option to provide a custom class. In order to keep the size of a figure for a thumbnail image small I add the following CSS code to the assets/css/custom.css file:

/* Cover figure */

figure.thumbnail {
  width: 200px;
}

  1. Figure in the MDN Web Docs. ↩︎

  2. CSS grid layout in the MDN Web Docs ↩︎