Conditional .Inner logic for shortcodes

Can’t seem to figure out the logic for checking to see if a shortcode is expanded with a closing shortcode or not.

Essentially, the idea is to allow html or markdown in shortcodes. It seems this is only possible by opening and closing the shortcode, with content between the tags and accessable by calling .Inner. Is this correct?

So the approach that seems best is to allow shortcode tags to be “opened” to allow for markup, or not.

The goal is to allow for either of these within the same file:

this

<!-- anyfile.md -->
{{% headline  "This is a Simple Headline" %}}

and/or

{{% headline %}}
This is a *Fancy* Headline
{{% /headline %}}

But I can’t seem to figure out the logic. Here’s what I have so far:

<!-- headline.html -->
<div class="headline">
  <h3>
    {{ with .Get 0 }} {{.}}
      {{else}} {{.Inner}}
    {{end}}
  </h3>
</div>

This works if there’s only one “opened” shortcode and it’s at the top of the file. Otherwise, the whole block simply doesn’t get rendered. Is there some way to check for a length inside of an “unopened” shortcode?

Also: Perhaps the best way around this is to simply somehow allow for html or markdown markup within the shortcode itself (without breaking it out into opening and closing shortcode tags). Regarding my use-case of interest, read Lonely Planet’s approach to a maintainable style guide. I’m essentially trying to adapt their approach to theme development with Hugo.

I got this working, but in a slightly odd way:

<div class="headline">
  {{ if len .Inner }}
    <h3>{{ .Inner }}</h3>
  {{ else }}
    <h3>{{ .Get 0 }}</h3>
  {{end}}
</div>

(.Get 0 causes hugo server --watch to crash if it isn’t set, IIRC.)

In the content file, I had to do:

{{% headline "Simple Headline" %}}{{% /headline %}}

{{% headline %}}
*Fancy* Headline
{{% /headline %}}

I am guessing that when Hugo sees a closing tag, it assumes that all versions must have closing tags. BTW, while .Get 0 fails hard, .Get "field" does not.

Thanks for the help, @halostatue

Your solution and my initial attempt (above) seem to have the same functional result. I hadn’t tried putting a closing tag on non-opened shortcodes (eg: {{% headline "Simple Headline" %}}{{% /headline %}}), but when I add it things work. All the while, using if len seems much cleaner…

In the spirit of Markdown being a minimal formatting language, having to add closing tags to non-opened shortcodes isn’t much of a solution (though it’s good to know that it works as a temporary work-around).

It’d be awesome to be able to use opened and non-opened shortcodes in the same content file without having to add closing tags to non-opened ones.

The goal of shortcodes was that nothing but the template itself is required to use a shortcode. There’s no configuration of any kind. This makes them very easy to create and use.

When we introduced .Inner and paired shortcodes the big challenge was how to do this without a. Adding configuration, b. Adding a different type of shortcode. Ultimately I decided that the best approach would be to look for .Inner. If it was used then it was a paired shortcode and we needed to look for an ending tag.

While I do see a potential advantage of being able to use it without an ending, ultimately this leads to ambiguity.

Take this example.

{{% headline "Simple Headline" %}}
{{% headline type="1" %}}
*Fancy* Headline
{{% /headline %}}

Which headline opening tag is paired with the closing tag? The parser can’t base it off of the parameters passed because both single and paired shortcodes use them.

Yeah, it doesn't seem like a big deal to require two shortcodes here - one for the single and one for the paired. It's probably a lot more clear for the user as well.

@spf13 Thanks for sharing about the logic that went into architecting shortcodes. They’re certainly quite useful… just trying to find the use case “possibliity boundaries.”

If it was possible to use markdown or html markup within unopened short tags I wouldn’t have any need for conditional .Inner logic. And just to make sure, this isn’t possible with Hugo, correct? (I’ve tried and it doesn’t work… didn’t know if I was missing something.)

For me it feels very strange to have a inline parameter treated as a markup format. For example if I set color as “#123456” I would not expect that to be a headline.

Currently it’s not possible to treat an inline parameter as markdown. I think this is the right decision.

You can use HTML. There’s nothing to intrepret. It’s already in the final state. You probably need to tell the go template library that it is HTML in the shortcode template.

What might be nice is if, like safeHtml, there were a markdownHtml function that could be used within the shortcode so that we can choose to make this happen on a per-shortcode basis. I haven’t really needed to do it with any of the shortcodes that I’ve made, but there have been some surprising behaviours with the interaction of shortcodes.

Shouldn’t be too hard to do… not sure if it would be worth it though. Most markdown formatting is based on line returns which can’t be expressed inline.

Still it wouldn’t hurt to add this as a feature and let shortcode creators be creative.

What about supporting some type of yaml|json|toml data structure to be passed through with shortcodes? I’ve found myself wanting to use shortcodes for lists of organized data (often nested) but it seems they can only currently support single key -> values, correct?

To me this seems like it’d allow for the ultimate flexibility/creative-ability, especially if markdown could be combined with this. I have no idea how feasible or not this type of implementation might be… but it would be pretty sweet :slight_smile:

@halostatue, I like the idea of a markdownHtml function/filter. Jekyll has this and it’s quite useful, they call it the “markdownify” filter. It can be used for parsing anything as markdown, including front-matter and data from data files.

@isaac, markdownify is probably a good name for this sort of function.

@spf13 one thing that I’ve found slightly annoying about paired shortcodes is that the process of running markdown on .Inner puts paired <p>…</p> around the inner text—making it impossible to do something like
{{% x ref="page-name" %}}link text{{% /x %}} inline. I’m not sure how I’d do it otherwise, but I just thought I’d mention.

(My x shortcode gives me a page-name-based cross-reference linking capability.)

1 Like

See