@ykocaman/astro-medium-loader
Version:
Astro plugin to fetch Medium feeds by username
62 lines (61 loc) • 2.56 kB
JavaScript
import Parser from 'rss-parser';
import { fromStorage, toStorage } from './storage.js';
export async function getMediumPosts({ username, storage = { enabled: false, path: '.' } }) {
const STORAGE_FILE = `${storage.path}/${username}.json`;
let posts = [];
if (storage.enabled) {
console.log('Checking storage for Medium posts:', STORAGE_FILE);
posts = fromStorage(STORAGE_FILE);
if (posts.length > 0) {
return posts;
}
}
posts = await fetchMediumPosts(username);
// save storage for future use
if (storage.enabled) {
toStorage(STORAGE_FILE, posts);
}
return posts;
}
async function fetchMediumPosts(username) {
const url = `https://medium.com/feed/@${username}`;
const parser = new Parser();
console.log('Parsing Medium RSS feed from', url);
let feed;
try {
feed = await parser.parseURL(url);
}
catch (err) {
throw new Error(`Failed to parse Medium RSS feed for @${username}: ${err instanceof Error ? err.message : String(err)}`);
}
return (feed.items).map((item) => {
let slug = item.title?.toLocaleLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '') || item.link?.split('/').pop() || '';
let heroImage;
if (item['content:encoded']) {
const match = item['content:encoded'].match(/<img[^>]+src=["']([^"'>]+)["']/i);
if (match)
heroImage = match[1];
}
let description = '';
if (item['content:encodedSnippet']) {
const words = item['content:encodedSnippet'].match(/\S+/g) || [];
description = words.slice(0, 32).join(' ') + (words.length > 32 ? '...' : '');
}
let content = item['content:encoded'] || '';
// Remove <p>was originally published in ...</p> if present, because we will add a canonical link to the original post
content = content.replace(/<hr><p>[\s\S]*?was originally published in[\s\S]*?<\/p>/i, '');
let canonical = `<hr><p>Read the original post on: <a href="${item.link}" rel="canonical" target="_blank">${item.title}</a></p>`;
return {
title: item.title || '',
link: item.link || '',
pubDate: item.pubDate ? new Date(item.pubDate) : new Date(0),
isoDate: item.isoDate ? new Date(item.isoDate) : new Date(0),
categories: item.categories || [],
description,
content,
canonical,
heroImage,
slug
};
});
}