Shortcode in Front Matter

I’ve seen discussions on including shortcodes in the front matter of a page. They all say it can’t be done, but I have a use case that is slightly different from the discussions.

Background:
I’m building a theme that makes use of blocks to create it’s layouts. Each block is part of a front matter array. I’ve created shortcodes for things typically used in footers like “copyright”. I’ve got a parser that works for my needs, but it’s only going to work for very specific cases.

{{ $scratch := newScratch }}
{{ $scratch.Set "rendered" nil }}
{{ $scratch.Set "templates" (slice) }}
{{ $shortcodes := findRE "{{< ?(#[a-z]+ )?[a-z]*? >}}" .content }}
{{ $page := .page }}
{{ $site := .site }}
{{ $content :=  split (replaceRE "{{< ?(#[a-z]+ )?[a-z]*? >}}" "," .content) "," }}
{{ range $shortcodes }}
  {{ $scratch.Add "templates" ( trim (trim . " >}}") "{{< ")}}
{{ end }}
{{ range $scratch.Get "templates" }}
  {{ $partial := printf "%s.html" . | urlize }}
{{ end }}
{{ range $index, $part:= $content }}
  {{ $part | markdownify }}
  {{ $shortcode :=  (index ($scratch.Get "templates") $index) }}
  {{ if ne $shortcode nil }}
    {{ $partial := printf "partial-shortcodes/%s" $shortcode | urlize }}
    {{ partial $partial (dict "page" $page "site" $site "content" $content ) }}
  {{ end }}
{{ end }}

Question:
Anyone out there have some experience with processing Hugo shortcodes? I’d like to be able to process the same way Hugo does. Right now I can only include partials instead of shortcodes. And I lose the ability to apply markdownify correctly, since all new lines are removed I don’t get paragraph tags.

Thanks in advance!

Hi,

I have recently done something similar where I have a parser go through standard markdown (no shortcodes, no partials) to pluck out images (i.e. ![alt text](src-string "image title")) and replace with a responsive figure element.

It does it by:

  1. find all instances (.md strings) where there is an image
  2. range over instances:
    1. extract parameters
    2. call a custom figure partial which returns a HTML string
    3. replace instance with new HTML string continually cleaning and updating your whole block of content
  3. once all the images have been replaced, the entire block and be mardownified.

I am not sure how performant this is, but it has worked surprisingly well.

But, your question is about shortcodes.

From my understanding, shortcodes are syntactic sugar for content creators to use while writing markdown. This is opposed to the developers writing code to render said markdown. Another way to think about it, is that shortcodes are workarounds/addendums to Markdown’s limited abilities. (see: Shortcodes | Hugo)

I would suggest that that you tweak your parser to look for shortcodes and programatically call a partial (this could allow you (as the developer) to also add some conditional logic, etc. which can be hidden from the “content authors”).


This seems to be related to an issue? feature? of Blackfriday where orphan lines of markdown are rendered without <p> tags. or it could be caused by what your partial is doing … are you using return?

Thanks,

The issue with the paragraph tags was due to me splitting the content. That got rid of all the newlines. You mentioned you had a partial that was returning HTML. I didn’t realize you could do that. So I didn’t need to split the content anymore.

Worked like a charm.

This is my partial named process-shortcodes

{{ $scratch := newScratch }}

{{ $scratch.Set "partials" (slice) }}
{{ $scratch.Set "content" .content }}
{{ $shortcodes := findRE "{{< ?(#[a-z]+ )?[a-z]*? >}}" .content }}

{{ $page := .page }}
{{ $site := .site }}

{{ $content :=  split (replaceRE "{{< ?(#[a-z]+ )?[a-z]*? >}}" "," .content) "," }}

{{ range $shortcodes }}
  {{ $scratch.Add "partials" ( trim (trim . " >}}") "{{< ")}}
{{ end }}

{{ range $index, $partial := $scratch.Get "partials" }}
  {{ if ne $partial nil }}
    {{ $path := printf "bugo-shortcodes/%s" $partial | urlize }}

    {{ $rendered := partial $path (dict "page" $page "site" $site "content" . ) }}

    {{ $shortcode := index $shortcodes $index }}
    {{ $shortcode }}
    {{ $scratch.Set "content" (replace ($scratch.Get "content") $shortcode $rendered) }}
  {{ end }}
{{ end }}

{{ return $scratch.Get "content" }}

And I call it like this

{{ partial "utilities/process-shortcodes" (dict "page" $page "site" $site "content" .content) | markdownify }}

The $shortcodes RegEX needs some work. And I can’t pass variables into it yet. Any insight on this?

What exactly are you trying to do? pass variables into the partial? or programmatically create regex statements?

also, it seems like you don’t need Scratch here … might just be confusing things.