UNPKG

astro-maintenance

Version:

Maintenance and Coming Soon integration for Astro

147 lines (129 loc) 4.7 kB
import type { MaintenanceOptions } from "./index"; import { HandlebarsCompatibleEngine, renderTemplate, type TemplateContext } from "./templateEngine"; // Use ?raw to import file content as string import simpleTemplateSource from "./templates/simple.hbs?raw"; import countdownTemplateSource from "./templates/countdown.hbs?raw"; import constructionTemplateSource from "./templates/construction.hbs?raw"; // Built-in templates imported as raw strings const builtInTemplates: Record<string, string> = { simple: simpleTemplateSource, countdown: countdownTemplateSource, construction: constructionTemplateSource, }; // Cache for compiled template functions (for performance optimization) const compiledTemplateCache: Record<string, (context: TemplateContext) => string> = {}; /** * Get or compile a built-in template */ function getCompiledTemplate(templateName: string): (context: TemplateContext) => string { // Check cache first if (compiledTemplateCache[templateName]) { return compiledTemplateCache[templateName]; } // Get template source const source = builtInTemplates[templateName]; if (!source) { console.error(`Built-in template "${templateName}" not found, falling back to simple template`); // Recursive call to get simple template (which should always exist) return getCompiledTemplate("simple"); } // Compile and cache const compiled = HandlebarsCompatibleEngine.compile(source); compiledTemplateCache[templateName] = compiled; return compiled; } /** * Helper to detect if a string is template content vs template name */ function isTemplateContent(template: string): boolean { // Template content should contain HTML tags or be multiline return template.includes('<') || template.includes('\n') || template.length > 100; } /** * Compile custom template content */ function compileCustomTemplate(templateContent: string): (context: TemplateContext) => string { try { return HandlebarsCompatibleEngine.compile(templateContent); } catch (error) { console.error(`Error compiling custom template: ${error}`); // Fallback to simple template return getCompiledTemplate("simple"); } } /** * Main function to render a maintenance page * Works consistently across all deployment environments including Cloudflare Workers */ export default function renderPage(options: MaintenanceOptions): string { const { template = "simple", title = "We're sorry! The Site is under maintenance right now.", description = "Our website is currently down for scheduled maintenance. We'll return shortly. We appreciate your patience.", logo, emailAddress, emailText = "Contact us for further information.", copyright = "Copyright © 2025", countdown, socials, } = options; // Prepare template context data const templateContext: TemplateContext = { title, description, logo, copyright, emailAddress, emailText, countdown, socials, }; try { // Check if template is custom content (imported using ?raw) if (typeof template === "string" && isTemplateContent(template)) { const customTemplate = compileCustomTemplate(template); return customTemplate(templateContext); } // Handle built-in templates by name let templateName: string; if (template === "countdown" && countdown) { templateName = "countdown"; } else if (template === "construction") { templateName = "construction"; } else if (template === "simple" || !template) { templateName = "simple"; } else if (typeof template === "string" && builtInTemplates[template]) { templateName = template; } else { // Unknown template name or deprecated file path usage console.warn( `[astro-maintenance] Unknown template "${template}" or file path templates are no longer supported. ` + `Please use "simple", "countdown", "construction", or import your template using "?raw". ` + `Falling back to simple template.` ); templateName = "simple"; } const compiledTemplate = getCompiledTemplate(templateName); return compiledTemplate(templateContext); } catch (error) { console.error(`[astro-maintenance] Error rendering template:`, error); // Emergency fallback - render a basic HTML page return `<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>${templateContext.title || 'Site Maintenance'}</title> <style> body { font-family: sans-serif; text-align: center; padding: 50px; } h1 { color: #333; } p { color: #666; } </style> </head> <body> <h1>${templateContext.title || 'Site Under Maintenance'}</h1> <p>${templateContext.description || 'We\'ll be back shortly!'}</p> </body> </html>`; } }