-
Notifications
You must be signed in to change notification settings - Fork 4
feat: add RSS feeds #66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
WalkthroughThis change introduces RSS feed support for package releases. New server endpoints are added to serve package-specific RSS feeds in XML, Atom, and JSON formats. A utility function is implemented to generate feeds for either a single package or all packages. The UI for package pages is updated to include a collapsible RSS feed selector, allowing users to access the different feed formats. Supporting dependencies for feed generation and Markdown parsing are added. Additionally, a helper function is introduced to fetch and aggregate releases for all packages. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI (Package Page)
participant Server (SvelteKit)
participant RSS Handler
participant Feed Generator
participant Data Source
User->>UI (Package Page): Clicks RSS feed button
UI (Package Page)->>Server (SvelteKit): Requests /package/[...package]/rss.xml (or .json/.xml/.atom)
Server (SvelteKit)->>RSS Handler: Handles GET request
RSS Handler->>Feed Generator: Fetch package/all releases, build feed
Feed Generator->>Data Source: Retrieve release data
Data Source-->>Feed Generator: Return release info
Feed Generator-->>RSS Handler: Return feed object
RSS Handler-->>Server (SvelteKit): Format feed (XML/JSON/Atom)
Server (SvelteKit)-->>UI (Package Page): Respond with feed content
UI (Package Page)-->>User: Feed is available for subscription
Assessment against linked issues
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
src/routes/package/[...package]/+page.svelteOops! Something went wrong! :( ESLint: 9.25.1 Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@sveltejs/adapter-vercel' imported from /svelte.config.js src/lib/components/AnimatedCollapsibleContent.svelteOops! Something went wrong! :( ESLint: 9.25.1 Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@sveltejs/adapter-vercel' imported from /svelte.config.js src/routes/package/[...package]/atom.xml/+server.tsOops! Something went wrong! :( ESLint: 9.25.1 Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@sveltejs/adapter-vercel' imported from /svelte.config.js
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
marked is always there when I need it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (5)
src/lib/components/AnimatedCollapsibleContent.svelte (1)
1-32: Clean implementation of animated collapsible content.This component effectively extends the bits-ui Collapsible.Content with smooth slide transitions and follows Svelte 5 patterns correctly.
Consider making the flex class configurable to increase component flexibility:
- <div {...props} transition:slide={{ duration, axis }} class="flex"> + <div {...props} transition:slide={{ duration, axis }} class={`flex ${$$props.class || ''}`}>Also, note that using
forceMountalways keeps the content in the DOM, which might impact performance for complex content. This is typically a reasonable tradeoff for smoother animations, but worth being aware of for future reference.src/routes/package/[...package]/atom.xml/+server.ts (1)
1-11: Consider using more specific content type for Atom feeds.The implementation is clean and consistent with other feed endpoints.
For Atom feeds, the more specific MIME type
application/atom+xmlis widely recognized and preferred over genericapplication/xml:text(feed.atom1(), { headers: { "Cache-Control": "max-age=0, s-max-age=600", - "Content-Type": "application/xml" + "Content-Type": "application/atom+xml" } })src/routes/package/[...package]/+page.svelte (1)
71-112: UI improvements look good, but check URL concatenationThe RSS feed selector UI is well-implemented with proper accessibility considerations and animations. However, there's a potential issue with the URL construction that could lead to malformed URLs.
The URL construction on line 105 might result in double slashes if the page URL already ends with a slash. Consider using a more robust URL joining approach:
- href="{page.url}/{file}" + href="{page.url.endsWith('/') ? page.url + file : `${page.url}/${file}`}"src/routes/package/[...package]/rss.ts (2)
14-35: The base feed configuration looks good, but URL handling could be improvedThe
getBaseFeedfunction sets up a well-structured feed with all the necessary metadata. However, the URL manipulation for feed links is using regex replacement which might be fragile.Consider using URL manipulation methods instead of regex for more robust URL handling:
- xml: url.toString().replace(/[A-z\d]+\.[A-z\d]+$/, "rss.xml"), - json: url.toString().replace(/[A-z\d]+\.[A-z\d]+$/, "rss.json"), - atom: url.toString().replace(/[A-z\d]+\.[A-z\d]+$/, "atom.xml") + xml: new URL("rss.xml", url.origin + url.pathname.replace(/[^/]+$/, "")).toString(), + json: new URL("rss.json", url.origin + url.pathname.replace(/[^/]+$/, "")).toString(), + atom: new URL("atom.xml", url.origin + url.pathname.replace(/[^/]+$/, "")).toString()
42-46: Consider sanitization for Markdown contentWhile GitHub content might be trusted, it's generally a good practice to sanitize HTML output from markdown converters.
Even though you're handling GitHub content which is likely safe, it might be worth adding sanitization for extra security. The marked library has sanitization options that can be enabled.
- // we'll assume GH content doesn't need to be sanitized *wink wink* - return marked(md) as string; // can only be a Promise if the `async` option is set to true, not the case here + // Enable sanitization for extra security + return marked(md, { sanitize: true }) as string; // can only be a Promise if the `async` option is set to true, not the case hereOr consider using DOMPurify as an additional layer:
import DOMPurify from 'dompurify'; // ... return DOMPurify.sanitize(marked(md) as string);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yamlsrc/lib/components/ui/collapsible/index.tsis excluded by!src/lib/components/ui/**
📒 Files selected for processing (8)
package.json(3 hunks)src/lib/components/AnimatedCollapsibleContent.svelte(1 hunks)src/routes/package/[...package]/+page.svelte(2 hunks)src/routes/package/[...package]/atom.xml/+server.ts(1 hunks)src/routes/package/[...package]/rss.json/+server.ts(1 hunks)src/routes/package/[...package]/rss.ts(1 hunks)src/routes/package/[...package]/rss.xml/+server.ts(1 hunks)src/routes/package/releases.ts(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: WarningImHack3r
PR: WarningImHack3r/svelte-changelog#56
File: src/routes/package/+layout.server.ts:28-40
Timestamp: 2025-04-25T10:58:24.062Z
Learning: WarningImHack3r prefers elegant, aesthetically pleasing solutions for performance optimizations rather than quick fixes that introduce nested async IIFEs or similar approaches that might make code harder to read.
Learnt from: WarningImHack3r
PR: WarningImHack3r/svelte-changelog#48
File: src/routes/package/[...package]/+page.server.ts:50-53
Timestamp: 2025-04-11T10:33:07.002Z
Learning: WarningImHack3r prefers to keep server-side console.log statements in the codebase as they find them useful for debugging and monitoring, even if they might clean them up later.
🧬 Code Graph Analysis (3)
src/routes/package/[...package]/atom.xml/+server.ts (3)
src/routes/package/[...package]/rss.json/+server.ts (1)
GET(4-11)src/routes/package/[...package]/rss.xml/+server.ts (1)
GET(4-11)src/routes/package/[...package]/rss.ts (1)
rssHandler(53-106)
src/routes/package/[...package]/rss.json/+server.ts (1)
src/routes/package/[...package]/rss.ts (1)
rssHandler(53-106)
src/routes/package/releases.ts (1)
src/lib/server/package-discoverer.ts (1)
discoverer(150-150)
🔇 Additional comments (4)
package.json (1)
31-31: LGTM: TailwindCSS dependencies updated.The minor version updates to TailwindCSS dependencies are appropriate.
Also applies to: 63-63
src/routes/package/[...package]/rss.json/+server.ts (1)
1-11: Looks good - JSON feed implementation is clean and conciseThe JSON feed implementation follows SvelteKit's conventions, reuses the shared
rssHandler, and sets appropriate headers for content type and caching strategy.src/routes/package/[...package]/rss.xml/+server.ts (1)
1-11: Looks good - XML feed implementation is clean and conciseThe XML feed implementation follows SvelteKit's conventions, reuses the shared
rssHandler, and sets appropriate headers for content type and caching strategy.src/routes/package/[...package]/rss.ts (1)
53-106:✅ Verification successful
RSS handler implementation is solid with good error handling
The
rssHandlerfunction is well-implemented with proper error handling, support for both single package and all packages, and comprehensive feed generation. It also aligns with your preference for clean, readable code as seen in previous PRs.
🏁 Script executed:
#!/bin/bash # Verify consistent case-handling for package slugs # Check if there are other places in the codebase where slugs are compared rg -C 3 "package(Name|Slug)\.toLowerCase\(\)"Length of output: 503
Approve: RSS handler is solid and slug case-handling is consistent
I’ve verified that the only case-insensitive comparison (
slugPackage.toLowerCase() === "all") is correctly scoped to this handler and there are no other slug or package-name comparisons elsewhere in the codebase. The implementation is clean, has proper error handling, and generates the feed as expected. Great work!
Fixes #57
Quite self-explanatory: add RSS feeds for each package and all packages at once.
All feeds are available as RSS 2 (
/rss.xml), ATOM (/atom.xml), and JSON Feed (/rss.json). As described, they're accessible by appending the appropriate suffix to their regular URL (e.g.,/package/svelte/rss.xml).Similarly, RSS feeds for all the packages are available under
/package/all/rss.xmland equivalents.Roadmap
References
Summary by CodeRabbit
New Features
Chores