Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
quarto-dev
GitHub Repository: quarto-dev/quarto-cli
Path: blob/main/src/resources/tools/ast-diagram/main.ts
12922 views
1
#!/usr/bin/env -S deno run --allow-read --allow-write --allow-run
2
3
import { join } from "https://deno.land/std/path/mod.ts";
4
import { renderPandocAstToBlockDiagram } from "./ast-diagram.ts";
5
import { PandocAST } from "./types.ts";
6
7
/**
8
* Convert a markdown file to an HTML block diagram
9
*/
10
async function renderMarkdownToBlockDiagram(
11
markdownFile: string,
12
outputFile: string,
13
mode = "block",
14
) {
15
console.log(`Processing ${markdownFile}...`);
16
17
try {
18
// Read the markdown file content
19
console.log("Reading markdown source file...");
20
// Read the CSS file
21
const scriptDir = new URL(".", import.meta.url).pathname;
22
const cssPath = join(scriptDir, "style.css");
23
const cssContent = await Deno.readTextFile(cssPath);
24
25
// Run pandoc to convert markdown to JSON
26
console.log("Running pandoc to convert to JSON...");
27
const command = new Deno.Command("quarto", {
28
args: ["pandoc", "-t", "json", markdownFile],
29
stdout: "piped",
30
});
31
32
const { code, stdout } = await command.output();
33
if (code !== 0) {
34
throw new Error(`Pandoc command failed with exit code ${code}`);
35
}
36
37
const jsonOutput = new TextDecoder().decode(stdout);
38
39
// Parse the JSON
40
console.log("Parsing Pandoc JSON...");
41
const pandocAst = JSON.parse(jsonOutput) as PandocAST;
42
const fullHtml = renderPandocAstToBlockDiagram(pandocAst, cssContent, mode);
43
44
// Write the result to the output file
45
console.log(`Writing output to ${outputFile}...`);
46
await Deno.writeTextFile(outputFile, fullHtml);
47
48
console.log("Done!");
49
return true;
50
} catch (err) {
51
// deno-lint-ignore no-explicit-any
52
console.error("Error:", (err as unknown as any).message);
53
return false;
54
}
55
}
56
57
// Check if script is run directly
58
if (import.meta.main) {
59
// Get markdown file from command line arguments
60
const args = Deno.args;
61
62
// Check for --mode flag and its value
63
let mode = "block";
64
const modeIndex = args.indexOf("--mode");
65
if (modeIndex !== -1 && modeIndex + 1 < args.length) {
66
const modeValue = args[modeIndex + 1];
67
if (
68
modeValue === "block" || modeValue === "inline" || modeValue === "full"
69
) {
70
mode = modeValue;
71
} else {
72
console.error(
73
"Invalid mode value. Must be 'block', 'inline', or 'full'.",
74
);
75
Deno.exit(1);
76
}
77
}
78
79
// Backwards compatibility for --verbose flag
80
const verboseIndex = args.indexOf("--verbose");
81
if (verboseIndex !== -1) {
82
mode = "inline";
83
}
84
85
// Remove the --mode flag and its value, or --verbose flag for the rest of argument processing
86
const cleanedArgs = [...args];
87
if (modeIndex !== -1) {
88
cleanedArgs.splice(modeIndex, 2); // Remove both flag and value
89
} else if (verboseIndex !== -1) {
90
cleanedArgs.splice(verboseIndex, 1); // Remove just the flag
91
}
92
93
if (cleanedArgs.length < 1) {
94
console.log(
95
"Usage: main.ts [--mode <block|inline|full>] <markdown-file> [output-html-file]",
96
);
97
console.log("Options:");
98
console.log(
99
" --mode block|inline|full Rendering mode: 'block' (default), 'inline' (detailed AST), or 'full' (all nodes)",
100
);
101
console.log(
102
" --verbose (Legacy) Equivalent to --mode inline",
103
);
104
console.log(
105
"\nIf output file is not specified, it will use the input filename with .html extension",
106
);
107
Deno.exit(1);
108
}
109
110
const markdownFile = cleanedArgs[0];
111
let outputFile = cleanedArgs[1];
112
113
if (!outputFile) {
114
// Default output file is input file with .html extension
115
outputFile = markdownFile.replace(/\.[^\.]+$/, "") + ".html";
116
}
117
118
renderMarkdownToBlockDiagram(markdownFile, outputFile, mode);
119
}
120
121