Path: blob/main/src/resources/tools/ast-diagram/main.ts
12922 views
#!/usr/bin/env -S deno run --allow-read --allow-write --allow-run12import { join } from "https://deno.land/std/path/mod.ts";3import { renderPandocAstToBlockDiagram } from "./ast-diagram.ts";4import { PandocAST } from "./types.ts";56/**7* Convert a markdown file to an HTML block diagram8*/9async function renderMarkdownToBlockDiagram(10markdownFile: string,11outputFile: string,12mode = "block",13) {14console.log(`Processing ${markdownFile}...`);1516try {17// Read the markdown file content18console.log("Reading markdown source file...");19// Read the CSS file20const scriptDir = new URL(".", import.meta.url).pathname;21const cssPath = join(scriptDir, "style.css");22const cssContent = await Deno.readTextFile(cssPath);2324// Run pandoc to convert markdown to JSON25console.log("Running pandoc to convert to JSON...");26const command = new Deno.Command("quarto", {27args: ["pandoc", "-t", "json", markdownFile],28stdout: "piped",29});3031const { code, stdout } = await command.output();32if (code !== 0) {33throw new Error(`Pandoc command failed with exit code ${code}`);34}3536const jsonOutput = new TextDecoder().decode(stdout);3738// Parse the JSON39console.log("Parsing Pandoc JSON...");40const pandocAst = JSON.parse(jsonOutput) as PandocAST;41const fullHtml = renderPandocAstToBlockDiagram(pandocAst, cssContent, mode);4243// Write the result to the output file44console.log(`Writing output to ${outputFile}...`);45await Deno.writeTextFile(outputFile, fullHtml);4647console.log("Done!");48return true;49} catch (err) {50// deno-lint-ignore no-explicit-any51console.error("Error:", (err as unknown as any).message);52return false;53}54}5556// Check if script is run directly57if (import.meta.main) {58// Get markdown file from command line arguments59const args = Deno.args;6061// Check for --mode flag and its value62let mode = "block";63const modeIndex = args.indexOf("--mode");64if (modeIndex !== -1 && modeIndex + 1 < args.length) {65const modeValue = args[modeIndex + 1];66if (67modeValue === "block" || modeValue === "inline" || modeValue === "full"68) {69mode = modeValue;70} else {71console.error(72"Invalid mode value. Must be 'block', 'inline', or 'full'.",73);74Deno.exit(1);75}76}7778// Backwards compatibility for --verbose flag79const verboseIndex = args.indexOf("--verbose");80if (verboseIndex !== -1) {81mode = "inline";82}8384// Remove the --mode flag and its value, or --verbose flag for the rest of argument processing85const cleanedArgs = [...args];86if (modeIndex !== -1) {87cleanedArgs.splice(modeIndex, 2); // Remove both flag and value88} else if (verboseIndex !== -1) {89cleanedArgs.splice(verboseIndex, 1); // Remove just the flag90}9192if (cleanedArgs.length < 1) {93console.log(94"Usage: main.ts [--mode <block|inline|full>] <markdown-file> [output-html-file]",95);96console.log("Options:");97console.log(98" --mode block|inline|full Rendering mode: 'block' (default), 'inline' (detailed AST), or 'full' (all nodes)",99);100console.log(101" --verbose (Legacy) Equivalent to --mode inline",102);103console.log(104"\nIf output file is not specified, it will use the input filename with .html extension",105);106Deno.exit(1);107}108109const markdownFile = cleanedArgs[0];110let outputFile = cleanedArgs[1];111112if (!outputFile) {113// Default output file is input file with .html extension114outputFile = markdownFile.replace(/\.[^\.]+$/, "") + ".html";115}116117renderMarkdownToBlockDiagram(markdownFile, outputFile, mode);118}119120121