- 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
62 lines
2.2 KiB
JavaScript
62 lines
2.2 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
const contentService = require('../services/content');
|
|
const commentService = require('../services/comments');
|
|
|
|
function renderPost(req, res, next, slug, lang) {
|
|
const post = contentService.getPost(slug, lang);
|
|
if (!post) {
|
|
return next(); // Fall through to standalone pages or 404
|
|
}
|
|
|
|
const { prev, next: nextPost } = contentService.getAdjacentPosts(slug);
|
|
const comments = commentService.getCommentsForPost(slug);
|
|
|
|
// Set SEO metadata for post
|
|
res.locals.seo = {
|
|
title: `${post.title} - ${res.locals.site.title}`,
|
|
description: post.excerpt || res.locals.site.tagline,
|
|
canonicalUrl: `${res.locals.site.url}/${post.slug}${post.isDefault ? '' : `/${post.lang}`}`,
|
|
ogImage: post.cover ? (post.cover.startsWith('http') ? post.cover : `${res.locals.site.url}${post.cover}`) : res.locals.seo.ogImage,
|
|
type: 'article',
|
|
publishedTime: post.date.toISOString(),
|
|
author: post.author
|
|
};
|
|
|
|
res.render('pages/post', {
|
|
title: post.title,
|
|
post,
|
|
currentLang: lang || post.lang,
|
|
comments,
|
|
commentStatus: req.query.comment_status,
|
|
prevPost: prev,
|
|
nextPost
|
|
});
|
|
}
|
|
|
|
// Route for bilingual variant: /<post-slug>/<lang> (e.g. /my-post/zh)
|
|
router.get('/:slug/:lang([a-zA-Z]{2,5})', (req, res, next) => {
|
|
const post = contentService.getPost(req.params.slug);
|
|
if (post && post.defaultLang === req.params.lang) {
|
|
return res.redirect(301, `/${req.params.slug}`);
|
|
}
|
|
renderPost(req, res, next, req.params.slug, req.params.lang);
|
|
});
|
|
|
|
// Legacy redirects for multilingual posts
|
|
router.get('/ai-can-change-coding-for-kids-en', (req, res) => {
|
|
res.redirect(301, '/ai-can-change-coding-for-kids');
|
|
});
|
|
|
|
// Route for default language: /<post-slug>
|
|
router.get('/:slug', (req, res, next) => {
|
|
// Exclude reserved top-level prefixes if any
|
|
const reserved = ['blogs', 'category', 'tag', 'tags', 'search', 'quick-links', 'feed', 'rss.xml', 'sitemap.xml', 'robots.txt', 'api', 'plugins', 'public', 'posts-assets', 'guanli', 'admin'];
|
|
if (reserved.includes(req.params.slug)) {
|
|
return next();
|
|
}
|
|
renderPost(req, res, next, req.params.slug, null);
|
|
});
|
|
|
|
module.exports = router;
|