#!/usr/bin/env node
/**
* Build-time HTML templating system for DocFast.
* No dependencies — uses only Node.js built-ins.
*
* - Reads page sources from templates/pages/*.html
* - Reads partials from templates/partials/*.html
* - Replaces {{> partial_name}} with partial content
* - Supports metadata comments at top of page files
* - Replaces {{key}} variables with extracted metadata
* - Writes output to public/
*/
import { readFileSync, writeFileSync, readdirSync } from 'node:fs';
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = fileURLToPath(new URL('.', import.meta.url));
const ROOT = join(__dirname, '..');
const PAGES_DIR = join(ROOT, 'templates', 'pages');
const PARTIALS_DIR = join(ROOT, 'templates', 'partials');
const OUTPUT_DIR = join(ROOT, 'public');
// Load all partials
const partials = {};
for (const file of readdirSync(PARTIALS_DIR)) {
if (!file.endsWith('.html')) continue;
const name = file.replace('.html', '');
partials[name] = readFileSync(join(PARTIALS_DIR, file), 'utf-8');
}
console.log(`Loaded ${Object.keys(partials).length} partials: ${Object.keys(partials).join(', ')}`);
// Process each page
const pages = readdirSync(PAGES_DIR).filter(f => f.endsWith('.html'));
console.log(`Processing ${pages.length} pages...`);
for (const file of pages) {
let content = readFileSync(join(PAGES_DIR, file), 'utf-8');
// Extract all metadata comments from the top
const vars = {};
while (true) {
const m = content.match(/^\n?/);
if (!m) break;
vars[m[1]] = m[2];
content = content.slice(m[0].length);
}
// Replace {{> partial_name}} with partial content (support nested partials)
let maxDepth = 5;
while (maxDepth-- > 0 && content.includes('{{>')) {
content = content.replace(/\{\{>\s*([a-zA-Z0-9_-]+)\s*\}\}/g, (match, name) => {
if (!(name in partials)) {
console.warn(` Warning: partial "${name}" not found in ${file}`);
return match;
}
return partials[name];
});
}
// Replace {{variable}} with extracted metadata
content = content.replace(/\{\{([a-zA-Z_-]+)\}\}/g, (match, key) => {
if (key in vars) return vars[key];
console.warn(` Warning: variable "${key}" not defined in ${file}`);
return match;
});
// Write output
const outPath = join(OUTPUT_DIR, file);
writeFileSync(outPath, content);
console.log(` ✓ ${file} (${(content.length / 1024).toFixed(1)}KB)`);
}
console.log('Done!');