disseminate/index.ts
hexlocation's laptop (asiago) 4ea74c0cb1 aaa
2024-03-29 08:51:20 -04:00

68 lines
1.9 KiB
TypeScript

import marked from "marked";
import express from "express"
import ejs from "ejs";
import fs from "fs";
import path from "path";
import jsdom from "jsdom";
import config from "./config.json"
let app = express();
// set view engine to ejs
app.set("view engine", "ejs")
app.set('views', path.join(__dirname, 'templates'))
// type for post object
type Post = {
file: string;
title: string;
parsedPost: string;
rawPost: string;
metadata: fs.Stats;
}
// html stripper, used for title
async function htmlstripper(html: string){
return new jsdom.JSDOM(html).window.document.body.textContent || " ";
}
// returns Post array
async function contentScan(){
let posts: Post[] = []
let postsDir = path.join(__dirname, "posts")
let files = await fs.readdirSync(postsDir).filter((name: string) => name.toLowerCase().endsWith(".md"))
for (const file of files) {
let postPath = path.join(postsDir, file)
let metadata = fs.statSync(postPath)
let postContent = fs.readFileSync(postPath, "utf-8")
posts.push(
{
file: file,
title: await htmlstripper(
await marked.parse(
postContent.split("\n")[0]
)
),
metadata: metadata,
parsedPost: await marked.parse(postContent),
rawPost: postContent
}
)
}
return posts;
}
app.get("/", async (req:express.Request,res:express.Response) => {
res.render("index", {posts: (await contentScan()), config: config})
});
app.use("/post/:post", async (req:express.Request,res:express.Response) => {
let pathToPost = path.join(__dirname, "posts", req.params.post);
if(!fs.existsSync(pathToPost)) return res.end("404.");
let posts = await contentScan();
let post = posts.filter(post => post.file === req.params.post)
if(!post[0]) return res.end("404.")
res.render("post", {posts: posts, post: post[0], config: config})
})
app.listen(3024)