2019-01-04 18:14:53 +00:00
|
|
|
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";
|
|
|
|
|
2020-07-09 18:14:42 +00:00
|
|
|
async function generatePostFromFile(postPath: string, additionalMetadata: object = {}): Promise<Page> {
|
|
|
|
const page = await metadata.get(postPath);
|
|
|
|
|
2021-04-12 22:31:03 +00:00
|
|
|
(<PostMetadata>page.metadata).tagSlugs = (<PostMetadata>page.metadata).tags.map((tag) => slugify(tag));
|
|
|
|
|
2020-07-09 18:14:42 +00:00
|
|
|
for (const k in additionalMetadata) {
|
|
|
|
if (additionalMetadata.hasOwnProperty(k)) page.metadata[k] = additionalMetadata[k];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(<PostMetadata>page.metadata).permalink) {
|
|
|
|
let postMeta = <PostMetadata>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")) {
|
|
|
|
(<PostMetadata>page.metadata).wordCount = util.getWordCount(page.text);
|
|
|
|
(<PostMetadata>page.metadata).readingTime = util.getReadingTime((<PostMetadata>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 (!(<PostMetadata>page.metadata).excerpt) {
|
|
|
|
const parts = page.text.split("<!-- excerpt-end -->");
|
|
|
|
(<PostMetadata>page.metadata).excerpt = parts[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
return page;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function generatePostFromDirectory(dir: string): Promise<Page> {
|
|
|
|
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
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-01-04 18:14:53 +00:00
|
|
|
export default async function posts(): Promise<Page[]> {
|
|
|
|
const posts: Page[] = [];
|
|
|
|
|
|
|
|
const files = await fs.readdir("site/posts");
|
|
|
|
for (const f of files) {
|
2019-11-11 17:10:48 +00:00
|
|
|
const postPath = path.join("site/posts", f);
|
2020-07-09 18:14:42 +00:00
|
|
|
const stats = await fs.stat(postPath);
|
2019-01-04 18:14:53 +00:00
|
|
|
|
2020-07-09 18:14:42 +00:00
|
|
|
let page: Page;
|
2019-01-04 18:14:53 +00:00
|
|
|
|
2020-07-09 18:14:42 +00:00
|
|
|
if (stats.isDirectory()) {
|
|
|
|
page = await generatePostFromDirectory(postPath);
|
|
|
|
} else {
|
|
|
|
page = await generatePostFromFile(postPath);
|
2019-01-04 18:14:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2019-08-17 19:02:10 +00:00
|
|
|
}
|