Embedding Asciinema Casts in Hugo

Jun 20, 2018 21:53 · 561 words · 3 minutes read

Background

asciinema is an excellent tool for technical blogs, documentation, and landing pages alike. It allows you to create compact animations of commands along with their output and formatting with far less overhead than the alternative of creating a gif or mp4.

You can embed casts hosted on asciinema into your Hugo posts and pages by embedding a snippet like this directly into the markdown:

<script src="https://asciinema.org/a/186686.js" id="asciicast-186686" async></script>

This works fine, but if you’re already using a static site generator you are probably using a service like Netlify or even a basic S3 + CDN setup for your hosting. If so, you don’t really care about offloading assets and bandwidth and by hosting asciinema casts yourself you also get some extra flexibility in styling and customisation.

Embedding in Hugo with shortcodes

Download

Download the latest asciinema-player release from their GitHub page.

Add static assets to your head

Add the following to your template’s head section:

{{ if .Params.asciinema }}
    <link rel="stylesheet" type="text/css" href="{{ .Site.BaseURL }}css/asciinema-player.css" />
{{ end }}

Add the following just before the closing body tag in your template’s footer:

{{ if .Params.asciinema }}
    <script src="{{ .Site.BaseURL }}js/asciinema-player.js"></script>
{{ end }}

The conditions are so that the assets aren’t included in pages that they aren’t needed. The javascript is ~527KB uncompressed, so it’s a good idea to limit the pages it is downloaded for.

Create a shortcode

Instead of having to embed raw HTML every time you want to embed a cast, Hugo has a handy feature called shortcodes for exactly this use case.

Create a file layouts/shortcodes/asciinema.html with the following contents:

<p>
    <asciinema-player
        src="/casts/{{ with .Get "key" }}{{ . }}{{ end }}.cast"
        cols="{{ if .Get "cols" }}{{ .Get "cols" }}{{ else }}640{{ end }}"
        rows="{{ if .Get "rows" }}{{ .Get "rows" }}{{ else }}10{{ end }}"
        {{ if .Get "autoplay" }}autoplay="{{ .Get "autoplay" }}"{{ end }}
        {{ if .Get "preload" }}preload="{{ .Get "preload" }}"{{ end }}
        {{ if .Get "loop" }}loop="{{ .Get "loop" }}"{{ end }}
        start-at="{{ if .Get "start-at" }}{{ .Get "start-at" }}{{ else }}0{{ end }}"
        speed="{{ if .Get "speed" }}{{ .Get "speed" }}{{ else }}1{{ end }}"
        {{ if .Get "idle-time-limit" }}idle-time-limit="{{ .Get "idle-time-limit" }}"{{ end }}
        {{ if .Get "poster" }}poster="{{ .Get "poster" }}"{{ end }}
        {{ if .Get "font-size" }}font-size="{{ .Get "font-size" }}"{{ end }}
        {{ if .Get "theme" }}theme="{{ .Get "theme" }}"{{ end }}
        {{ if .Get "title" }}title="{{ .Get "title" }}"{{ end }}
        {{ if .Get "author" }}author="{{ .Get "author" }}"{{ end }}
        {{ if .Get "author-url" }}author-url="{{ .Get "author-url" }}"{{ end }}
        {{ if .Get "author-img-url" }}author-img-url="{{ .Get "author-img-url" }}"{{ end }}
    ></asciinema-player>
</p>

The fields map directly to those documented here. All fields are supported, but only the key is required.

Create casts

Follow the instructions to create new casts. Save them to static/casts/<key>.cast.

Using the shortcode

You can now embed asciinema casts in your Hugo posts and pages with the following shortcode:

{{< asciinema key="demo-cast" rows="10" preload="1" >}}

You also need to include asciinema = true in the frontmatter for you post too, to make sure the javascript and css assets are included.

Result

You should end up with something like this:

Check out my other post on adding custom fonts and glyphs to asciinema casts so your casts can show off your prompt without □ littered everywhere your special font characters are supposed to be.