blog/plugin/remark-typst.ts

59 lines
1.6 KiB
TypeScript
Raw Normal View History

2024-04-05 15:34:32 +00:00
import type { RemarkPlugin } from "@astrojs/markdown-remark";
import { mkdtempSync, readFileSync, writeFileSync } from "node:fs";
import { visit } from "unist-util-visit";
import { join, resolve, dirname } from "node:path";
2024-04-05 15:34:32 +00:00
import { spawnSync } from "node:child_process";
import { tmpdir } from "node:os";
import { readdir, copyFile } from "node:fs/promises";
2024-04-05 15:34:32 +00:00
const remarkTypst: RemarkPlugin = () => {
const tmp = mkdtempSync(join(tmpdir(), "typst"));
let ctr = 0;
return async (tree, { history }) => {
const path: string = resolve(history[history.length - 1]!);
const dir = dirname(path);
// Copy all the .typ files in the dir
for (const file of await readdir(dir)) {
console.log("checking", file);
if (file.endsWith(".typ")) {
const src = resolve(join(dir, file));
const dst = resolve(join(tmp, file));
console.log("copying", src, dst);
await copyFile(src, dst);
}
}
2024-04-05 15:34:32 +00:00
visit(
tree,
(node) => node.type === "code" && node.lang === "typst",
(node, index, parent) => {
const doc = resolve(join(tmp, `${ctr}.typ`));
const docOut = resolve(join(tmp, `${ctr}.svg`));
2024-04-05 15:34:32 +00:00
ctr += 1;
writeFileSync(doc, node.value);
const result = spawnSync("typst", [
"compile",
"--format",
"svg",
doc,
docOut,
]);
2024-04-05 15:34:32 +00:00
console.log("OUTPUT", result.stderr.toString());
const svgOut = readFileSync(docOut);
node.type = "html";
node.value = `
<div class="svg">
${svgOut.toString()}
</div>
`;
2024-04-05 15:34:32 +00:00
},
);
};
};
export default remarkTypst;