javascriptrssatom-feedeleventy

Get file length for rss.xml enclosure tag in Eleventy


I have the following RSS feed in Eleventy v3.1.1. I wish to add the tag so I can include the featured image in the feed. The tag requires the length of the file in bytes. There are numerous ways to parse a file's length, but how can I include it in the XML? I assume I'll have to create some sort of filter in eleventy.js. but I have no idea where to start.

--json
{
  "permalink": "rss.xml",
  "eleventyExcludeFromCollections": true,
  "metadata": {
    "title": "My Website",
    "description": "A neato description",
    "language": "en-US",
    "base": "https://my.site/",
    "author": {
      "name": "John Q. Smith"
    }
  }
}
---
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:base="{{ metadata.base | addPathPrefixToFullUrl }}" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title><![CDATA[{{ metadata.title }}]]></title>
    <link>{{ metadata.base | addPathPrefixToFullUrl }}</link>
    <atom:link href="{{ permalink | htmlBaseUrl(metadata.base) }}" rel="self" type="application/rss+xml" />
    <description><![CDATA[{{ metadata.description }}]]></description>
    <language>{{ metadata.language or page.lang }}</language>
    <category>Blog</category>
    <copyright>Copyright © 2012{{ helpers.currentYearRSS() | safe }} John Q. Smith. All rights reserved.</copyright>
    <image>
      <url>https://my.site/assets/images/site/logo.png</url>
      <title><![CDATA[{{ metadata.title }}]]></title>
      <link>{{ metadata.base | addPathPrefixToFullUrl }}</link>
      <description><![CDATA[{{ metadata.description }}]]></description>
      <width>144</width>
      <height>144</height>
    </image>
    {%- for post in collections.blog | sortByPubDate | reverse %}
    {%- set absolutePostUrl = post.url | htmlBaseUrl(metadata.base) %}
    <item>
      <title><![CDATA[{{ post.data.title }}]]></title>
      <link>{{ absolutePostUrl }}</link>
      <description><![CDATA[{{ post.data.excerpt }}]]></description>
      <pubDate>{{ post.data.pubdate | dateToRfc822 }}</pubDate>
      <lastBuildDate>{{ post.date | dateToRfc822 }}</lastBuildDate>
      <dc:creator>{{ metadata.author.name }}</dc:creator>
      <guid>{{ absolutePostUrl }}</guid>
      <enclosure url="https://my.site/{{ post.data.image }}"
    length="" type="image/jpeg" />
    </item>
    {%- endfor %}
  </channel>
</rss>

Solution

  • I figured it out. Here's the filter:

    module.exports = async function(eleventyConfig) {  
      // Convert length to bytes
      eleventyConfig.addAsyncFilter(`convertLengthToBytes`, async function (value) {
        const fileImg = await fetch(`https://my.site` + value).then(r => r.blob());
    
        return fileImg.size;
      });
    };
    

    Usage: `

    <enclosure url="https://my.site/{{ post.data.image }}"
        length="{{ post.data.image | convertLengthToBytes }}" type="image/jpeg" />
    

    `