Generating absolute URLs in my RSS feed(s)
My RSS feeds are generated by 11ty at build time from a Liquid.js template. When I wrote posts and link elsewhere on my site I use a bookmarklet to capture the URI for linking. To ensure I have absolute URLs in my feeds, I use a filter to convert said URIs.
My 11ty filter looks like this:
import { JSDOM } from "jsdom";
export default {
convertRelativeLinks: (htmlContent, domain) => {
if (!htmlContent || !domain) return htmlContent;
const dom = new JSDOM(htmlContent);
const document = dom.window.document;
document.querySelectorAll("a[href]").forEach(link => {
let href = link.getAttribute("href");
if (href.startsWith("#")) {
link.remove();
return;
}
if (!href.startsWith("http://") && !href.startsWith("https://"))
link.setAttribute("href", `${domain.replace(/\/$/, '')}/${href.replace(/^\/+/, '')}`);
});
return document.body.innerHTML;
},
generatePermalink: (url, baseUrl) => {
if (url?.includes("http") || !baseUrl) return url
return `${baseUrl}${url}`
}
}
And it's used like this:
{{ feedItem.content | markdown | convertRelativeLinks: globals.url }}
I parse the feedItem.content
to markdown and call the filter while passing in the global base URL for my site.
The filter then takes the HTML content, passes it to new JSDOM(...)
, traverses the resulting document, strips link tags that contain #
, and combines the global URL with the relative link (by verifying that the href
contents contains neither http://
or https://
). When combining the link elements the filter also removes any trailing and leading slashes before returning the innerHTML
from the generated document.
Now, each feed contains only absolute URLs.