mirror of
https://github.com/juherr/kill-the-news.git
synced 2026-06-20 22:03:48 +00:00
fix(feed): add Atom link in emails page, fix HTML stripping, use request URL for self-link
- Add Atom Feed URL to the Feed Details card in the emails page - Fix extractBodyContent to handle emails without a closing </body> tag (regex now falls back to capturing everything after the opening <body>) - Use the actual request URL origin for atom:link rel="self" in RSS/Atom feeds, guaranteeing it always matches the document location regardless of how DOMAIN is configured Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -93,7 +93,7 @@ emailsRouter.get("/feeds/:feedId/emails", async (c) => {
|
||||
|
||||
const emailAddress = `${feedId}@${env.DOMAIN}`;
|
||||
const rssUrl = `https://${env.DOMAIN}/rss/${feedId}`;
|
||||
|
||||
const atomUrl = `https://${env.DOMAIN}/atom/${feedId}`;
|
||||
|
||||
return c.html(
|
||||
<Layout title={`${feedConfig.title} - Emails`}>
|
||||
@@ -114,6 +114,7 @@ emailsRouter.get("/feeds/:feedId/emails", async (c) => {
|
||||
<div>
|
||||
<CopyField label="Email Address:" value={emailAddress} />
|
||||
<CopyField label="RSS Feed:" value={rssUrl} />
|
||||
<CopyField label="Atom Feed:" value={atomUrl} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -16,11 +16,13 @@ export async function handle(c: Context<{ Bindings: Env }>): Promise<Response> {
|
||||
}
|
||||
|
||||
const baseUrl = `https://${c.env.DOMAIN}`;
|
||||
const selfUrl = new URL(c.req.url).origin + `/atom/${feedId}`;
|
||||
const atomXml = generateAtomFeed(
|
||||
feedData.feedConfig,
|
||||
feedData.emails,
|
||||
baseUrl,
|
||||
feedId,
|
||||
selfUrl,
|
||||
);
|
||||
const linkHeader = [
|
||||
`<${baseUrl}/hub>; rel="hub"`,
|
||||
|
||||
@@ -16,11 +16,13 @@ export async function handle(c: Context<{ Bindings: Env }>): Promise<Response> {
|
||||
}
|
||||
|
||||
const baseUrl = `https://${c.env.DOMAIN}`;
|
||||
const selfUrl = new URL(c.req.url).origin + `/rss/${feedId}`;
|
||||
const rssXml = generateRssFeed(
|
||||
feedData.feedConfig,
|
||||
feedData.emails,
|
||||
baseUrl,
|
||||
feedId,
|
||||
selfUrl,
|
||||
);
|
||||
const linkHeader = [
|
||||
`<${baseUrl}/hub>; rel="hub"`,
|
||||
|
||||
@@ -16,8 +16,12 @@ function parseFromAddress(from: string): { name: string; email?: string } {
|
||||
// Email content is stored as a full HTML document. Feed readers expect only
|
||||
// the body fragment in <description>/<content:encoded>, not a full document.
|
||||
export function extractBodyContent(html: string): string {
|
||||
const match = html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
|
||||
return match ? match[1] : html;
|
||||
const withClose = html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
|
||||
if (withClose) return withClose[1];
|
||||
// Some HTML emails omit </body>; capture everything after the opening tag
|
||||
const withoutClose = html.match(/<body[^>]*>([\s\S]*)/i);
|
||||
if (withoutClose) return withoutClose[1].replace(/<\/html>\s*$/i, "");
|
||||
return html;
|
||||
}
|
||||
|
||||
function buildFeed(
|
||||
@@ -25,6 +29,7 @@ function buildFeed(
|
||||
emails: EmailData[],
|
||||
baseUrl: string,
|
||||
feedId: string,
|
||||
selfUrl?: { rss?: string; atom?: string },
|
||||
): Feed {
|
||||
const feed = new Feed({
|
||||
title: feedConfig.title,
|
||||
@@ -39,8 +44,8 @@ function buildFeed(
|
||||
generator: "kill-the-news",
|
||||
copyright: `Copyright © ${new Date().getFullYear()} ${feedConfig.title}`,
|
||||
feedLinks: {
|
||||
rss: `${baseUrl}/rss/${feedId}`,
|
||||
atom: `${baseUrl}/atom/${feedId}`,
|
||||
rss: selfUrl?.rss ?? `${baseUrl}/rss/${feedId}`,
|
||||
atom: selfUrl?.atom ?? `${baseUrl}/atom/${feedId}`,
|
||||
},
|
||||
author: feedConfig.author
|
||||
? {
|
||||
@@ -80,8 +85,15 @@ export function generateRssFeed(
|
||||
emails: EmailData[],
|
||||
baseUrl: string,
|
||||
feedId: string,
|
||||
selfUrl?: string,
|
||||
): string {
|
||||
return buildFeed(feedConfig, emails, baseUrl, feedId).rss2();
|
||||
return buildFeed(
|
||||
feedConfig,
|
||||
emails,
|
||||
baseUrl,
|
||||
feedId,
|
||||
selfUrl ? { rss: selfUrl } : undefined,
|
||||
).rss2();
|
||||
}
|
||||
|
||||
export function generateAtomFeed(
|
||||
@@ -89,6 +101,13 @@ export function generateAtomFeed(
|
||||
emails: EmailData[],
|
||||
baseUrl: string,
|
||||
feedId: string,
|
||||
selfUrl?: string,
|
||||
): string {
|
||||
return buildFeed(feedConfig, emails, baseUrl, feedId).atom1();
|
||||
return buildFeed(
|
||||
feedConfig,
|
||||
emails,
|
||||
baseUrl,
|
||||
feedId,
|
||||
selfUrl ? { atom: selfUrl } : undefined,
|
||||
).atom1();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user