Skip to Content
DevelopmentAPIUtilities

Utilities

Comprehensive guide to validation, conversion, and feed manipulation utilities.

Validation Utilities

Validate feeds against format specifications to ensure compliance.

validateRSS2

Validate RSS 2.0 feeds:

import { validateRSS2 } from 'rss.today'; const result = validateRSS2(parsedFeed); console.log(`Valid: ${result.valid}`); console.log('Errors:', result.errors); console.log('Warnings:', result.warnings);

Validation checks:

  • Feed title is required
  • Feed description is required
  • Feed link is required and valid
  • Items have title or description
  • Item links are valid URLs
  • Enclosure URLs are valid
  • Enclosure type and length are present

Result Interface:

interface ValidationResult { valid: boolean; // true if no errors errors: string[]; // Critical issues warnings: string[]; // Minor issues }

validateAtom

Validate Atom 1.0 feeds:

import { validateAtom } from 'rss.today'; const result = validateAtom(parsedFeed); if (!result.valid) { console.error('Validation failed:', result.errors); } if (result.warnings.length > 0) { console.warn('Warnings:', result.warnings); }

Validation checks:

  • Feed title is required
  • Feed has link or feedUrl
  • Items have title
  • Item links are valid URLs
  • Items have ID
  • Items have published date

validateJSONFeed

Validate JSON Feed 1.0:

import { validateJSONFeed } from 'rss.today'; const result = validateJSONFeed(jsonFeed); if (result.valid) { console.log('Valid JSON Feed'); }

Validation checks:

  • Version includes jsonfeed.org/version/
  • Title is present
  • Items have ID
  • Items have URL or content

Conversion Utilities

Convert feeds between different formats.

convertToRSS2

Convert any parsed feed to RSS 2.0:

import { Parser, convertToRSS2 } from 'rss.today'; const parser = new Parser(); // Convert Atom to RSS 2.0 const atomFeed = await parser.parseURL('https://example.com/atom.xml'); const rss2Xml = convertToRSS2(atomFeed); console.log(rss2Xml); // Convert JSON Feed to RSS 2.0 const jsonFeed = await parser.parseJSON(jsonString); const rss2Xml = convertToRSS2(jsonFeed);

convertToAtom

Convert any parsed feed to Atom 1.0:

import { Parser, convertToAtom } from 'rss.today'; const parser = new Parser(); // Convert RSS 2.0 to Atom const rssFeed = await parser.parseURL('https://example.com/rss.xml'); const atomXml = convertToAtom(rssFeed); console.log(atomXml);

convertToJSON

Convert any parsed feed to JSON Feed 1.0:

import { Parser, convertToJSON } from 'rss.today'; const parser = new Parser(); // Convert RSS 2.0 to JSON Feed const rssFeed = await parser.parseURL('https://example.com/rss.xml'); const jsonFeed = convertToJSON(rssFeed); console.log(jsonFeed); // Parse as JSON const feedData = JSON.parse(jsonFeed); console.log(feedData.title);

Feed Utilities

mergeFeeds

Combine multiple feeds into one, automatically removing duplicates:

import { Parser, mergeFeeds } from 'rss.today'; const parser = new Parser(); const feeds = await Promise.all([ parser.parseURL('https://example.com/feed1.xml'), parser.parseURL('https://example.com/feed2.xml'), parser.parseURL('https://example.com/feed3.xml') ]); const merged = mergeFeeds(feeds); console.log(`Merged ${merged.items.length} items`); console.log(`Title: ${merged.title}`);

Duplicate detection:

