Escaping shortcodes while within another shortcode appears to produce inconsistant results

I’ve encountered a strange behavior with shortcode escaping while inside another shortcode. My problem is that if I escape a shortcode while inside something like the details shortcode, the escaped shortcode is still processed and rendered. But double escaping the shortcode correctly prints a (singly) escaped shortcode. Neither of these options print the shortcode as un-escaped (what I want).

In some situations, it appears that double escaping can display an un-escaped shortcode, if there are other shortcodes are also being used/escaped elsewhere inside the details shortcode. I haven’t dug around enough to find all the edge cases.

Escaping short codes appears to work correctly when outside of the details shortcode.

It might be easier to explain with a screenshot and example code. Here’s some example markdown using the built-in highlight and details shortcodes.

{{< details summary="Shortcode escaping demo: Several in one `details`" open="true" >}}
No escape (Renders unexpectedly)

```go-text-template
Inline highlighted code → {{< highlight lua "hl_inline=true" >}}if true print("hello world!") end{{< /highlight >}}.
```

One escape (Renders as if not escaped)

```go-text-template
Inline highlighted code → {{</* highlight lua "hl_inline=true" */>}}if true print("hello world!") end{{</* /highlight */>}}.
```

Two escapes (At least does what I want)

```go-text-template
Inline highlighted code → {{</*/* highlight lua "hl_inline=true" */*/>}}if true print("hello world!") end{{</*/* /highlight */*/>}}.
```
{{< /details >}}


{{< details summary="Shortcode escaping demo: One escape on it's own" open="true" >}}
One escape on it's own (Renders as if not escaped)

```go-text-template
Inline highlighted code → {{</* highlight lua "hl_inline=true" */>}}if true print("hello world!") end{{</* /highlight */>}}.
```
{{< /details >}}


{{< details summary="Shortcode escaping demo: Two escapes on it's own" open="true" >}}
Two escapes on their own (Renders "as expected", but single escape didn't give me what I want.)

```go-text-template
Inline highlighted code → {{</*/* highlight lua "hl_inline=true" */*/>}}if true print("hello world!") end{{</*/* /highlight */*/>}}.
```
{{< /details >}}

### Examples outside of the shortcode

One escape outside of the `details` shortcode (Renders as expected)

```go-text-template
Inline highlighted code → {{</* highlight lua "hl_inline=true" */>}}if true print("hello world!") end{{</* /highlight */>}}.
```

Two escapes outside of the `details` shortcode (Renders as expected)

```go-text-template
Inline highlighted code → {{</*/* highlight lua "hl_inline=true" */*/>}}if true print("hello world!") end{{</*/* /highlight */*/>}}.
```

(I’ve got some CSS happening in this screenshot, but aside from a ::before adding the name of the language to the code block, I don’t have any other templates or Shortcodes that mess with the HTML.)

I tested this demo on Hugo 0.141.0 (hugo v0.141.0-e7bd51698e5c3778a86003018702b1a7dcb9559a linux/amd64 BuildDate=2025-01-16T13:11:18Z VendorInfo=gohugoio) and also 0.140.0 (hugo v0.140.2-aae02ca612a02e085c08366a9c9279f4abb39d94 linux/amd64 BuildDate=2024-12-30T15:01:53Z VendorInfo=gohugoio).

Is this a bug, or am I overlooking something?

(It’s also getting late out here. I figured I ought to post this while it’s fresh before I call it a day, but I probably wont be able to reply until tomorrow.)

Escaping shortcodes within another shortcode is, and probably always will be, imperfect. It depends on how you call the shortcode and what the shortcode does with the inner content, and whether you’re willing to set markup.goldmark.renderer.unsafe = 'true' in your site configuration.

Could this imperfect behavior be improved? Maybe, but nobody’s going to spend any time on it.

Instead, replace the left-opening braces with the equivalent HTML entity:

&lbrace;{% highlight lua "hl_inline=true" %}} if true print("hello world!") end &lbrace;{% /highlight %}}.

That’s a pretty clean solution. My current workaround is using alert-style blockquotes and render hooks to make my own details block without the details shortcode. But it has it’s own downsides, so I might switch to your suggestion.

Thank you!

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