How to alter the shortcode rendering for RSS output format?

I have a shortcode which I use in my markdown files. It adds parametrized boilerplate content which I want to exclude (or render differently) in my full-text RSS feed.

Is there a way to do this? Maybe there are some variables which I can check in my shortcode?

UPDATE: example repo

The clue lies in the embedded RSS Template:

{{ with .OutputFormats.Get "RSS" }}

I haven’t tried this myself, but with the above, you could create a condition to exclude parts of a content file.

@alexandros Thanks!

Following your advice I attempted to use {{ with .Page.OutputFormats.Get "HTML" }} (to render the shortcode only in HTML), but it crashed Hugo with this error: can't evaluate field Site in type *hugolib.OutputFormat.

Then I changed it to use different statements and it seems to be working:

{{ if .Page.OutputFormats.Get "HTML" }}
{{ end }}

Oops, this doesn’t work (have no idea why it seemed otherwise at first).

It looks like {{ .Page.OutputFormats.Get "RSS" }} is always <nil> inside the shortcode.

You’re most likely missing the context inside the shortcode. Try: {{ $.Page.OutputFormats.Get "RSS" }}

Unfortunately, this is also <nil>.

Is it possible to inject additional variable into .Page context inside rss.xml template

  <description>{{ .Content | html }}</description>

in order to check it in a shortcode inside the .Content?

You’re talking about splitting .Content and making the check in the template.

That’s a bit involved but:

  • strings.Contains might help to search within .Content without splitting it (look it up in the forum, it’s not in the Docs -don’t know why-)

  • I vaguely remember someone posting about splitting .Content on GitHub. (search the closed Hugo Issues on GitHub).

Also if you feel like uploading a repository with a test project, it would help people who want to check out whether it is possible to exclude a shortcode from the RSS pages.

Another (failed) experiment ([SOLVED] Current Output Format):


  {{ .Scratch.Set "isRSS" "true" }}
  {{ range (where .Data.Pages "Section" "!=" "")  }}{{ if not .Draft }}
    <title>{{ .Title }}</title>
    <link>{{ .Permalink }}</link>
    <pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
    {{ with }}<author>{{.}}{{ with $ }} ({{.}}){{end}}</author>{{end}}
    <guid>{{ .Permalink }}</guid>
    <description>{{ .Content | html }}</description>
  {{ end }}{{ end }}


    {{ $.Page.Scratch.Get "isRSS" }}

The Scratch is also empty inside a shortcode.

Also found this thread: Page context in shortcodes

UPDATE: This is why Scratch doesn’t work: Use .Scratch (or other params) in a shortcode

According to this issue, Hugo should recognize per-format shortcode templates (although this is undocumented

I created the quote.html and quote.rss.html shortcodes, but unfortunately this approach also doesn’t work (or I’m missing something).

Sample repo with the test project:

UPDATE: it looks like Hugo looks up only the following shortcode templates: ["quote.en.html.html" "quote.html.html" "quote.en.html" "quote.html"]

Just found another thread which solves this issue, but has unintended side effect: Filename for shortcodes when using custom RSS output format

Basically, if I change this (default):

home = ["HTML", "RSS"]
page = ["HTML"]

to this:

home = ["HTML", "RSS"]
page = ["HTML", "RSS"]

then my quote.rss.xml shortcode get picked up for rendering content inside RSS and it works as expected.

Unfortunately, this solution has one side effect - it generates additional per-page rss files which I do not want. Also each html post gets a link <link rel="alternate" type="application/rss+xml" ... to this RSS feed, which can confuse an RSS reader.

I think this is a bug - if RSS format is enabled for the home page, then when I render page Content in the rss.xml it should be considered to be part of the home page and inherit its format.

And the ugly solution I’ve settled with is this (in the rss.xml):

  <description>{{ .Content |  replaceRE "(?s)<!-- +begin_quote(.+?)end_quote +-->" "" | replaceRE "(?s)begin_quote_rss(.+?)end_quote_rss" "begin_quote_rss -->$1<!-- end_qoute_rss" | html}}</description>

Basically I placed both rendering variants into the quote.html, surrounded by html comments, and then remove one variant and uncomment another.

This is ugly, because in the actual site I have multiple shortcodes which I want to render differently, and this leads to multiple replaceRE pipes. But so far it works and does not produce additional *.xml files for pages.

The solution was inspired by this: Access page meta data while building the rss feed Go template programming (Partials: pipe, use as functions, recursive)

If you say that the home page should be output to RSS, we use any RSS-specific shortcode to render the shortcodes in the home page’s .Content. This currently does not extend to any page you include via where etc.

@bep Is it worth filing a bug on Github? So far in this thread I collected several other threads where people are trying to alter the content rendering for RSS feeds.

If you call it a feature request and not a bug, then yes.

Note that the “shortcode output format” support was added to support the AMP use case, so to speak. Where you set AMP as output format for all of your pages (not just the home page, as an example). In that case, you would have “output format variants” of every page. Doing the same for RSS would be wasteful.