"use strict"; const h = require("highland"); const fs = require("fs"); const path = require("path"); const toml = require("toml"); const { promisify } = require("util"); const matter = require("gray-matter"); const markdown = require("../modules/markdown.js"); const predentation = require("predentation"); const { indentForTemplate, postIndentLevel } = require("../responders.js"); const grayMatterOptions = { lang: "toml", delims: "+++", engines: { toml: toml.parse.bind(toml) } }; function* lowercaseKeys(iterator) { for (let [k, v] of iterator) { yield [String(k).toLowerCase(), v]; } } function canonicaliseMetadata(meta) { if (meta.data) { meta.data = new Map(lowercaseKeys(Object.entries(meta.data))); } else { meta.data = new Map(); } return meta; } function getTitle(file) { return path.basename(file.path, path.extname(file.path)); } async function indentBody(content) { return await h( h .of(content) .map(markdown) .map(html => indentForTemplate(html, postIndentLevel)) .pipe(predentation()) ) .invoke("toString", ["utf-8"]) .toPromise(Promise); } async function get(getURL, filename) { const fileMatter = matter.read(filename, grayMatterOptions); fileMatter.basename = getTitle(fileMatter); delete fileMatter.orig; fileMatter.body = await indentBody(fileMatter.content); fileMatter.url = getURL(fileMatter.basename); return Promise.resolve(canonicaliseMetadata(fileMatter)); } async function getFolder(folder, getURL) { const files = (await promisify(fs.readdir)(folder)).map(f => path.resolve(folder, f) ); const posts = await Promise.all(files.map(get.bind(this, getURL))); return new Map(posts.map(f => [getTitle(f), f])); } function tag(posts) { const tags = new Map(); for (let [, post] of posts) { if (post.data.has("tags")) { for (let term of post.data.get("tags")) { const current = tags.get(term); tags.set(term, current ? current.concat(post) : [post]); } } } return tags; } module.exports = async function(config, getURL) { const posts = await getFolder(config.folder, getURL); const tags = tag(posts); const lastPostDate = Math.max(Array.from(posts.values(), p => p.date)); return { lastPostDate, posts, tags, get }; };