import fs from 'node:fs'; import { spawn } from 'node:child_process'; import path from 'node:path'; import { defineConfig } from 'vite'; function generatedPages(directory) { const inputs = {}; for (const entry of fs.readdirSync(directory, { withFileTypes: true })) { const filePath = path.join(directory, entry.name); if (entry.isDirectory()) Object.assign(inputs, generatedPages(filePath)); else if (entry.name === 'index.html') { const relativePath = path.relative('.generated', filePath); const key = relativePath.endsWith('/index.html') ? relativePath.slice(0, -'/index.html'.length) : relativePath; inputs[key] = path.resolve(filePath); } } return inputs; } function contentGenerator() { let timer; let generator; let rerun = false; const generate = (server) => { if (generator) { rerun = true; return; } generator = spawn(process.execPath, ['generator.js'], { stdio: 'inherit' }); generator.on('error', (error) => { console.error(`Content generation failed: ${error.message}`); }); generator.on('close', (code) => { generator = undefined; if (code === 0) server.ws.send({ type: 'full-reload' }); if (rerun) { rerun = false; generate(server); } }); }; return { name: 'content-generator', configureServer(server) { const sources = [ path.resolve('notes'), path.resolve('posts'), path.resolve('README.md'), path.resolve('THIRD_PARTY_LICENSES.md'), path.resolve('external.json'), path.resolve('generator.js'), path.resolve('html.js'), ]; server.watcher.add(sources); server.watcher.on('all', (event, file) => { if (!['add', 'change', 'unlink'].includes(event)) return; const isMarkdown = file.endsWith('.md') && (file.startsWith(`${path.resolve('notes')}/`) || file.startsWith(`${path.resolve('posts')}/`)); const isExternal = file === path.resolve('external.json'); const isStandaloneMarkdown = file === resolve('README.md') || file === path.resolve('THIRD_PARTY_LICENSES.md'); const isGenerator = file === path.resolve('generator.js') || file === path.resolve('html.js'); if (!isMarkdown && !isStandaloneMarkdown && !isExternal && !isGenerator) return; clearTimeout(timer); timer = setTimeout(() => { generate(server); }, 100); }); }, }; } export default defineConfig({ plugins: [contentGenerator()], root: '.generated', publicDir: '../public', resolve: { alias: { '/src': path.resolve('src'), }, }, server: { watch: { ignored: ['**/.generated/**'], }, }, build: { outDir: path.resolve('dist'), emptyOutDir: true, rollupOptions: { input: generatedPages('.generated'), }, }, });