- Migrate historical posts, localized assets, and 103 comments - Colocate media into posts/<slug>/images/ and remove wp-content - Add native bilingual support for ai-can-change post (English default, /zh variant) - Support clean taxonomy routing (/category/:category and /tag/:tag) - Dynamically populate categories and tags in sitemap.xml - Fix header scroll padding/margin offsets for anchor and reference links - Constrain image and media widths to prevent content overflow - Redesign homepage recent posts to 4 compact editorial cards - Restore valid binary favicon.ico and high-res icon assets - Remove placeholder content and sample test comments
50 lines
1.9 KiB
JavaScript
50 lines
1.9 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
const contentService = require('../services/content');
|
|
|
|
function renderBlogListing(req, res, filterType, filterVal) {
|
|
let posts = contentService.getAllPosts();
|
|
const category = filterType === 'category' ? filterVal : req.query.category;
|
|
const tag = filterType === 'tag' ? filterVal : req.query.tag;
|
|
const page = req.query.page;
|
|
|
|
let activeFilter = null;
|
|
|
|
if (category) {
|
|
const catLower = category.trim().toLowerCase();
|
|
posts = posts.filter(p => (p.category || '').toLowerCase() === catLower);
|
|
activeFilter = { type: 'category', value: category };
|
|
} else if (tag) {
|
|
const tagLower = tag.trim().toLowerCase();
|
|
posts = posts.filter(p => (p.tags || []).some(t => t.toLowerCase() === tagLower));
|
|
activeFilter = { type: 'tag', value: tag };
|
|
}
|
|
|
|
const postsPerPage = 12;
|
|
const currentPage = Math.max(1, parseInt(page, 10) || 1);
|
|
const totalPosts = posts.length;
|
|
const totalPages = Math.ceil(totalPosts / postsPerPage);
|
|
|
|
const startIndex = (currentPage - 1) * postsPerPage;
|
|
const paginatedPosts = posts.slice(startIndex, startIndex + postsPerPage);
|
|
|
|
const taxonomy = contentService.getTaxonomy();
|
|
|
|
res.render('pages/blogs', {
|
|
title: activeFilter ? `${activeFilter.value} - ${activeFilter.type === 'category' ? 'Category' : 'Tag'} - ${res.locals.site.title}` : `Blogs - ${res.locals.site.title}`,
|
|
posts: paginatedPosts,
|
|
currentPage,
|
|
totalPages,
|
|
totalPosts,
|
|
activeFilter,
|
|
taxonomy
|
|
});
|
|
}
|
|
|
|
router.get('/blogs', (req, res) => renderBlogListing(req, res));
|
|
router.get('/category/:category', (req, res) => renderBlogListing(req, res, 'category', req.params.category));
|
|
router.get('/tag/:tag', (req, res) => renderBlogListing(req, res, 'tag', req.params.tag));
|
|
router.get('/tags/:tag', (req, res) => renderBlogListing(req, res, 'tag', req.params.tag));
|
|
|
|
module.exports = router;
|