#!/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); } let ticker = 0; 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; ticker++; 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)); console.log("----------------\n" + ticker + " pages successfully written"); console.error(skippedFiles.length + " files skipped");