website/pages.js

76 lines
2.0 KiB
JavaScript

const fs = require('fs');
const path = require('path');
const showdown = require('showdown');
const frontmatter = require('front-matter');
const converter = new showdown.Converter();
// Pages to process
const dir = 'src/pages';
// Where to put them
const distDir = 'dist'
// Required meta
const requiredMeta = ['title']
// Actual processing
function run() {
if (!fs.existsSync(distDir)) fs.mkdirSync(distDir);
getPages().forEach((page) => {
const dirPath = path.join(distDir, page.path);
if (!fs.existsSync(dirPath)) fs.mkdirSync(dirPath);
fs.writeFileSync(path.join(dirPath, 'index.html'), buildTemplate(page.title, page.body))
});
}
// Generic template
const template = fs.readFileSync(path.join('src', 'pages.html')).toString();
// Inject the title and body
function buildTemplate(title, body) {
return template
.replace('{{title}}', title)
.replace('{{body}}', body)
}
// Validate a page's metadata
function validateMeta(meta) {
const attr = meta.attributes;
let errs = [];
requiredMeta.forEach((required) => {
if (!(required in attr)) errs.push(`missing ${required}`);
});
return errs
}
// Module stuff
class Page {
constructor(title, path, body, file) {
this.title = title;
this.path = path;
this.body = body;
this.file = file;
}
}
function getPages() {
const pages = [];
fs.readdirSync(dir).forEach((file) => {
const filePath = path.join(dir, file)
const contents = fs.readFileSync(filePath);
const meta = frontmatter(contents.toString())
const errs = validateMeta(meta);
if (errs.length) throw `Errors in ${file}:\n${errs.join('\n')}`;
const body = converter.makeHtml(meta.body);
pages.push(new Page(meta.attributes.title, 'path' in meta.attributes ? meta.attributes.path : path.basename(file), body, file));
});
return pages;
}
module.exports = { getPages };
// Run the h*ckin' thing
if (require.main === module) {
run();
}