Created
May 25, 2020 00:31
-
-
Save ebanisadr/891f686ffbc09947bbcbfc0270c7225b to your computer and use it in GitHub Desktop.
Simple Javascript SSG
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
const fs = require('fs'); | |
const path = require('path'); | |
const compile = require('./compiler'); | |
const inputDir = 'content'; | |
const outputDir = 'stage'; | |
let overrides = {}; | |
if (process.argv[2] === 'dev') { | |
overrides.baseurl = path.join(__dirname, outputDir) + '/'; | |
} | |
function processFile(file) { | |
console.log('Processing:', file); | |
let extension = file.substring(file.lastIndexOf('.') + 1); | |
switch (extension) { | |
case 'md': | |
return { | |
path: file.replace(inputDir, outputDir).replace(/md$/, 'html'), | |
content: compile(file, overrides) | |
}; | |
case'html': | |
return { | |
path: file.replace(inputDir, outputDir), | |
content: compile(file, overrides) | |
}; | |
case 'css': | |
return { | |
path: file.replace(inputDir, outputDir), | |
content: fs.readFileSync(file, { encoding: 'utf-8' }) | |
}; | |
case 'jpg': | |
case 'png': | |
case 'pdf': | |
return { | |
path: file.replace(inputDir, outputDir), | |
content: fs.readFileSync(file) | |
} | |
default: | |
return undefined; | |
} | |
} | |
function processDir(dir) { | |
let contents = fs.readdirSync(dir); | |
let files = contents | |
.filter((name) => !fs.lstatSync(path.join(dir, name)).isDirectory()); | |
let folders = contents | |
.filter((name) => fs.lstatSync(path.join(dir, name)).isDirectory()); | |
files.forEach((file) => { | |
let output = processFile(path.join(dir, file)); | |
if (output) { | |
console.log('Writing:', output.path); | |
fs.writeFileSync(output.path, output.content); | |
} else { | |
console.log('Unhandled file:', path.join(dir, file)); | |
} | |
}); | |
folders.forEach((folder) => { | |
let loc = path.join(dir, folder); | |
console.log('Making directory:', loc.replace(inputDir, outputDir)); | |
fs.mkdirSync(loc.replace(inputDir, outputDir)); | |
processDir(loc); | |
}) | |
} | |
processDir('./content'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const path = require('path'); | |
const hljs = require('highlight.js'); | |
const yaml = require('js-yaml'); | |
const mustache = require('mustache'); | |
const fs = require('fs'); | |
const md = require('markdown-it')({ | |
html: true, | |
xhtmlOut: true, | |
breaks: false, | |
langPrefix: '', | |
linkify: true, | |
typographer: true, | |
quotes: '“”‘’', | |
highlight: function (str, lang) { | |
if (lang && hljs.getLanguage(lang)) { | |
try { | |
return hljs.highlight(lang, str).value; | |
} catch (e) { | |
console.err(e); | |
return ''; | |
} | |
} | |
} | |
}).use(require('markdown-it-sub')) | |
.use(require('markdown-it-sup')) | |
.use(require('markdown-it-abbr')) | |
.use(require('markdown-it-footnote')) | |
.use(require('markdown-it-container'), 'warning'); | |
// Consider: markdown-it-texmath | |
hljs.configure({ | |
tabReplace: ' ', | |
//useBR: true; | |
classPrefix: '' | |
}); | |
// Loads the files in the given directory into an object with this structure | |
// { file: 'file content' } | |
// where file is the filename without its extension | |
function loadDir(dir) { | |
return files = fs.readdirSync(dir) | |
.filter((filename) => !fs.lstatSync(path.join(dir, filename)).isDirectory()) | |
.map((filename) => { | |
let name = filename.substring(0, filename.indexOf('.')); | |
let content = fs.readFileSync(path.join(dir, filename), { encoding: 'utf-8' }); | |
let obj = {}; | |
obj[name] = content; | |
return obj; | |
}) | |
.reduce((name, partial) => Object.assign(name, partial), {}); | |
} | |
// Load sitewide variables | |
const site = require('./site.json'); | |
let templates = loadDir(site.templatesDir); | |
let partials = loadDir(site.partialsDir); | |
function compileMarkdown(filePath, siteOverrides) { | |
if (!fs.existsSync(filePath)) { | |
throw new Error("File not found: " + filePath); | |
} | |
const fileText = fs.readFileSync(filePath, { encoding: 'utf-8' }); | |
let yamlEnd = fileText.indexOf('---', 4); | |
let fileYaml = yaml.load(fileText.substring(0, yamlEnd)); | |
let fileMarkdown = fileText.substring(yamlEnd + 4); | |
let config = fileYaml; | |
config.site = site; | |
if (siteOverrides) { | |
Object.assign(config.site, siteOverrides); | |
} | |
let content = md.render(fileMarkdown); | |
let template = templates[config.template.toLowerCase()]; | |
let vars = config; | |
vars.content = content; | |
return mustache.render(template, vars, partials); | |
} | |
function compileHtml(filePath, siteOverrides) { | |
if (!fs.existsSync(filePath)) { | |
throw new Error("File not found: " + filePath); | |
} | |
const fileText = fs.readFileSync(filePath, { encoding: 'utf-8' }); | |
let config = { site: site }; | |
if (siteOverrides) { | |
Object.assign(config.site, siteOverrides); | |
} | |
return mustache.render(fileText, config, partials); | |
} | |
module.exports = function compile(filePath, siteOverrides) { | |
switch (filePath.substring(filePath.lastIndexOf('.'))) { | |
case '.md': | |
return compileMarkdown(filePath, siteOverrides); | |
case '.html': | |
return compileHtml(filePath, siteOverrides); | |
default: | |
console.log("Don't know how to compile file:", filePath); | |
return ''; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment