( publication: any, posts: any[], currentCursor: string | null, nextCursor: string | null, )
| 3 | const NON_ASCII_REGEX = /[\u{0080}-\u{FFFF}]/gu; |
| 4 | |
| 5 | export const constructRSSFeedFromPosts = ( |
| 6 | publication: any, |
| 7 | posts: any[], |
| 8 | currentCursor: string | null, |
| 9 | nextCursor: string | null, |
| 10 | ) => { |
| 11 | const baseUrl = publication.url; |
| 12 | |
| 13 | const customElements = [ |
| 14 | { |
| 15 | 'atom:link': { |
| 16 | _attr: { |
| 17 | rel: 'first', |
| 18 | href: `${baseUrl}/rss.xml`, |
| 19 | }, |
| 20 | }, |
| 21 | }, |
| 22 | ]; |
| 23 | if (nextCursor) { |
| 24 | customElements.push({ |
| 25 | 'atom:link': { |
| 26 | _attr: { |
| 27 | rel: 'next', |
| 28 | href: `${baseUrl}/rss.xml${nextCursor ? `?after=${nextCursor}` : ''}`, |
| 29 | }, |
| 30 | }, |
| 31 | }); |
| 32 | } |
| 33 | |
| 34 | const feedConfig = { |
| 35 | title: `${publication.title || `${publication.author!.name}'s blog`}`, |
| 36 | description: publication.about?.html, |
| 37 | feed_url: `${baseUrl}/rss.xml${currentCursor ? `?after=${currentCursor}` : ''}`, |
| 38 | site_url: baseUrl, |
| 39 | image_url: publication.preferences!.logo, |
| 40 | language: 'en', |
| 41 | ttl: 60, |
| 42 | custom_elements: customElements, |
| 43 | }; |
| 44 | |
| 45 | const feed = new RSS(feedConfig); |
| 46 | |
| 47 | posts.forEach((post) => { |
| 48 | feed.item({ |
| 49 | title: post.title, |
| 50 | description: post.content!.html!.replace(NON_ASCII_REGEX, ''), |
| 51 | url: `${baseUrl}/${post.slug}`, |
| 52 | categories: post.tags!.map((tag: any) => tag.name), |
| 53 | author: post.author!.name, |
| 54 | date: post.publishedAt, |
| 55 | ...(post.coverImage && { custom_elements: [{ cover_image: post.coverImage }] }), |
| 56 | }); |
| 57 | }); |
| 58 | |
| 59 | const xml = feed.xml(); |
| 60 | return xml; |
| 61 | }; |
no outgoing calls
no test coverage detected