- 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
98 lines
3.4 KiB
JavaScript
98 lines
3.4 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
const contentService = require('../services/content');
|
|
|
|
router.get('/sitemap.xml', (req, res) => {
|
|
const siteUrl = res.locals.site.url;
|
|
const posts = contentService.getAllPosts();
|
|
const pages = Array.from(contentService.pagesBySlug.values());
|
|
|
|
let xml = '<?xml version="1.0" encoding="UTF-8"?>\n';
|
|
xml += '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n';
|
|
|
|
// Static / Top-level pages
|
|
const staticRoutes = ['/', '/blogs', '/search'];
|
|
for (const route of staticRoutes) {
|
|
xml += ' <url>\n';
|
|
xml += ` <loc>${siteUrl}${route}</loc>\n`;
|
|
xml += ` <changefreq>daily</changefreq>\n`;
|
|
xml += ` <priority>${route === '/' ? '1.0' : '0.8'}</priority>\n`;
|
|
xml += ' </url>\n';
|
|
}
|
|
|
|
// Standalone pages
|
|
for (const page of pages) {
|
|
if (!page.slug || page.slug === '/') continue;
|
|
const cleanSlug = page.slug.startsWith('/') ? page.slug : `/${page.slug}`;
|
|
if (cleanSlug === '/guanli' || cleanSlug.startsWith('/guanli/') || cleanSlug === '/admin' || cleanSlug.startsWith('/admin/')) {
|
|
continue;
|
|
}
|
|
xml += ' <url>\n';
|
|
xml += ` <loc>${siteUrl}${cleanSlug}</loc>\n`;
|
|
xml += ` <changefreq>weekly</changefreq>\n`;
|
|
xml += ` <priority>0.7</priority>\n`;
|
|
xml += ' </url>\n';
|
|
}
|
|
|
|
// Blog posts (including translations)
|
|
for (const post of posts) {
|
|
if (!post.slug || post.slug.startsWith('guanli') || post.slug.startsWith('admin')) continue;
|
|
xml += ' <url>\n';
|
|
xml += ` <loc>${siteUrl}/${post.slug}</loc>\n`;
|
|
xml += ` <lastmod>${post.date.toISOString().split('T')[0]}</lastmod>\n`;
|
|
xml += ` <changefreq>monthly</changefreq>\n`;
|
|
xml += ` <priority>0.9</priority>\n`;
|
|
xml += ' </url>\n';
|
|
|
|
// Bilingual URLs
|
|
if (post.availableLanguages) {
|
|
for (const lang of post.availableLanguages) {
|
|
if (lang !== post.lang && lang !== 'default') {
|
|
xml += ' <url>\n';
|
|
xml += ` <loc>${siteUrl}/${post.slug}/${lang}</loc>\n`;
|
|
xml += ` <lastmod>${post.date.toISOString().split('T')[0]}</lastmod>\n`;
|
|
xml += ` <changefreq>monthly</changefreq>\n`;
|
|
xml += ` <priority>0.8</priority>\n`;
|
|
xml += ' </url>\n';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Taxonomy archive pages (Categories & Tags)
|
|
const taxonomy = contentService.getTaxonomy();
|
|
if (taxonomy.categories && taxonomy.categories.length > 0) {
|
|
for (const cat of taxonomy.categories) {
|
|
xml += ' <url>\n';
|
|
xml += ` <loc>${siteUrl}/category/${encodeURIComponent(cat.name)}</loc>\n`;
|
|
xml += ` <changefreq>weekly</changefreq>\n`;
|
|
xml += ` <priority>0.6</priority>\n`;
|
|
xml += ' </url>\n';
|
|
}
|
|
}
|
|
|
|
if (taxonomy.tags && taxonomy.tags.length > 0) {
|
|
for (const tag of taxonomy.tags) {
|
|
xml += ' <url>\n';
|
|
xml += ` <loc>${siteUrl}/tag/${encodeURIComponent(tag.name)}</loc>\n`;
|
|
xml += ` <changefreq>weekly</changefreq>\n`;
|
|
xml += ` <priority>0.5</priority>\n`;
|
|
xml += ' </url>\n';
|
|
}
|
|
}
|
|
|
|
xml += '</urlset>';
|
|
|
|
res.header('Content-Type', 'application/xml; charset=utf-8');
|
|
res.send(xml);
|
|
});
|
|
|
|
router.get('/robots.txt', (req, res) => {
|
|
const siteUrl = res.locals.site.url;
|
|
const content = `User-agent: *\nDisallow: /admin/\nAllow: /\n\nSitemap: ${siteUrl}/sitemap.xml\n`;
|
|
res.header('Content-Type', 'text/plain; charset=utf-8');
|
|
res.send(content);
|
|
});
|
|
|
|
module.exports = router;
|