Files
pokopiawiki.tootaio.com/frontend/vite.config.ts
xiaomai 5ccc25b248 feat: separate regular and event entities for Pokemon and Habitats
Add dedicated routes and navigation for Event Pokemon and Event Habitats
Update API endpoints to filter by isEventItem and adapt frontend views
2026-05-04 06:50:37 +08:00

107 lines
2.7 KiB
TypeScript

import { defineConfig, loadEnv, type PluginOption } from 'vite';
import vue from '@vitejs/plugin-vue';
const fallbackSiteUrl = 'https://pokopiawiki.tootaio.com';
const frontendPort = 20015;
const sitemapPaths = ['/pokemon', '/event-pokemon', '/habitats', '/event-habitats', '/items', '/recipes', '/checklist', '/life'];
const robotsDisallowPaths = [
'/admin',
'/login',
'/register',
'/forgot-password',
'/reset-password',
'/verify-email',
'/pokemon/new',
'/event-pokemon/new',
'/pokemon/*/edit',
'/habitats/new',
'/event-habitats/new',
'/habitats/*/edit',
'/items/new',
'/items/*/edit',
'/recipes/new',
'/recipes/*/edit',
'/automation',
'/dish',
'/events',
'/actions',
'/dream-island',
'/clothes'
];
function normalizeSiteUrl(value: string | undefined): string {
return (value?.trim() || fallbackSiteUrl).replace(/\/+$/, '');
}
function robotsTxt(siteUrl: string): string {
const disallowLines = robotsDisallowPaths.map((path) => `Disallow: ${path}`).join('\n');
return `User-agent: *\nAllow: /\n${disallowLines}\nSitemap: ${siteUrl}/sitemap.xml\n`;
}
function sitemapXml(siteUrl: string): string {
const urls = sitemapPaths
.map(
(path) => ` <url>
<loc>${siteUrl}${path}</loc>
<changefreq>weekly</changefreq>
</url>`
)
.join('\n');
return `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${urls}
</urlset>
`;
}
function seoFilesPlugin(siteUrl: string): PluginOption {
return {
name: 'pokopia-seo-files',
transformIndexHtml(html) {
return html.replaceAll('%POKOPIA_SITE_URL%', siteUrl);
},
configureServer(server) {
server.middlewares.use((request, response, next) => {
if (request.url === '/robots.txt') {
response.setHeader('Content-Type', 'text/plain; charset=utf-8');
response.end(robotsTxt(siteUrl));
return;
}
if (request.url === '/sitemap.xml') {
response.setHeader('Content-Type', 'application/xml; charset=utf-8');
response.end(sitemapXml(siteUrl));
return;
}
next();
});
},
generateBundle() {
this.emitFile({
type: 'asset',
fileName: 'robots.txt',
source: robotsTxt(siteUrl)
});
this.emitFile({
type: 'asset',
fileName: 'sitemap.xml',
source: sitemapXml(siteUrl)
});
}
};
}
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), '');
const siteUrl = normalizeSiteUrl(process.env.VITE_SITE_URL ?? env.VITE_SITE_URL);
return {
plugins: [vue(), seoFilesPlugin(siteUrl)],
server: {
port: frontendPort
}
};
});