Add built-in RSS feed support#29
Conversation
There was a problem hiding this comment.
Pull request overview
Adds first-class RSS support to mdorigin by introducing a built-in /feed.xml route (gated by siteUrl + RSS enablement), exposing RSS configuration in site config, and emitting RSS autodiscovery link tags in rendered HTML.
Changes:
- Add
/feed.xmlroute that generates an RSS 2.0 feed from dated post content (excluding pages and drafts whendraftMode: 'exclude'). - Add
rssconfiguration (rss: falseto disable; overrides for title/description/author/maxItems) and corresponding normalization + tests. - Emit RSS autodiscovery
<link rel="alternate" type="application/rss+xml" ...>in HTML and document the new behavior.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/html/template.ts | Adds optional RSS autodiscovery <link> emission via rssFeedUrl. |
| src/core/site-config.ts | Introduces RSS config types and normalization into resolved site config. |
| src/core/site-config.test.ts | Adds coverage for RSS config normalization + disabling. |
| src/core/request-handler.ts | Adds /feed.xml route, feed item collection, and wiring RSS URL into HTML rendering. |
| src/core/request-handler.test.ts | Verifies feed output filtering and HTML autodiscovery link presence. |
| skills/mdorigin/SKILL.md | Updates skill description to mention /feed.xml support. |
| docs/site/reference/configuration.md | Documents RSS defaults, disable switch, and overrides. |
| docs/site/guides/getting-started.md | Adds getting-started guidance for /feed.xml and RSS config. |
| docs/site/concepts/routing.md | Documents routing for /feed.xml and autodiscovery behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const entries = await store.listDirectory(directoryPath); | ||
| if (entries === null) { | ||
| return []; | ||
| } | ||
|
|
||
| const feedItems: FeedItem[] = []; | ||
| const directoryShape = await inspectDirectoryShape(store, directoryPath); | ||
|
|
There was a problem hiding this comment.
collectRssFeedItems() calls store.listDirectory(directoryPath) and then immediately calls inspectDirectoryShape(store, directoryPath), which performs a second listDirectory() of the same directory. For large trees or remote-backed stores this doubles I/O per directory during feed generation. Consider deriving the DirectoryShape from the already-fetched entries (or adding an inspectDirectoryShapeFromEntries helper) so each directory is listed only once per traversal.
| function trimLeadingSlash(value: string): string { | ||
| return value.startsWith('/') ? value.slice(1) : value; | ||
| } | ||
|
|
||
| function ensureTrailingSlash(value: string): string { | ||
| return value.endsWith('/') ? value : `${value}/`; | ||
| } | ||
|
|
There was a problem hiding this comment.
trimLeadingSlash() and ensureTrailingSlash() are duplicated here but identical helpers already exist in src/search.ts. Duplicating URL-manipulation utilities increases the chance of subtle drift (e.g., around trailing slashes or edge cases) between search canonical URLs and feed URLs. Consider extracting these helpers into a shared utility module and importing them from both places.
| function trimLeadingSlash(value: string): string { | |
| return value.startsWith('/') ? value.slice(1) : value; | |
| } | |
| function ensureTrailingSlash(value: string): string { | |
| return value.endsWith('/') ? value : `${value}/`; | |
| } |
Summary
/feed.xmlsupport whensiteUrlis configuredrss: falseto disable itDetails
rss.title,rss.description,rss.author, andrss.maxItemsVerification
Closes #28