Nesting shortcodes and markdown

Is it possible to

  • use nest shortcodes
  • and use markdown inside the outermost shortcode

without setting unsafe=true?

For example, we have a resource_link shortcode (simplified implementation below). We want it to be able to (1) render a markdown title, and (2) the markdown title should support shortcodes, like subscripts and superscripts.

Implementations:

{{/* base-theme/layouts/shortcodes/sup.html */}}
<sup>{{- .Get 0 | markdownify -}}</sup>

{{/* base-theme/layouts/shortcodes/simplified_rlink.html */}}
[{{- .Inner -}}](dummy_url)

Usage:

Some markdown text {{% simplified_rlink %}} Super: {{< sup "a b" >}} bold: **abc** {{% /simplified_rlink %}} and some more text

Result:

Whereas I would expect that the link should have superscripts in it from the {{< sup "a b" >}} shortcode.

Notes:

  • I do get the expected output with unsafe=true. But it seems like this should not be necessary: The markdown file contains no raw HTML.

So, is there any way to make the original implementation work? Other than setting unsafe=true.

I can almost get the expected output if I do not use a nested shortcode, and instead use a parameter along with .RenderString:

{{- $title :=  index .Params 0 -}}
<a href="dummy_url">{{- $title | .Page.RenderString -}}</a>

and used via {{< simplified_rlink2 `Super: {{< sup "a b" >}} bold: **abc**` >}}:

This might be ok, but could cause trouble for content creators wanting inline code as part of a link.

No, it is not. And the restriction is not limited to nested shortcodes.

When you invoke a shortcode with the {{% %}} notation, any raw HTML will be omitted unless you set markup.goldmark.renderer.unsafe to true in your site configuration. For example…

layouts/shortcodes/foo.html

<div>foo</div>

markdown

{{< foo >}}
{{% foo %}}

rendered

<div>foo</div>

<!-- raw HTML omitted -->

Thanks for the explanation. Another approach I considered was

<a href="dummy_url">{{- .Inner | .Page.RenderString-}}</a>

but I believe .Inner has already had its shortcodes replaced with HTML, so they end up getting ommited when I pass to RenderString.

Is it possible to access the contents of Inner before shortcode substitution, so that RenderString could do the substituting?

No.

layouts/shortcodes/foo.html

<div>{{ .Inner | .Page.RenderString }}</div>

markdown

{{< foo >}}
Some **bold** text.
{{< /foo >}}

{{% foo %}}
Some **bold** text.
{{% /foo %}}

rendered

<div>Some <strong>bold</strong> text.</div>

<!-- raw HTML omitted -->

When you invoke a shortcode with the {{% %}} notation, any raw HTML will be omitted unless you set markup.goldmark.renderer.unsafe to true in your site configuration.

Using the unsafe option is only unsafe if you are not in control of the content that is created on your site.

I am now clear that {{% ... %}} will discard any HTML inside, even if that was rendered by a shortcode. (This still seems a little odd to me, since I think of {{%...%}} as rendering markdown, and I also think of shortcodes as part of markdown in Hugo.)

It sounds like our best option at the moment for markdown + shortcodes within a shortcode

<a href="dummy_url">{{- .Get 0 | .Page.RenderString -}}</a>

invoked as {{< foo `some **bold** and {{< other_shortcode >}}` >}}.

Thanks again for the explanations.

1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.