  • Uses GUID if present
  • Falls back to item link
  • Keeps first occurrence

diffFeeds

Compare two feeds to find differences:

import { Parser, diffFeeds } from 'rss.today'; const parser = new Parser(); const oldFeed = await parser.parseFile('./old-feed.xml'); const newFeed = await parser.parseFile('./new-feed.xml'); const diff = diffFeeds(oldFeed, newFeed); console.log(`Added: ${diff.added.length} items`); console.log(`Removed: ${diff.removed.length} items`); console.log(`Modified: ${diff.modified.length} items`); console.log(`Unchanged: ${diff.unchanged.length} items`); // Show new items diff.added.forEach(item => { console.log(`New: ${item.title} - ${item.link}`); });

FeedDiffResult Interface:

interface FeedDiffResult { added: ParsedItem[]; // Items in new feed only removed: ParsedItem[]; // Items in old feed only modified: ParsedItem[]; // Items that changed unchanged: ParsedItem[]; // Items that stayed the same }

filterFeed

Filter feed items using a custom predicate:

import { filterFeed } from 'rss.today'; const filtered = filterFeed(feed, (item, index) => { // Only include items with specific keywords in title return item.title?.toLowerCase().includes('typescript'); }); // Or with more complex logic const filtered = filterFeed(feed, (item, index) => { const hasContent = item.content && item.content.length > 100; const isRecent = item.pubDate && new Date(item.pubDate) > new Date('2024-01-01'); return hasContent && isRecent; });

filterByCategory

Filter items by category:

import { filterByCategory } from 'rss.today'; const techFeed = filterByCategory(feed, 'technology'); const jsFeed = filterByCategory(feed, 'javascript');

Category matching:

  • Matches category name exactly
  • Works with both string and object categories
  • Case-sensitive matching

filterByAuthor

Filter items by author:

import { filterByAuthor } from 'rss.today'; const authorFeed = filterByAuthor(feed, 'John Doe'); console.log(`Found ${authorFeed.items.length} items by John Doe`);

filterByDateRange

Filter items by date range:

import { filterByDateRange } from 'rss.today'; const startDate = new Date('2024-01-01'); const endDate = new Date('2024-01-31'); const januaryFeed = filterByDateRange(feed, startDate, endDate); // Only start date const recentFeed = filterByDateRange(feed, startDate);

sortFeed

Sort feed items using a custom comparator:

import { sortFeed } from 'rss.today'; const sorted = sortFeed(feed, (a, b) => { // Sort by custom criteria const lengthA = a.title?.length || 0; const lengthB = b.title?.length || 0; return lengthA - lengthB; });

sortByDate

Sort feed items by date:

import { sortByDate } from 'rss.today'; // Newest first (default) const newestFirst = sortByDate(feed, 'desc'); // Oldest first const oldestFirst = sortByDate(feed, 'asc');

sortByTitle

Sort feed items by title:

import { sortByTitle } from 'rss.today'; // Alphabetical (default) const alphabetical = sortByTitle(feed, 'asc'); // Reverse alphabetical const reverseAlphabetical = sortByTitle(feed, 'desc');

limitFeed

Limit feed to a specific number of items:

import { limitFeed } from 'rss.today'; const latest5 = limitFeed(feed, 5); const latest10 = limitFeed(feed, 10);

Best practice: Sort before limiting:

import { sortByDate, limitFeed } from 'rss.today'; const latest10 = limitFeed(sortByDate(feed, 'desc'), 10);

deduplicateFeed

Remove duplicate items from a feed:

import { deduplicateFeed } from 'rss.today'; const unique = deduplicateFeed(feed); console.log(`Removed duplicates: ${feed.items.length - unique.items.length}`);

Duplicate detection:

  • Uses GUID if present
  • Falls back to item link
  • Keeps first occurrence

Complete Examples

Feed Validation Workflow

import { Parser, validateRSS2 } from 'rss.today'; async function validateAndParse(url: string) { const parser = new Parser(); try { const feed = await parser.parseURL(url); // Validate RSS 2.0 const validation = validateRSS2(feed); if (!validation.valid) { console.error('Validation failed:'); validation.errors.forEach(error => console.error(` - ${error}`)); } if (validation.warnings.length > 0) { console.warn('Warnings:'); validation.warnings.forEach(warning => console.warn(` - ${warning}`)); } if (validation.valid) { console.log('Feed is valid RSS 2.0'); console.log(`Title: ${feed.title}`); console.log(`Items: ${feed.items.length}`); } return feed; } catch (error) { console.error('Error:', error.message); throw error; } }

Feed Aggregation

import { Parser, mergeFeeds, sortByDate, limitFeed } from 'rss.today'; async function aggregateFeeds(feedUrls: string[], limit: number = 20) { const parser = new Parser(); // Fetch all feeds const feeds = await Promise.all( feedUrls.map(url => parser.parseURL(url)) ); // Merge feeds const merged = mergeFeeds(feeds); // Sort by date (newest first) const sorted = sortByDate(merged, 'desc'); // Limit results const final = limitFeed(sorted, limit); console.log(`Aggregated ${limit} items from ${feedUrls.length} feeds`); return final; } aggregateFeeds([ 'https://example.com/feed1.xml', 'https://example.com/feed2.xml', 'https://example.com/feed3.xml' ], 10);

Feed Monitoring

import { Parser, diffFeeds } from 'rss.today'; import * as fs from 'fs/promises'; async function monitorFeed(url: string) { const parser = new Parser(); // Load previous state let oldFeed = null; try { const saved = await fs.readFile('./feed-state.json', 'utf-8'); oldFeed = JSON.parse(saved); } catch { console.log('No previous state found'); } // Fetch current feed const newFeed = await parser.parseURL(url); if (oldFeed) { // Compare feeds const diff = diffFeeds(oldFeed, newFeed); if (diff.added.length > 0) { console.log(`New items: ${diff.added.length}`); diff.added.forEach(item => { console.log(` + ${item.title}`); }); } if (diff.removed.length > 0) { console.log(`Removed items: ${diff.removed.length}`); } } // Save current state await fs.writeFile('./feed-state.json', JSON.stringify(newFeed, null, 2)); } monitorFeed('https://example.com/feed.xml');

Format Conversion

import { Parser, convertToRSS2, convertToAtom, convertToJSON } from 'rss.today'; import * as fs from 'fs/promises'; async function convertFeedFormats(sourceUrl: string) { const parser = new Parser(); const feed = await parser.parseURL(sourceUrl); // Convert to all formats const rss2 = convertToRSS2(feed); const atom = convertToAtom(feed); const json = convertToJSON(feed); // Save all formats await fs.writeFile('./output/feed.rss.xml', rss2); await fs.writeFile('./output/feed.atom.xml', atom); await fs.writeFile('./output/feed.json', json); console.log('Converted to all formats'); console.log(' - RSS 2.0: feed.rss.xml'); console.log(' - Atom 1.0: feed.atom.xml'); console.log(' - JSON Feed: feed.json'); } convertFeedFormats('https://example.com/feed.xml');

Advanced Filtering

import { Parser, filterByCategory, filterByDateRange, sortByDate, limitFeed } from 'rss.today'; async function getRecentTechPosts(url: string, days: number = 7) { const parser = new Parser(); const feed = await parser.parseURL(url); // Filter by category const techFeed = filterByCategory(feed, 'technology'); // Filter by date range (last N days) const startDate = new Date(); startDate.setDate(startDate.getDate() - days); const recentFeed = filterByDateRange(techFeed, startDate); // Sort by date const sorted = sortByDate(recentFeed, 'desc'); // Limit results const results = limitFeed(sorted, 10); console.log(`Found ${results.items.length} tech posts from last ${days} days`); return results; } getRecentTechPosts('https://example.com/feed.xml', 7);
Last updated on