Files
Tony f5dd404b1e perf(template): speed up atom & rss rendering (#23629)
* perf(template): speed up atom&rss rendering

* test: add regression test
2026-10-20 03:20:15 +08:00

59 lines
3.0 KiB
TypeScript

import { html } from 'hono/html';
import type { FC } from 'hono/jsx';
import type { Data } from '@/types';
import { getItemAttachments } from '@/utils/attachments';
const Link: FC<Record<string, string | number | undefined>> = (props) =>
html`<link${Object.entries(props)
.filter(([, value]) => value !== undefined)
.map(([name, value]) => html` ${name}="${value}"`)} />`;
const RSS: FC<{ data: Data }> = ({ data }) => (
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:rsshub="http://rsshub.app/xml/schemas" xml:lang={data.language || 'en'}>
{html`<title>${data.title || 'RSSHub'}</title>`}
<Link rel="alternate" href={data.link || 'https://docs.rsshub.app'} />
<Link rel="self" href={data.atomlink} type="application/atom+xml" />
<id>{data.id || data.link}</id>
<subtitle>{data.description || data.title} - Powered by RSSHub</subtitle>
<generator>RSSHub</generator>
<updated>{new Date(data.lastBuildDate || new Date()).toISOString()}</updated>
<author>
<name>{data.author || 'RSSHub'}</name>
</author>
{data.icon && <icon>{data.icon}</icon>}
{data.logo && <logo>{data.logo}</logo>}
{data.item?.map((item) => (
<entry>
{html`<title>${item.title}</title>`}
{item.description ? <content type="html">{item.description}</content> : item.content?.text ? <content type="text">{item.content.text}</content> : <content src={item.link} type="text/html" />}
<Link href={item.link} />
{getItemAttachments(item).map((attachment) => (
<Link rel="enclosure" href={attachment.url} type={attachment.mime_type} length={attachment.size_in_bytes} title={attachment.title} />
))}
<id>{item.guid || item.link || item.title}</id>
{item.pubDate && <published>{new Date(item.pubDate).toISOString()}</published>}
<updated>{new Date(item.updated || item.pubDate || new Date()).toISOString()}</updated>
{item.summary && <summary>{item.summary}</summary>}
{item.author && (
<author>
<name>{item.author}</name>
</author>
)}
{item.category !== undefined && (Array.isArray(item.category) ? item.category : [item.category]).map((c) => <category term={c}></category>)}
{item.media &&
Object.entries(item.media).map(([key, value]) => {
const Tag = `media:${key}`;
return <Tag {...value} />;
})}
{item.upvotes ? <rsshub:upvotes>{item.upvotes}</rsshub:upvotes> : ''}
{item.downvotes ? <rsshub:downvotes>{item.downvotes}</rsshub:downvotes> : ''}
{item.comments ? <rsshub:comments>{item.comments}</rsshub:comments> : ''}
</entry>
))}
</feed>
);
export default RSS;