diff options
Diffstat (limited to 'packages/astro-rss/src')
-rw-r--r-- | packages/astro-rss/src/index.ts | 7 | ||||
-rw-r--r-- | packages/astro-rss/src/util.ts | 16 |
2 files changed, 19 insertions, 4 deletions
diff --git a/packages/astro-rss/src/index.ts b/packages/astro-rss/src/index.ts index 90c30eb0f..35bf5f613 100644 --- a/packages/astro-rss/src/index.ts +++ b/packages/astro-rss/src/index.ts @@ -29,6 +29,7 @@ export type RSSOptions = { customData?: z.infer<typeof rssOptionsValidator>['customData']; /** Whether to include drafts or not */ drafts?: z.infer<typeof rssOptionsValidator>['drafts']; + trailingSlash?: z.infer<typeof rssOptionsValidator>['trailingSlash']; }; type RSSFeedItem = { @@ -54,6 +55,7 @@ type GlobResult = z.infer<typeof globResultValidator>; const rssFeedItemValidator = rssSchema.extend({ link: z.string(), content: z.string().optional() }); const globResultValidator = z.record(z.function().returns(z.promise(z.any()))); + const rssOptionsValidator = z.object({ title: z.string(), description: z.string(), @@ -77,6 +79,7 @@ const rssOptionsValidator = z.object({ drafts: z.boolean().default(false), stylesheet: z.union([z.string(), z.boolean()]).optional(), customData: z.string().optional(), + trailingSlash: z.boolean().default(true), }); export default async function getRSS(rssOptions: RSSOptions) { @@ -171,7 +174,7 @@ async function generateRSS(rssOptions: ValidatedRSSOptions): Promise<string> { root.rss.channel = { title: rssOptions.title, description: rssOptions.description, - link: createCanonicalURL(site).href, + link: createCanonicalURL(site, rssOptions.trailingSlash, undefined).href, }; if (typeof rssOptions.customData === 'string') Object.assign( @@ -183,7 +186,7 @@ async function generateRSS(rssOptions: ValidatedRSSOptions): Promise<string> { // If the item's link is already a valid URL, don't mess with it. const itemLink = isValidURL(result.link) ? result.link - : createCanonicalURL(result.link, site).href; + : createCanonicalURL(result.link, rssOptions.trailingSlash, site).href; const item: any = { title: result.title, link: itemLink, diff --git a/packages/astro-rss/src/util.ts b/packages/astro-rss/src/util.ts index ad0e40a68..a87828bfc 100644 --- a/packages/astro-rss/src/util.ts +++ b/packages/astro-rss/src/util.ts @@ -1,10 +1,22 @@ import { z } from 'astro/zod'; +import { RSSOptions } from './index'; /** Normalize URL to its canonical form */ -export function createCanonicalURL(url: string, base?: string): URL { +export function createCanonicalURL( + url: string, + trailingSlash?: RSSOptions['trailingSlash'], + base?: string +): URL { let pathname = url.replace(/\/index.html$/, ''); // index.html is not canonical pathname = pathname.replace(/\/1\/?$/, ''); // neither is a trailing /1/ (impl. detail of collections) - if (!getUrlExtension(url)) pathname = pathname.replace(/(\/+)?$/, '/'); // add trailing slash if there’s no extension + if (trailingSlash === false) { + // remove the trailing slash + pathname = pathname.replace(/(\/+)?$/, ''); + } else if (!getUrlExtension(url)) { + // add trailing slash if there’s no extension or `trailingSlash` is true + pathname = pathname.replace(/(\/+)?$/, '/'); + } + pathname = pathname.replace(/\/+/g, '/'); // remove duplicate slashes (URL() won’t) return new URL(pathname, base); } |