import fs from "node:fs"; import { fileURLToPath } from "node:url"; import { notFoundTemplate, subpathNotUsedTemplate } from "../../template/4xx.js"; import { cleanUrl } from "../../vite-plugin-utils/index.js"; import { stripBase } from "./util.js"; const HAS_FILE_EXTENSION_REGEXP = /^.*\.[^\\]+$/; function vitePluginAstroPreview(settings) { const { base, outDir, trailingSlash } = settings.config; return { name: "astro:preview", apply: "serve", configurePreviewServer(server) { server.middlewares.use((req, res, next) => { if (!req.url.startsWith(base)) { res.statusCode = 404; res.end(subpathNotUsedTemplate(base, req.url)); return; } const pathname = cleanUrl(stripBase(req.url, base)); const isRoot = pathname === "/"; if (!isRoot) { const hasTrailingSlash = pathname.endsWith("/"); if (hasTrailingSlash && trailingSlash == "never") { res.statusCode = 404; res.end(notFoundTemplate(pathname, 'Not Found (trailingSlash is set to "never")')); return; } if (!hasTrailingSlash && trailingSlash == "always" && !HAS_FILE_EXTENSION_REGEXP.test(pathname)) { res.statusCode = 404; res.end(notFoundTemplate(pathname, 'Not Found (trailingSlash is set to "always")')); return; } } next(); }); return () => { server.middlewares.use((req, res, next) => { const pathname = cleanUrl(req.url); if (pathname.endsWith("/")) { const pathnameWithoutSlash = pathname.slice(0, -1); const htmlPath = fileURLToPath(outDir + pathnameWithoutSlash + ".html"); if (fs.existsSync(htmlPath)) { req.url = pathnameWithoutSlash + ".html"; return next(); } } else { const htmlPath = fileURLToPath(outDir + pathname + "/index.html"); if (fs.existsSync(htmlPath)) { req.url = pathname + "/index.html"; return next(); } } next(); }); for (const middleware of server.middlewares.stack) { if (middleware.handle.name === "vite404Middleware") { middleware.handle = (req, res) => { const errorPagePath = fileURLToPath(outDir + "/404.html"); if (fs.existsSync(errorPagePath)) { res.statusCode = 404; res.setHeader("Content-Type", "text/html;charset=utf-8"); res.end(fs.readFileSync(errorPagePath)); } else { res.statusCode = 404; res.end(notFoundTemplate(req.url, "Not Found")); } }; } } }; } }; } export { vitePluginAstroPreview };