aboutsummaryrefslogtreecommitdiff
path: root/render.js
diff options
context:
space:
mode:
Diffstat (limited to 'render.js')
-rw-r--r--render.js172
1 files changed, 172 insertions, 0 deletions
diff --git a/render.js b/render.js
new file mode 100644
index 0000000..e394400
--- /dev/null
+++ b/render.js
@@ -0,0 +1,172 @@
+'use strict'
+
+const pug = require('pug')
+const marked = require('marked')
+const fs = require('fs').promises
+
+const walk = async (path, filename) => {
+ const type = await fs.lstat(path)
+ if (type.isFile()) return {type: 'file', path: path, name: filename || path}
+ if (!type.isDirectory()) return null
+
+ const files = await fs.readdir(path)
+ return {
+ type: 'folder',
+ path: path,
+ name: filename || path,
+ children: await Promise.all(files.map(file => walk(`${path}/${file}`, file)))
+ }
+}
+
+const ext_static = ['.css', '.js', '.otf', '.png', '.svg', '.txt', 'client', 'server']
+const ext_md = ['.md', '.markdown']
+const ext_pug = ['.pug', '.jade']
+
+const suffix = file => ext => file.substring(file.length - ext.length) == ext ? ext : null
+const suffixl = (...l) => file => l.find(suffix(file))
+const is_static = suffixl(...ext_static)
+const is_md = suffixl(...ext_md)
+const is_pug = suffixl(...ext_pug)
+
+const prefix = file => ext => file.substring(0, ext.length) == ext ? ext : null
+const prefixl = (...l) => file => l.find(prefix(file))
+
+const rm_prefix = (...l) => file => file.substring(prefixl(...l)(file).length)
+const rm_suffix = (...l) => file => file.substring(0, file.length - suffixl(...l)(file).length)
+
+const propagate_md_layout = (tree, markdown_template) => {
+ if (tree.type == 'file' && is_md(tree.name)) {
+ tree.template = markdown_template
+ } else if (tree.type == 'folder') {
+ const find_md_tpl = tree.children.filter(c => c.type == 'file' && c.name == '_markdown.pug')
+ const new_md_tpl = find_md_tpl.length > 0 ? find_md_tpl[0] : markdown_template
+ tree.children.forEach(c => propagate_md_layout(c, new_md_tpl))
+ }
+ return tree
+}
+
+const elagate_templates = tree => {
+ if (tree.type != 'folder') return tree
+
+ tree.children = tree.children.filter(e => !(e.type == 'file' && e.name[0] == '_'))
+ tree.children.forEach(elagate_templates)
+ return tree
+}
+
+const propagate_nice_name = prefix => tree => {
+ const without_prefix = tree.path.substring(prefix.length)
+ const splitted = without_prefix.split('/').filter(v => v.length > 0)
+ if (splitted.length > 0) {
+ tree.nice_path = splitted.slice(0, -1)
+ tree.nice_name = splitted[splitted.length - 1].split('.')[0]
+ tree.url = without_prefix
+ }
+
+ if (tree.type == 'folder') tree.children.forEach(propagate_nice_name(prefix))
+ return tree
+}
+
+const prepare_copy = (old_prefix, new_prefix, exts) => tree => {
+ if (tree.type == 'file' && is_static(tree.name)) {
+ tree.generate = {
+ cmd: 'copy',
+ src: tree.path,
+ out: new_prefix + rm_prefix(old_prefix)(tree.path)
+ }
+ } else if (tree.type == 'folder') {
+ tree.children.forEach(prepare_copy(old_prefix, new_prefix, exts))
+ }
+ return tree
+}
+
+const prepare_pug = (old_prefix, new_prefix) => tree => {
+ if (tree.type == 'file' && is_pug(tree.name)) {
+ tree.generate = {
+ cmd: 'pug',
+ src: tree.path,
+ out: new_prefix + rm_prefix(old_prefix)(rm_suffix(...ext_pug)(tree.path)) + '.html'
+ }
+ }
+ else if (tree.type == 'folder') {
+ tree.children.forEach(prepare_pug(old_prefix, new_prefix))
+ }
+
+ return tree
+}
+
+const prepare_md = (old_prefix, new_prefix) => tree => {
+ if (tree.type == 'file' && is_md(tree.name)) {
+ tree.generate = {
+ cmd: 'pug',
+ src: tree.template.path,
+ markdown: tree.path,
+ out: new_prefix + rm_prefix(old_prefix)(rm_suffix(...ext_md)(tree.path)) + '.html'
+ }
+ }
+ else if (tree.type == 'folder') {
+ tree.children.forEach(prepare_md(old_prefix, new_prefix))
+ }
+
+ return tree
+}
+
+const prepare_folder = (old_prefix, new_prefix) => tree => {
+ if (tree.type == 'folder') {
+ tree.generate = {
+ cmd: 'mkdir',
+ out: new_prefix + rm_prefix(old_prefix)(tree.path)
+ }
+ tree.children.forEach(prepare_folder(old_prefix, new_prefix))
+ }
+
+ return tree
+}
+
+const do_folder = async tree => {
+ if (!tree.generate || tree.generate.cmd != 'mkdir') return tree
+ await fs.mkdir(tree.generate.out, { recursive: true })
+ await Promise.all(tree.children.map(do_folder))
+ return tree
+}
+
+const do_copy = async tree => {
+ if (tree.generate && tree.generate.cmd == 'copy')
+ await fs.copyFile(tree.generate.src, tree.generate.out)
+ else if (tree.type == 'folder')
+ await Promise.all(tree.children.map(do_copy))
+
+ return tree
+}
+
+const do_pug = (prt, root) => async tree => {
+ prt = prt || tree
+ root = root || tree
+ if (tree.generate && tree.generate.cmd == 'pug') {
+ const html = pug.renderFile(tree.generate.src, {
+ markdown: tree.generate.markdown ? marked(await fs.readFile(tree.generate.markdown, 'utf-8')) : null,
+ prt: prt,
+ root: root,
+ element: tree
+ })
+ await fs.writeFile(tree.generate.out, html)
+ } else if (tree.type == 'folder')
+ await Promise.all(tree.children.map(do_pug(tree,root)))
+
+ return tree
+}
+
+
+const conf = { src: './src', dest: './static'}
+walk(conf.src)
+ .then(propagate_md_layout)
+ .then(elagate_templates)
+ .then(propagate_nice_name(conf.src))
+ .then(prepare_copy(conf.src, conf.dest))
+ .then(prepare_pug(conf.src, conf.dest))
+ .then(prepare_md(conf.src, conf.dest))
+ .then(prepare_folder(conf.src, conf.dest))
+ .then(do_folder)
+ .then(do_copy)
+ .then(do_pug())
+ .then(v => console.log("done"))
+ .catch(console.error)