feat: WebSub Atom support, HTML processing via linkedom, W3C badges

WebSub / PubSubHubbub:
- Hub now accepts both /rss/:id and /atom/:id topic URLs
- WebSubSubscription stores format ("rss" | "atom")
- notifySubscribers sends RSS or Atom XML with correct Content-Type
- verifyAndStoreSubscription sends correct topic URL per format
- CI paths-ignore docs/** to skip deploy on docs-only changes

HTML processing (linkedom + escape-html):
- New html-processor.ts: body extraction, script/iframe/object removal,
  event handler + javascript: URL stripping, mso-* style cleanup,
  plain text → <pre> with HTML escaping via escape-html
- feed-generator.ts and entries.ts use processEmailContent

Admin UI:
- W3C validation badges (Atom + RSS) on feed detail page

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Julien Herr
2026-05-22 21:12:10 +02:00
parent 1789870f27
commit a29e9ab372
13 changed files with 719 additions and 69 deletions
+24
View File
@@ -116,6 +116,30 @@ emailsRouter.get("/feeds/:feedId/emails", async (c) => {
<CopyField label="RSS Feed:" value={rssUrl} />
<CopyField label="Atom Feed:" value={atomUrl} />
</div>
<div class="feed-validate">
<a
href={`https://validator.w3.org/feed/check.cgi?url=${encodeURIComponent(atomUrl)}`}
target="_blank"
rel="noopener noreferrer"
>
<img
src="https://validator.w3.org/feed/images/valid-atom.png"
alt="[Valid Atom 1.0]"
title="Validate my Atom 1.0 feed"
/>
</a>
<a
href={`https://validator.w3.org/feed/check.cgi?url=${encodeURIComponent(rssUrl)}`}
target="_blank"
rel="noopener noreferrer"
>
<img
src="https://validator.w3.org/feed/images/valid-rss-rogers.png"
alt="[Valid RSS]"
title="Validate my RSS feed"
/>
</a>
</div>
</div>
<h2>