@hpcc-js/wasm-graphviz-cli
Version:
hpcc-js - WASM Graphviz Cli
180 lines (172 loc) • 5.06 kB
JavaScript
// src/main.ts
import fs from "fs";
import { Graphviz } from "@hpcc-js/wasm-graphviz";
// src/cliArgs.ts
var HELP_TEXT = `Usage: dot-wasm [options] fileOrDot
Options:
-K, --layout <engine> Set layout engine (circo | dot | fdp | sfdp | neato |
osage | patchwork | twopi | nop | nop2). Default: dot
-T, --format <format> Set output format (svg | dot | json | dot_json |
xdot_json | plain | plain-ext). Default: svg
-n, --neato-no-op <flag> Set neato no-op flag (only valid with -K neato)
-y, --invert-y Invert Y axis in plain/plain-ext formats
-v Echo GraphViz version
-h, --help Show this help message
Examples:
dot-wasm -K neato -T xdot ./input.dot
https://github.com/hpcc-systems/hpcc-js-wasm`;
function parseArgs(args) {
const parsed = {
positional: []
};
const readValue = (flag, index) => {
if (index >= args.length) {
throw new Error(`${flag} option requires a value.`);
}
return args[index];
};
for (let i = 0; i < args.length; ++i) {
const token = args[i];
if (token === "--") {
parsed.positional.push(...args.slice(i + 1));
break;
}
if (token.startsWith("--")) {
const [rawName, maybeValue] = token.slice(2).split("=", 2);
i = handleOption(parsed, rawName, maybeValue ?? null, i, readValue);
continue;
}
if (token.startsWith("-") && token.length > 1) {
i = handleShortFlags(parsed, token.slice(1), i, readValue);
continue;
}
parsed.positional.push(token);
}
return parsed;
}
function handleOption(parsed, name, value, currentIndex, readValue) {
switch (name) {
case "layout":
parsed.layout = value ?? readValue("--layout", ++currentIndex);
return currentIndex;
case "format":
parsed.format = value ?? readValue("--format", ++currentIndex);
return currentIndex;
case "neato-no-op":
parsed.neatoNoOp = value ?? readValue("--neato-no-op", ++currentIndex);
return currentIndex;
case "invert-y":
parsed.invertY = true;
return currentIndex;
case "help":
parsed.help = true;
return currentIndex;
case "version":
parsed.version = true;
return currentIndex;
default:
throw new Error(`Unknown option --${name}`);
}
}
function handleShortFlags(parsed, flags, currentIndex, readValue) {
for (let j = 0; j < flags.length; ++j) {
const flag = flags[j];
switch (flag) {
case "K": {
const remaining = flags.slice(j + 1);
if (remaining) {
parsed.layout = remaining;
return currentIndex;
}
parsed.layout = readValue("-K", ++currentIndex);
return currentIndex;
}
case "T": {
const remaining = flags.slice(j + 1);
if (remaining) {
parsed.format = remaining;
return currentIndex;
}
parsed.format = readValue("-T", ++currentIndex);
return currentIndex;
}
case "n": {
const remaining = flags.slice(j + 1);
if (remaining) {
parsed.neatoNoOp = remaining;
return currentIndex;
}
parsed.neatoNoOp = readValue("-n", ++currentIndex);
return currentIndex;
}
case "y":
parsed.invertY = true;
break;
case "v":
parsed.version = true;
break;
case "h":
parsed.help = true;
break;
default:
throw new Error(`Unknown option -${flag}`);
}
}
return currentIndex;
}
// src/main.ts
async function main() {
try {
const parsed = parseArgs(process.argv.slice(2));
if (parsed.help) {
console.log(HELP_TEXT);
return;
}
if (parsed.positional.length > 1) {
throw new Error("Only one 'fileOrDot' argument is allowed.");
}
let dot;
const fileOrDot = parsed.positional[0];
if (fileOrDot) {
if (fs.existsSync(fileOrDot)) {
dot = fs.readFileSync(fileOrDot, "utf8");
} else {
dot = fileOrDot;
}
}
const graphviz = await Graphviz.load();
if (parsed.version) {
console.log(`GraphViz version: ${graphviz.version()}`);
return;
}
if (dot) {
const layout = (parsed.layout ?? "dot").trim();
const format = (parsed.format ?? "svg").trim();
if (parsed.neatoNoOp && layout !== "neato") {
throw new Error("-n option is only supported with -K neato");
}
const ext = {};
if (parsed.neatoNoOp) {
ext.nop = parseInt(parsed.neatoNoOp, 10);
}
if (parsed.invertY) {
ext.yInvert = true;
}
const response = graphviz.layout(dot, format, layout, ext);
console.log(response);
} else {
throw new Error("'fileOrDot' is required.");
}
} catch (e) {
console.error(`Error: ${e?.message}
`);
console.error(HELP_TEXT);
}
}
// src/index.ts
await main();
export {
main
};
//# sourceMappingURL=index.js.map