import { promises as fs } from "fs"; import path from "path"; import dateFns from "date-fns"; import slugify from "@sindresorhus/slugify"; import * as util from "../util"; import * as metadata from "../metadata"; import { Page, PostMetadata } from "../metadata"; import * as markdown from "../markdown"; import layout from "../layout"; async function generatePostFromFile(postPath: string, additionalMetadata: object = {}): Promise { const page = await metadata.get(postPath); (page.metadata).tagSlugs = (page.metadata).tags.map((tag) => slugify(tag)); for (const k in additionalMetadata) { if (additionalMetadata.hasOwnProperty(k)) page.metadata[k] = additionalMetadata[k]; } if (!(page.metadata).permalink) { let postMeta = page.metadata; postMeta.date = dateFns.parse(postMeta.date); postMeta.slug = postMeta.slug || slugify(postMeta.title); postMeta.permalink = `/${postMeta.date.getFullYear()}/${postMeta.slug}/`; } if (page.metadata.source && page.metadata.source!.endsWith(".md")) { (page.metadata).wordCount = util.getWordCount(page.text); (page.metadata).readingTime = util.getReadingTime((page.metadata).wordCount); page.text = markdown.render(page.text); } page.text = util.render(page.text, { metadata: page.metadata }, postPath); // todo: handle word count if not .md if (!(page.metadata).excerpt) { const parts = page.text.split(""); if (parts.length > 1) { (page.metadata).excerpt = parts[0]; } } return page; } async function generatePostFromDirectory(dir: string): Promise { const files = await fs.readdir(dir); let indexPath: string; for (const f of files) { if (f.split(".")[0] === "index") { indexPath = path.join(dir, f); break; } } if (!indexPath) { throw new Error(`Unable to find index file for post: ${dir}`); } return await generatePostFromFile(indexPath, { sourceDir: dir }); } export default async function posts(): Promise { const posts: Page[] = []; const files = await fs.readdir("site/posts"); for (const f of files) { const postPath = path.join("site/posts", f); const stats = await fs.stat(postPath); let page: Page; if (stats.isDirectory()) { page = await generatePostFromDirectory(postPath); } else { page = await generatePostFromFile(postPath); } const renderedText = await layout(page.text, page.metadata, page.metadata.layout || "article.html.ejs"); let dest = page.metadata.permalink; if (dest.endsWith("/")) { dest += "index.html"; } util.write(dest, renderedText); posts.push(page); } return posts; }