index.js (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
#!/usr/bin/env bun
import cpy from "cpy";
import double from "./addons/double.js"; //TODO add systemized plugin support
import insertJSX from "./insertJSX.js";
import rehypeDocument from "rehype-document";
import rehypeFormat from "rehype-format";
import rehypeRaw from "rehype-raw";
import rehypeStringify from "rehype-stringify";
import rehypeWrap from "rehype-wrap";
import remarkParse from "remark-parse";
import remarkRehype from "remark-rehype";
import { emptyDir } from "fs-extra";
import { glob } from "glob";
import { matter } from "vfile-matter";
import { read, write } from "to-vfile";
import { resolve } from "path";
import { unified } from "unified";
import { reporterPretty } from "vfile-reporter-pretty";
const skippedFiles = [];
function errCatch(file, error) {
file.message(error);
skippedFiles.push(file);
return null;
}
// Resolve input/putput directories respecting a project's root folder.
const inputDir = resolve(process.cwd(), "input");
const outputDir = resolve(process.cwd(), "out");
const site = await glob(`${inputDir}/**/*.md`, { nodir: true });
// mise en place
emptyDir(`${outputDir}`, { recursive: true }); // clears the output folder
await cpy([`${inputDir}/**`, `!${inputDir}/**/*.md`], `${outputDir}`, {
flat: true,
}); //copies all assets into out/
async function createSiteIndex() {
return (
await Promise.all(
site.map(async (page) => {
let file = await read(page, "utf-8");
try {
matter(file);
file.data.matter.filename = file.stem;
return file.data.matter;
} catch (e) {
errCatch(file, e);
}
}),
)
).filter(Boolean);
}
export async function kushiyaki(filepath, siteIndex) {
const file = await read(filepath, "utf-8");
try {
matter(file, { strip: true });
file.data.matter.filename = file.stem;
} catch (e) {
return null;
}
const processor = unified()
.data("siteIndex", siteIndex)
.use(remarkParse)
.use(double)
.use(remarkRehype, { allowDangerousHtml: true })
.use(rehypeRaw)
.use(rehypeWrap, { wrapper: "main" })
.use(insertJSX, file.data.matter)
.use(rehypeDocument, {
css: file.data.matter?.css ?? "style.css",
title: file.data.matter?.title ?? "untitled",
link: [{ href: "favicon.png", rel: "icon", type: "image/png" }], //FIX make filetype-agnostic
})
.use(rehypeFormat)
.use(rehypeStringify);
try {
const output = await processor.process(file);
output.extname = ".html";
output.dirname = outputDir;
return output;
} catch (e) {
errCatch(file, e);
}
}
// Loop through function for each page
const siteIndex = await createSiteIndex();
for (const file of site) {
const output = await kushiyaki(file, siteIndex);
if (output) await write(output);
}
console.log(reporterPretty(skippedFiles));
|