#!/usr/bin/env node /** * Post-build: inline critical CSS in dist/*.html (SvelteKit adapter-static output). * Runs after vite build; Beasties reads/writes relative to dist/. * * Beasties with preload:'default' adds preload tags; same options as legacy Critters. */ import Beasties from 'beasties'; import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const ROOT = path.join(__dirname, '..'); const DIST = path.join(ROOT, 'dist'); async function main() { if (!fs.existsSync(DIST)) { console.error('dist/ not found. Run vite build first.'); process.exit(1); } const beasties = new Beasties({ path: DIST, preload: 'default', noscriptFallback: true, pruneSource: false, logLevel: 'warn', }); const rootFiles = fs.readdirSync(DIST) .filter((f) => f.endsWith('.html')) .map((f) => path.join(DIST, f)); const servicesDir = path.join(DIST, 'services'); const serviceFiles = []; if (fs.existsSync(servicesDir)) { const walk = (dir) => { for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { const fullPath = path.join(dir, entry.name); if (entry.isDirectory()) { walk(fullPath); } else if (entry.isFile() && entry.name.endsWith('.html')) { serviceFiles.push(fullPath); } } }; walk(servicesDir); } const files = [...rootFiles, ...serviceFiles]; for (const filePath of files) { let html = fs.readFileSync(filePath, 'utf8'); html = await beasties.process(html); fs.writeFileSync(filePath, html, 'utf8'); console.log('✓ Critical CSS inlined → dist/' + path.relative(DIST, filePath)); } console.log('Critical CSS step complete.'); } main().catch((err) => { console.error(err); process.exit(1); });