Create a generic solution for parsing links

This commit is contained in:
Berry de Vos 2023-05-12 15:36:13 +02:00
parent 6ed35ecaac
commit ff968983ff
3 changed files with 37 additions and 13 deletions

View file

@ -7,6 +7,7 @@ import { Output } from 'rss-parser'
import { CustomItem } from '../parseFeeds'
import { formatDate } from '../utils/formatter'
import Summary from './Summary'
import { parseLinks } from './parseLinks'
interface Props {
feed: Output<CustomItem>
@ -21,15 +22,19 @@ export default ({ feed, hasBottomSeparator }: Props) => {
{feed.title}
</Link>
</Text>
{feed.items.map((item) => (
<Container key={item.guid} style={section}>
<Link style={anchor} href={item.link}>
{item.title}
</Link>
{item.pubDate && <Text style={date}>{formatDate(item.pubDate)}</Text>}
{item.content && <Summary href={item.link} paragraphStyle={paragraph} blockquoteStyle={{ ...paragraph, ...blockquote }} content={item.content} />}
</Container>
))}
{feed.items.map((item) => {
const href = parseLinks(item.links)
return (
<Container key={item.guid} style={section}>
<Link style={anchor} href={href}>
{item.title}
</Link>
{item.pubDate && <Text style={date}>{formatDate(item.pubDate)}</Text>}
{item.content && <Summary href={href} paragraphStyle={paragraph} blockquoteStyle={{ ...paragraph, ...blockquote }} content={item.content} />}
</Container>
)
})}
{hasBottomSeparator && (
<Section>
<Hr style={hr} />

View file

@ -3,15 +3,14 @@ import { Img } from '@react-email/img'
import { Link } from '@react-email/link'
import { Text } from '@react-email/text'
import { Output } from 'rss-parser'
import { CustomItem, ItemLink } from '../../parseFeeds'
import { CustomItem } from '../../parseFeeds'
import Summary from './Summary'
import { parseLinks } from '../parseLinks'
interface Props {
feed: Output<CustomItem>
}
const findRelatedLink = (links: ItemLink[]) => links.map(({ $: link }) => link).find(({ rel }) => rel === 'related')?.href
export default ({ feed }: Props) => {
return (
<Container style={box}>
@ -19,7 +18,7 @@ export default ({ feed }: Props) => {
<Img src="https://daringfireball.net/graphics/logos/" style={logo} />
</Link>
{feed.items.map((item) => {
const href = findRelatedLink(item.links) ?? item.link
const href = parseLinks(item.links)
return (
<Container key={item.guid ?? item.id} style={section}>
<Text style={title}>

20
src/email/parseLinks.ts Normal file
View file

@ -0,0 +1,20 @@
import { ItemLink } from '../parseFeeds'
type Rel = 'alternate' | 'related'
const hrefByRel = (links: ItemLink[], rel: Rel) => links.map(({ $: link }) => link).find((link) => link.rel === rel)?.href
export const parseLinks = (links: ItemLink[]) => {
if (links.length === 0) {
throw new Error('Empty links array cannot be parsed')
}
const validLinks = links.filter((link) => link.$)
if (validLinks.length === 0) {
// The RSS parsers result is weird, when the links are just a string we can use the first without parsing
return `${links[0]}`
}
return hrefByRel(links, 'related') ?? hrefByRel(links, 'alternate') ?? links[0].$.href
}