Images in Hugo RSS?

When I use inoreader I see many other feeds include an image in their preview.
Is there a way to do this or a template that is a good example?
I found one discuss post about it - but I’m not following how I would implement it.
I am using the hugo-icarus theme that has a little bit of image handling built-in (just noting it in case it helps in any responses).

Hmmmm - here is my front matter template for displaying the image - can I hack it directly into the rss template?

{{ if and (isset .Params "banner") (not (eq .Params.banner "")) }}
  <a href="{{ .Permalink }}" itemprop="url">
  <img src="{{ .Params.banner | absURL }}" class="article-banner">
{{ end }}

DarwinJS, just to be clear, do you mean an image for every item in the feed or a general image/banner for the RSS-feed?

An image per individual item.

Right. So, first of all, this is how you edit the RSS template.

But, in order to validate a feed with images you need to edit the template like the example below. Pay extra attention to the tags on the first row (you may have to scroll horizontally), these are needed in order to validate multimedia RSS feeds. Also make sure you understand chomp.

<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1" xmlns:content="http://purl.org/rss/1.0/modules/content" xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <title>Title of feed</title>
        <link>{{ .Permalink }}</link>
        <language>en-EN</language>
        <description>Description of your feed</description>
        <copyright>{{ .Site.Copyright }}</copyright>
        <lastBuildDate>{{ .Site.LastChange.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate>
        <atom:link href="{{ .Permalink }}" rel="self" type="application/rss+xml" />

        {{ range .Data.Pages }}
        {{ if not (in .URL "_index")}}
            <item>
            <title>{{ .Title }}</title>
            <link>{{ .Permalink }}</link>
            <pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
            <guid>{{ .Permalink }}</guid>
            <dc:creator>{{ .Params.author }}</dc:creator>
            <media:content type="image/jpeg" medium="image" width="900" height="600"
                  url="https://www.yoursite.com/img/{{ .Params.img | safeHTML }}" />
            <description>{{chomp "<![CDATA[\n"}}{{ .Description | safeHTML }}{{chomp "]]>\n"}}</description>
            <content:encoded>{{chomp "<![CDATA[\n"}}{{ .Content | safeHTML }}{{chomp "]]>\n"}}</content:encoded>
            </item>
        {{ end }}
        {{ end }}
    </channel>
</rss>

Hope that gets you on track!

2 Likes

@Rick - that is super helpful!

Some Follow up Questions
[1] I see you have a large or full size width and height - do you know whether all feed readers / consumers generally auto-resize? Or does it make sense to hard code a smaller dimension for some that might not resize?

[2] Do I need chomp, or can I just use the existing description tag and skip the content:encoded tag?

[3] Is chomp part of Hugo already?

[4] hugo seems to kick the error ““Debugging”: template: rss.xml:23:74: executing “rss.xml” at : wrong number of args for safeHTML: want 1 got 0”

[5] I have seen some recommendations do to it like the below - should I include both?

<image><title>{{ with .Title }}{{.}} on {{ end }}{{ .Site.Title }}</title>
<link>{{ .Permalink }}</link>  
<url>imageurl.gif</url></image>

No worries!

  1. I think the large size is just to accomodate users of feed readers like Flipboard (which display large images)
  2. Yes, I think you need chomp in this case, but try without locally
  3. Not heavily documented but I think so (perhaps one of the core contributors can answer this)
  4. Can you elaborate
  5. I would’n’t use title in this

Wow that was quick.

number 4 is when rendering tags. Should not have picked the debugging tag. It shows in the output of “hugo server”, here is a better example - the tag in this case is “Puppet”

ERROR 2017/04/19 08:42:37 Error while rendering "Puppet": template: rss.xml:23:74: executing "rss.xml" at <safeHTML>: wrong number of args for safeHTML: want 1 got 0

It does it for all tags.

I’m having a hard time getting the right format to pull the frontmatter field. Judging from the code I initially posted and the fact that the I updated @Rick’s suggestion to this:

<media:content type="image/png" medium="image" width="700" height="400"
      url="https://cloudywindows.com/{{ .Params.banner | safeHTML }}" /> 

But hugo rendering complains that safeHTML is not getting an argument. I also tried straight “.banner”

Front matter looks like this:

banner = "banners/windows-path.png"

Thanks for any suggestions on how to get this data into the RSS template.

@DarwinJS after upgrading to 0.20 where not even getting our RSS-feeds to work - I will have to get back to you

Ok so for anyone scratching their balls (pardon my french, a bit annoyed after some skull bashing here), this needs to be added to config for RSS feeds to work on corresponding types of pages in Hugo 0.20. Unfortunately my lazy ass didn’t read the output format guide closely enough.

[outputs]
home = [ "HTML", "RSS"]
section = [ "HTML", "RSS"]
taxonomy = [ "HTML", "RSS"]

Back to your question @DarwinJS:
I think you may have been looking at this a bit too long :wink: Notice that you have:

url="https://cloudywindows.com/banners/{{ .Params.banner | absURL }}" />

then you mention that you have banners/windows-path.png in frontmatter. If this is the case your code will try to find the image at https://cloudywindows.com/banners/banners/windows-path.png – should it really be /banners/banners (twice) in the path?

(If my assumption is correct and it still breaks there, use safeHTML instead of absURL)

@Rick - yes I did notice that and corrected it in my actual code since I made that post. But doesn’t help with the fact that “.Pararms.banner” seems to be empty in this context. Also absURL is wrong too and so went back to “safeHTML” as you suggested - but still errors out that it’s not getting params.

Hmm, are you sure that’s where it breaks? Do you have a link to the feed?

I didn’t push it public because it breaks the feed.

Is the terminal telling you the error is on that row? I don’t think the code should break just because the image isn’t found, my bet is that it’s something else.

@Rick - your bet was right. I had accidentally inserted a second end of item tag </item>

I also found I had to include logic to not include the image if the post does not have one - I forgot that the RSS processing touches pages and other things that are not in the posts portion of my site where everything has a banner.

Final code which works (and avoids chomp by using regular hugo references is):

Rss opening tag (as you suggested):

<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1" xmlns:content="http://purl.org/rss/1.0/modules/content" xmlns:media="http://search.yahoo.com/mrss/">

Right before close item tag:
{{ if and (isset .Params "banner") (not (eq .Params.banner "")) }} <media:content type="image/png" medium="image" width="700" height="400" url="https://cloudywindows.com/{{ .Params.banner | safeHTML }}" /> {{ end }}

The only challenge / question I have now is that some of my images are jpg and some are png - the above code hard codes to png for the content type.

My questions (in order of preferred implementation):

  1. Can I leave “content type” out?
  2. Is there a content type reference that would cover both jpg and png?
  3. How would I use the template language to strip the extension from “.Params.banner” and drop it in the content type ?

Found part of my answer here:

“Note also that a subtype specification is MANDATORY. There are no default subtypes.” => https://www.w3.org/Protocols/rfc1341/4_Content-Type.html

Also there is no “jpg” subtype - so I would probably rename my .jpg to .jpeg so that the logic could just be to pull the extension and drop it in as the subtype.

If that can’t be done I’ll just convert everthing to png and only use png in the future.

Where can I find documentation for what functions are available that are like “safeHTML” and “absURL” - and does anyone know if there is one for “file extension” or something that could trim the last part of the graphic file reference ?

@DarwinJS I’m happy it worked out :slightly_smiling:

Before you leave out the chomp, make sure your feed validates in https://validator.w3.org/feed/

Also, I’ve referenced this before, but it’s a great go to guide: https://about.flipboard.com/rss-spec/

The only quick solution to your remaining questions is to always write filetype in .Params.banner. BUT, from a speed perspective (not irrelevant for SEO, even if it’s not a major issue in RSS-feeds) you should always use .jpg as these are usually smaller in file size than .png

Take care!

My feed does not validate because it is served from CloudFront - a whole other story about how that validator is not being updated to keep up with technology. May address it at a later time.

I use png for transparency and most of my readers will be techs who probably have the bandwidth to take the small size difference.

Does anyone know if this is the reference of functions I can use in go lang field substitutions?

https://golang.org/pkg/strings/
Or this:
https://golang.org/pkg/text/template/