107 lines
3.8 KiB
JavaScript
107 lines
3.8 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
const path = require('path');
|
|
const fs = require('fs');
|
|
const { marked } = require('marked');
|
|
const fm = require('front-matter'); // For parsing front matter
|
|
const RSS = require('rss'); // Import RSS package
|
|
|
|
// Directory containing Markdown blog posts
|
|
const blogDirectory = path.join(__dirname, '../blog');
|
|
|
|
// Function to get all Markdown files in the blog directory
|
|
function getBlogPosts() {
|
|
const files = fs.readdirSync(blogDirectory);
|
|
return files.filter(file => file.endsWith('.md')).map(file => {
|
|
const content = fs.readFileSync(path.join(blogDirectory, file), 'utf-8');
|
|
|
|
// Parse front matter
|
|
const parsed = fm(content);
|
|
const { title, date, preview } = parsed.attributes; // Get title, date, and preview from front matter
|
|
|
|
// Remove Markdown formatting by converting to HTML and stripping the tags
|
|
const htmlContent = marked(parsed.body);
|
|
const plainText = htmlContent.replace(/<\/?[^>]+(>|$)/g, ""); // Strip HTML tags from Markdown-converted content
|
|
|
|
// Truncate the plain text to create the preview
|
|
const generatedPreview = plainText.split(' ').slice(0, 30).join(' ').substring(0, 150); // First 150 characters
|
|
|
|
// Use the preview from front matter if available, otherwise use the generated plain-text preview
|
|
const finalPreview = preview || generatedPreview;
|
|
|
|
const slug = file.replace('.md', ''); // Remove file extension for slug
|
|
|
|
console.log(`Preview for ${title}: ${finalPreview}`); // Log the preview to verify
|
|
|
|
return {
|
|
title,
|
|
date,
|
|
preview: finalPreview, // Ensure the correct preview is sent
|
|
slug
|
|
};
|
|
});
|
|
}
|
|
|
|
|
|
// New Route to generate RSS feed - put this before the dynamic slug route
|
|
router.get('/rss.xml', (req, res) => {
|
|
const feed = new RSS({
|
|
title: 'The Klein Blog',
|
|
description: 'Latest updates from The Klein Blog',
|
|
feed_url: `${req.protocol}://${req.get('host')}/rss.xml`,
|
|
site_url: `${req.protocol}://${req.get('host')}`,
|
|
language: 'en',
|
|
pubDate: new Date().toUTCString(),
|
|
});
|
|
|
|
// Add each blog post to the RSS feed
|
|
const posts = getBlogPosts();
|
|
posts.forEach(post => {
|
|
feed.item({
|
|
title: post.title,
|
|
description: post.preview, // Short preview for the RSS feed
|
|
url: `${req.protocol}://${req.get('host')}/blog/${post.slug}`, // Link to the blog post
|
|
date: post.date, // Published date
|
|
});
|
|
});
|
|
|
|
// Set the content type to XML and send the RSS feed
|
|
res.set('Content-Type', 'application/rss+xml');
|
|
res.send(feed.xml());
|
|
});
|
|
|
|
// Route to serve the blog posts as JSON
|
|
router.get('/blog-posts', (req, res) => {
|
|
const posts = getBlogPosts(); // Get all blog posts
|
|
res.json(posts); // Return posts as JSON to be fetched by the client-side JS
|
|
});
|
|
|
|
// Route to serve the main blog page (serve blog.html)
|
|
router.get('/', (req, res) => {
|
|
// Render the blog.html file from the views directory
|
|
res.sendFile(path.join(__dirname, '../views/blog.html'));
|
|
});
|
|
|
|
marked.setOptions({
|
|
gfm: true, // GitHub-flavored Markdown
|
|
breaks: true, // Enable line breaks
|
|
smartypants: true, // Use smart quotes, dashes, etc.
|
|
sanitize: false, // This is the important option to allow HTML tags
|
|
});
|
|
|
|
// Route to serve individual blog posts dynamically
|
|
router.get('/:slug', (req, res) => {
|
|
const { slug } = req.params;
|
|
const filePath = path.join(blogDirectory, `${slug}.md`);
|
|
|
|
if (fs.existsSync(filePath)) {
|
|
const content = fs.readFileSync(filePath, 'utf-8');
|
|
const parsed = fm(content); // Parse front matter
|
|
const htmlContent = marked(parsed.body); // Convert markdown body to HTML
|
|
res.render('post', { content: htmlContent, title: parsed.attributes.title, date: parsed.attributes.date }); // Render post view
|
|
} else {
|
|
res.status(404).send('Blog post not found');
|
|
}
|
|
});
|
|
|
|
module.exports = router; |