优化后端
This commit is contained in:
+11
@@ -0,0 +1,11 @@
|
||||
# Viz.js
|
||||
|
||||
This project builds [Graphviz](http://www.graphviz.org) with [Emscripten](https://emscripten.org) and provides a simple wrapper for using it on the web.
|
||||
|
||||
## Install
|
||||
|
||||
Viz.js is published on NPM as [`@viz-js/viz`](https://www.npmjs.com/package/@viz-js/viz).
|
||||
|
||||
## API
|
||||
|
||||
[API Reference](https://viz-js.com/api/#viz)
|
||||
+9
File diff suppressed because one or more lines are too long
+373
File diff suppressed because one or more lines are too long
+367
File diff suppressed because one or more lines are too long
+16
File diff suppressed because one or more lines are too long
+3
@@ -0,0 +1,3 @@
|
||||
export const graphvizVersion = "14.1.3";
|
||||
export const formats = ["canon","cmap","cmapx","cmapx_np","dot","dot_json","eps","fig","gv","imap","imap_np","ismap","json","json0","pic","plain","plain-ext","pov","ps","ps2","svg","svg_inline","tk","xdot","xdot1.2","xdot1.4","xdot_json"];
|
||||
export const engines = ["circo","dot","fdp","neato","nop","nop1","nop2","osage","patchwork","sfdp","twopi"];
|
||||
+2154
File diff suppressed because it is too large
Load Diff
+44
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "@viz-js/viz",
|
||||
"description": "WebAssembly build of Graphviz with a simple wrapper for using it on the web",
|
||||
"keywords": [
|
||||
"graphviz",
|
||||
"emscripten"
|
||||
],
|
||||
"version": "3.25.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/mdaines/viz-js.git",
|
||||
"directory": "packages/viz"
|
||||
},
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"main": "./dist/viz.js",
|
||||
"types": "./types/index.d.ts",
|
||||
"exports": {
|
||||
"types": "./types/index.d.ts",
|
||||
"require": "./dist/viz.cjs",
|
||||
"default": "./dist/viz.js"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"lib",
|
||||
"src",
|
||||
"types"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.29.0",
|
||||
"@babel/preset-env": "^7.29.0",
|
||||
"@rollup/plugin-babel": "^6.1.0",
|
||||
"@rollup/plugin-terser": "^0.4.4",
|
||||
"jsdom": "^21.1.2",
|
||||
"mocha": "^11.7.5",
|
||||
"rollup": "^3.30.0",
|
||||
"typedoc": "^0.28.17",
|
||||
"typedoc-plugin-mdn-links": "^5.1.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha",
|
||||
"docs": "typedoc types/index.d.ts"
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
const errorPatterns = [
|
||||
[/^Error: (.*)/, "error"],
|
||||
[/^Warning: (.*)/, "warning"]
|
||||
];
|
||||
|
||||
export function parseStderrMessages(messages) {
|
||||
return messages.map(message => {
|
||||
for (let i = 0; i < errorPatterns.length; i++) {
|
||||
const [pattern, level] = errorPatterns[i];
|
||||
|
||||
let match;
|
||||
|
||||
if ((match = pattern.exec(message)) !== null) {
|
||||
return { message: match[1].trimEnd(), level };
|
||||
}
|
||||
}
|
||||
|
||||
return { message: message.trimEnd() };
|
||||
});
|
||||
}
|
||||
|
||||
export function parseAgerrMessages(messages) {
|
||||
const result = [];
|
||||
let level = undefined;
|
||||
|
||||
for (let i = 0; i < messages.length; i++) {
|
||||
if (messages[i] == "Error" && messages[i+1] == ": ") {
|
||||
level = "error";
|
||||
i += 1;
|
||||
} else if (messages[i] == "Warning" && messages[i+1] == ": ") {
|
||||
level = "warning";
|
||||
i += 1;
|
||||
} else {
|
||||
result.push({ message: messages[i].trimEnd(), level });
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import Module from "../lib/backend.js";
|
||||
import Viz from "./viz.js";
|
||||
|
||||
export { graphvizVersion, formats, engines } from "../lib/metadata.js";
|
||||
|
||||
export function instance() {
|
||||
return Module().then(m => new Viz(m));
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
import { getGraphvizVersion, getPluginList, renderInput } from "./wrapper.js";
|
||||
|
||||
class Viz {
|
||||
constructor(module) {
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
get graphvizVersion() {
|
||||
return getGraphvizVersion(this.module);
|
||||
}
|
||||
|
||||
get formats() {
|
||||
return getPluginList(this.module, "device");
|
||||
}
|
||||
|
||||
get engines() {
|
||||
return getPluginList(this.module, "layout");
|
||||
}
|
||||
|
||||
renderFormats(input, formats, options = {}) {
|
||||
return renderInput(this.module, input, formats, { engine: "dot", ...options });
|
||||
}
|
||||
|
||||
render(input, options = {}) {
|
||||
let format;
|
||||
|
||||
if (options.format === void 0) {
|
||||
format = "dot";
|
||||
} else {
|
||||
format = options.format;
|
||||
}
|
||||
|
||||
let result = renderInput(this.module, input, [format], { engine: "dot", ...options });
|
||||
|
||||
if (result.status === "success") {
|
||||
result.output = result.output[format];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
renderString(src, options = {}) {
|
||||
const result = this.render(src, options);
|
||||
|
||||
if (result.status !== "success") {
|
||||
throw new Error(result.errors.find(e => e.level == "error")?.message || "render failed");
|
||||
}
|
||||
|
||||
return result.output;
|
||||
}
|
||||
|
||||
renderSVGElement(src, options = {}) {
|
||||
const str = this.renderString(src, { ...options, format: "svg" });
|
||||
|
||||
let input;
|
||||
|
||||
if (typeof options.trustedTypePolicy !== "undefined") {
|
||||
input = options.trustedTypePolicy.createHTML(str);
|
||||
} else {
|
||||
input = str;
|
||||
}
|
||||
|
||||
const parser = new DOMParser();
|
||||
return parser.parseFromString(input, "image/svg+xml").documentElement;
|
||||
}
|
||||
|
||||
renderJSON(src, options = {}) {
|
||||
const str = this.renderString(src, { ...options, format: "json" });
|
||||
return JSON.parse(str);
|
||||
}
|
||||
}
|
||||
|
||||
export default Viz;
|
||||
+291
@@ -0,0 +1,291 @@
|
||||
import { parseStderrMessages, parseAgerrMessages } from "./errors.js";
|
||||
|
||||
export function getGraphvizVersion(module) {
|
||||
const resultPointer = module.ccall("viz_get_graphviz_version", "number", [], []);
|
||||
return module.UTF8ToString(resultPointer);
|
||||
}
|
||||
|
||||
export function getPluginList(module, kind) {
|
||||
const resultPointer = module.ccall("viz_get_plugin_list", "number", ["string"], [kind]);
|
||||
|
||||
if (resultPointer == 0) {
|
||||
throw new Error(`couldn't get plugin list: ${kind}`);
|
||||
}
|
||||
|
||||
const list = [];
|
||||
let itemPointer = resultPointer;
|
||||
let stringPointer;
|
||||
|
||||
while (stringPointer = module.getValue(itemPointer, "*")) {
|
||||
list.push(module.UTF8ToString(stringPointer));
|
||||
module.ccall("free", "number", ["number"], [stringPointer]);
|
||||
itemPointer += 4;
|
||||
}
|
||||
|
||||
module.ccall("free", "number", ["number"], [resultPointer]);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
export function renderInput(module, input, formats, options) {
|
||||
let graphPointer, contextPointer, resultPointer, imageFilePaths;
|
||||
|
||||
try {
|
||||
module["agerrMessages"] = [];
|
||||
module["stderrMessages"] = [];
|
||||
|
||||
imageFilePaths = createImageFiles(module, options.images);
|
||||
|
||||
if (typeof input === "string") {
|
||||
graphPointer = readStringInput(module, input, options);
|
||||
} else if (typeof input === "object") {
|
||||
graphPointer = readObjectInput(module, input, options);
|
||||
} else {
|
||||
throw new Error("input must be a string or object");
|
||||
}
|
||||
|
||||
if (graphPointer === 0) {
|
||||
return {
|
||||
status: "failure",
|
||||
output: undefined,
|
||||
errors: parseErrorMessages(module)
|
||||
};
|
||||
}
|
||||
|
||||
setDefaultAttributes(module, graphPointer, options);
|
||||
|
||||
module.ccall("viz_set_y_invert", "number", ["number"], [options.yInvert ? 1 : 0]);
|
||||
module.ccall("viz_set_reduce", "number", ["number"], [options.reduce ? 1 : 0]);
|
||||
|
||||
contextPointer = module.ccall("viz_create_context");
|
||||
|
||||
module.ccall("viz_reset_errors");
|
||||
|
||||
let layoutError = module.ccall("viz_layout", "number", ["number", "number", "string"], [contextPointer, graphPointer, options.engine]);
|
||||
|
||||
if (layoutError !== 0) {
|
||||
return {
|
||||
status: "failure",
|
||||
output: undefined,
|
||||
errors: parseErrorMessages(module)
|
||||
};
|
||||
}
|
||||
|
||||
let output = {};
|
||||
|
||||
for (let format of formats) {
|
||||
resultPointer = module.ccall("viz_render", "number", ["number", "number", "string"], [contextPointer, graphPointer, format]);
|
||||
|
||||
if (resultPointer === 0) {
|
||||
return {
|
||||
status: "failure",
|
||||
output: undefined,
|
||||
errors: parseErrorMessages(module)
|
||||
};
|
||||
} else {
|
||||
output[format] = module.UTF8ToString(resultPointer);
|
||||
|
||||
module.ccall("free", "number", ["number"], [resultPointer]);
|
||||
resultPointer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
status: "success",
|
||||
output: output,
|
||||
errors: parseErrorMessages(module)
|
||||
};
|
||||
} catch (error) {
|
||||
if (/^exit\(\d+\)/.test(error)) {
|
||||
return {
|
||||
status: "failure",
|
||||
output: undefined,
|
||||
errors: parseErrorMessages(module)
|
||||
};
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
} finally {
|
||||
if (contextPointer && graphPointer) {
|
||||
module.ccall("viz_free_layout", "number", ["number"], [contextPointer, graphPointer]);
|
||||
}
|
||||
|
||||
if (graphPointer) {
|
||||
module.ccall("viz_free_graph", "number", ["number"], [graphPointer]);
|
||||
}
|
||||
|
||||
if (contextPointer) {
|
||||
module.ccall("viz_free_context", "number", ["number"], [contextPointer]);
|
||||
}
|
||||
|
||||
if (resultPointer) {
|
||||
module.ccall("free", "number", ["number"], [resultPointer]);
|
||||
}
|
||||
|
||||
if (imageFilePaths) {
|
||||
removeImageFiles(module, imageFilePaths);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function parseErrorMessages(module) {
|
||||
return parseAgerrMessages(module["agerrMessages"]).concat(parseStderrMessages(module["stderrMessages"]));
|
||||
}
|
||||
|
||||
function createImageFiles(module, images) {
|
||||
if (!images) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return images.map(image => {
|
||||
if (typeof image.name !== "string") {
|
||||
throw new Error("image name must be a string");
|
||||
} else if (typeof image.width !== "number" && typeof image.width !== "string") {
|
||||
throw new Error("image width must be a number or string");
|
||||
} else if (typeof image.height !== "number" && typeof image.height !== "string") {
|
||||
throw new Error("image height must be a number or string");
|
||||
}
|
||||
|
||||
const path = module.PATH.join("/", image.name);
|
||||
const data = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="${image.width}" height="${image.height}"></svg>
|
||||
`;
|
||||
|
||||
module.FS.createPath("/", module.PATH.dirname(path));
|
||||
module.FS.writeFile(path, data);
|
||||
|
||||
return path;
|
||||
});
|
||||
}
|
||||
|
||||
function removeImageFiles(module, imageFilePaths) {
|
||||
for (const path of imageFilePaths) {
|
||||
if (module.FS.analyzePath(path).exists) {
|
||||
module.FS.unlink(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function readStringInput(module, src, options) {
|
||||
let srcPointer;
|
||||
|
||||
try {
|
||||
const srcLength = module.lengthBytesUTF8(src);
|
||||
srcPointer = module.ccall("malloc", "number", ["number"], [srcLength + 1]);
|
||||
module.stringToUTF8(src, srcPointer, srcLength + 1);
|
||||
|
||||
return module.ccall("viz_read_one_graph", "number", ["number"], [srcPointer]);
|
||||
} finally {
|
||||
if (srcPointer) {
|
||||
module.ccall("free", "number", ["number"], [srcPointer]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function readObjectInput(module, object, options) {
|
||||
const graphPointer = module.ccall("viz_create_graph", "number", ["string", "number", "number"], [object.name, typeof object.directed !== "undefined" ? object.directed : true, typeof object.strict !== "undefined" ? object.strict : false]);
|
||||
|
||||
readGraph(module, graphPointer, object);
|
||||
|
||||
return graphPointer;
|
||||
}
|
||||
|
||||
function readGraph(module, graphPointer, graphData) {
|
||||
setDefaultAttributes(module, graphPointer, graphData);
|
||||
|
||||
if (graphData.nodes) {
|
||||
graphData.nodes.forEach(nodeData => {
|
||||
if (typeof nodeData.name === "undefined") {
|
||||
throw new Error("nodes must have a name");
|
||||
}
|
||||
|
||||
const nodePointer = module.ccall("viz_add_node", "number", ["number", "string"], [graphPointer, String(nodeData.name)]);
|
||||
|
||||
if (nodeData.attributes) {
|
||||
setAttributes(module, graphPointer, nodePointer, nodeData.attributes);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (graphData.edges) {
|
||||
graphData.edges.forEach(edgeData => {
|
||||
if (typeof edgeData.tail === "undefined") {
|
||||
throw new Error("edges must have a tail");
|
||||
}
|
||||
|
||||
if (typeof edgeData.head === "undefined") {
|
||||
throw new Error("edges must have a head");
|
||||
}
|
||||
|
||||
const edgePointer = module.ccall("viz_add_edge", "number", ["number", "string", "string"], [graphPointer, String(edgeData.tail), String(edgeData.head)]);
|
||||
|
||||
if (edgeData.attributes) {
|
||||
setAttributes(module, graphPointer, edgePointer, edgeData.attributes);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (graphData.subgraphs) {
|
||||
graphData.subgraphs.forEach(subgraphData => {
|
||||
const subgraphPointer = module.ccall("viz_add_subgraph", "number", ["number", "string"], [graphPointer, typeof subgraphData.name !== "undefined" ? String(subgraphData.name) : 0]);
|
||||
|
||||
readGraph(module, subgraphPointer, subgraphData);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function setDefaultAttributes(module, graphPointer, data) {
|
||||
if (data.graphAttributes) {
|
||||
for (const [name, value] of Object.entries(data.graphAttributes)) {
|
||||
withStringPointer(module, graphPointer, value, stringPointer => {
|
||||
module.ccall("viz_set_default_graph_attribute", "number", ["number", "string", "number"], [graphPointer, name, stringPointer]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (data.nodeAttributes) {
|
||||
for (const [name, value] of Object.entries(data.nodeAttributes)) {
|
||||
withStringPointer(module, graphPointer, value, stringPointer => {
|
||||
module.ccall("viz_set_default_node_attribute", "number", ["number", "string", "number"], [graphPointer, name, stringPointer]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (data.edgeAttributes) {
|
||||
for (const [name, value] of Object.entries(data.edgeAttributes)) {
|
||||
withStringPointer(module, graphPointer, value, stringPointer => {
|
||||
module.ccall("viz_set_default_edge_attribute", "number", ["number", "string", "number"], [graphPointer, name, stringPointer]);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setAttributes(module, graphPointer, objectPointer, attributes) {
|
||||
for (const [key, value] of Object.entries(attributes)) {
|
||||
withStringPointer(module, graphPointer, value, stringPointer => {
|
||||
module.ccall("viz_set_attribute", "number", ["number", "string", "number"], [objectPointer, key, stringPointer]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function withStringPointer(module, graphPointer, value, callbackFn) {
|
||||
let stringPointer;
|
||||
|
||||
if (typeof value === "object" && "html" in value) {
|
||||
stringPointer = module.ccall("viz_string_dup_html", "number", ["number", "string"], [graphPointer, String(value.html)]);
|
||||
} else {
|
||||
stringPointer = module.ccall("viz_string_dup", "number", ["number", "string"], [graphPointer, String(value)]);
|
||||
}
|
||||
|
||||
if (stringPointer == 0) {
|
||||
throw new Error("couldn't dup string");
|
||||
}
|
||||
|
||||
callbackFn(stringPointer);
|
||||
|
||||
if (typeof value === "object" && "html" in value) {
|
||||
module.ccall("viz_string_free_html", "number", ["number", "number"], [graphPointer, stringPointer]);
|
||||
} else {
|
||||
module.ccall("viz_string_free", "number", ["number", "number"], [graphPointer, stringPointer]);
|
||||
}
|
||||
}
|
||||
+366
@@ -0,0 +1,366 @@
|
||||
export {}
|
||||
|
||||
/**
|
||||
* The version of Graphviz used for this build.
|
||||
*/
|
||||
export const graphvizVersion: string
|
||||
|
||||
/**
|
||||
* The names of the {@link https://www.graphviz.org/docs/outputs/ | Graphviz output formats} supported in this build.
|
||||
*/
|
||||
export const formats: string[]
|
||||
|
||||
/**
|
||||
* The names of the {@link https://www.graphviz.org/docs/layouts/ | Graphviz layout engines} supported in this build.
|
||||
*/
|
||||
export const engines: string[]
|
||||
|
||||
/**
|
||||
* Returns a promise that resolves to an instance of the {@link Viz} class.
|
||||
*/
|
||||
export function instance(): Promise<Viz>
|
||||
|
||||
/**
|
||||
* The {@link Viz} class isn't exported, but it can be instantiated using the {@link instance} function.
|
||||
*/
|
||||
declare class Viz {
|
||||
/**
|
||||
* The version of Graphviz at runtime.
|
||||
*/
|
||||
get graphvizVersion(): string
|
||||
|
||||
/**
|
||||
* The names of the {@link https://www.graphviz.org/docs/outputs/ | Graphviz output formats} supported at runtime.
|
||||
*/
|
||||
get formats(): string[]
|
||||
|
||||
/**
|
||||
* The names of the {@link https://www.graphviz.org/docs/layouts/ | Graphviz layout engines} supported at runtime.
|
||||
*/
|
||||
get engines(): string[]
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
constructor()
|
||||
|
||||
/**
|
||||
* Renders the graph described by the input and returns the result as an object.
|
||||
*
|
||||
* `input` may be a string in {@link https://www.graphviz.org/doc/info/lang.html | DOT syntax} or a {@link Graph | graph object}.
|
||||
*
|
||||
* This method does not throw an error if rendering failed, including for invalid DOT syntax, but it will throw for invalid types in input or unexpected runtime errors.
|
||||
*/
|
||||
render(input: string | Graph, options?: RenderOptions): RenderResult
|
||||
|
||||
/**
|
||||
* Renders the graph described by the input for each format in `formats` and returns the result as an object. For a successful result, `output` is an object keyed by format.
|
||||
*/
|
||||
renderFormats(input: string | Graph, formats: string[], options?: RenderOptions): MultipleRenderResult
|
||||
|
||||
/**
|
||||
* Renders the input and returns the result as a string. Throws an error if rendering failed.
|
||||
*/
|
||||
renderString(input: string | Graph, options?: RenderOptions): string
|
||||
|
||||
/**
|
||||
* Convenience method that renders the input, parses the output, and returns an SVG element. The `format` option is ignored. Throws an error if rendering failed.
|
||||
*/
|
||||
renderSVGElement(input: string | Graph, options?: SVGRenderOptions): SVGSVGElement
|
||||
|
||||
/**
|
||||
* Convenience method that renders the input, parses the output, and returns a JSON object. The `format` option is ignored. Throws an error if rendering failed.
|
||||
*/
|
||||
renderJSON(input: string | Graph, options?: RenderOptions): object
|
||||
}
|
||||
|
||||
export { type Viz }
|
||||
|
||||
/**
|
||||
* @property format
|
||||
* The {@link https://www.graphviz.org/docs/outputs/ | Graphviz output format} to render. For example, `"dot"` or `"svg"`.
|
||||
*
|
||||
* @property engine
|
||||
* The {@link https://www.graphviz.org/docs/layouts/ | Graphviz layout engine} to use for graph layout. For example, `"dot"` or `"neato"`.
|
||||
*
|
||||
* @property yInvert
|
||||
* Invert y coordinates in output. This corresponds to the {@link https://www.graphviz.org/doc/info/command.html#-y | `-y`} Graphviz command-line option</a>.
|
||||
*
|
||||
* @property reduce
|
||||
* Reduce the graph. This corresponds to the {@link https://www.graphviz.org/doc/info/command.html#-x | `-x`} Graphviz command-line option</a>.
|
||||
*
|
||||
* @property graphAttributes
|
||||
* Sets the default graph attributes. This corresponds the {@link https://www.graphviz.org/doc/info/command.html#-G | `-G`} Graphviz command-line option</a>.
|
||||
*
|
||||
* @property nodeAttributes
|
||||
* Sets the default node attributes. This corresponds the {@link https://www.graphviz.org/doc/info/command.html#-N `-N`} Graphviz command-line option</a>.
|
||||
*
|
||||
* @property edgeAttributes
|
||||
* Sets the default edge attributes. This corresponds the {@link https://www.graphviz.org/doc/info/command.html#-E | `-E`} Graphviz command-line option</a>.
|
||||
*
|
||||
* @property images
|
||||
* Image sizes to use when rendering nodes with <code>image</code> attributes.
|
||||
*
|
||||
* For example, to indicate to Graphviz that the image <code>test.png</code> has size 300x200:
|
||||
*
|
||||
* ```js
|
||||
* viz.render("graph { a[image=\"test.png\"] }", {
|
||||
* images: [
|
||||
* { name: "test.png", width: 300, height: 200 }
|
||||
* ]
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export interface RenderOptions {
|
||||
format?: string
|
||||
engine?: string
|
||||
yInvert?: boolean
|
||||
reduce?: boolean
|
||||
graphAttributes?: Attributes
|
||||
nodeAttributes?: Attributes
|
||||
edgeAttributes?: Attributes
|
||||
images?: ImageSize[]
|
||||
}
|
||||
|
||||
/**
|
||||
* @property engine
|
||||
* The {@link https://www.graphviz.org/docs/layouts/ | Graphviz layout engine} to use for graph layout. For example, `"dot"` or `"neato"`.
|
||||
*
|
||||
* @property yInvert
|
||||
* Invert y coordinates in output. This corresponds to the {@link https://www.graphviz.org/doc/info/command.html#-y | `-y`} Graphviz command-line option</a>.
|
||||
*
|
||||
* @property reduce
|
||||
* Reduce the graph. This corresponds to the {@link https://www.graphviz.org/doc/info/command.html#-x | `-x`} Graphviz command-line option</a>.
|
||||
*
|
||||
* @property graphAttributes
|
||||
* Sets the default graph attributes. This corresponds the {@link https://www.graphviz.org/doc/info/command.html#-G | `-G`} Graphviz command-line option</a>.
|
||||
*
|
||||
* @property nodeAttributes
|
||||
* Sets the default node attributes. This corresponds the {@link https://www.graphviz.org/doc/info/command.html#-N `-N`} Graphviz command-line option</a>.
|
||||
*
|
||||
* @property edgeAttributes
|
||||
* Sets the default edge attributes. This corresponds the {@link https://www.graphviz.org/doc/info/command.html#-E | `-E`} Graphviz command-line option</a>.
|
||||
*
|
||||
* @property images
|
||||
* Image sizes to use when rendering nodes with <code>image</code> attributes.
|
||||
*
|
||||
* For example, to indicate to Graphviz that the image <code>test.png</code> has size 300x200:
|
||||
*
|
||||
* ```js
|
||||
* viz.render("graph { a[image=\"test.png\"] }", {
|
||||
* images: [
|
||||
* { name: "test.png", width: 300, height: 200 }
|
||||
* ]
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @property trustedTypePolicy
|
||||
* The {@link https://developer.mozilla.org/en-US/docs/Web/API/TrustedTypePolicy | TrustedTypePolicy} object used to sanitize the rendered SVG string before parsing.
|
||||
*/
|
||||
export interface SVGRenderOptions {
|
||||
engine?: string
|
||||
yInvert?: boolean
|
||||
reduce?: boolean
|
||||
graphAttributes?: Attributes
|
||||
nodeAttributes?: Attributes
|
||||
edgeAttributes?: Attributes
|
||||
images?: ImageSize[]
|
||||
trustedTypePolicy?: object
|
||||
}
|
||||
|
||||
/**
|
||||
* The result object returned by {@link Viz.render}.
|
||||
*/
|
||||
export type RenderResult = SuccessResult | FailureResult
|
||||
|
||||
/**
|
||||
* Returned by {@link Viz.render} if rendering was successful. `errors` may contain warning messages even if the graph rendered successfully.
|
||||
*/
|
||||
export interface SuccessResult {
|
||||
status: "success"
|
||||
output: string
|
||||
errors: RenderError[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Returned by {@link Viz.render} or {@link Viz.renderFormats} if rendering failed.
|
||||
*/
|
||||
export interface FailureResult {
|
||||
status: "failure"
|
||||
output: undefined
|
||||
errors: RenderError[]
|
||||
}
|
||||
|
||||
/**
|
||||
* The result object returned by {@link Viz.renderFormats}.
|
||||
*/
|
||||
export type MultipleRenderResult = MultipleSuccessResult | FailureResult
|
||||
|
||||
/**
|
||||
* Returned by {@link Viz.renderFormats} if rendering was successful. `errors` may contain warning messages even if the graph rendered successfully.
|
||||
*/
|
||||
export interface MultipleSuccessResult {
|
||||
status: "success"
|
||||
output: { [format: string]: string }
|
||||
errors: RenderError[]
|
||||
}
|
||||
|
||||
export interface RenderError {
|
||||
level?: "error" | "warning"
|
||||
message: string
|
||||
}
|
||||
|
||||
/**
|
||||
* In addition to strings in {@link https://www.graphviz.org/doc/info/lang.html | DOT syntax}, {@link Viz.render | rendering methods} accept <i>graph objects</i>.
|
||||
*
|
||||
* Graph objects are plain JavaScript objects, similar to {@link https://jsongraphformat.info | JSON Graph} or {@link https://github.com/dagrejs/graphlib/wiki/API-Reference#json-write | the Dagre JSON serialization}, but are specifically designed for working with Graphviz. Because of that, they use terminology from the Graphviz API (edges have a "head" and "tail", and nodes are identified with "name") and support features such as subgraphs, HTML labels, and default attributes.
|
||||
*
|
||||
* Some example graph objects and the corresponding graph in DOT:
|
||||
*
|
||||
* ## Empty directed graph
|
||||
*
|
||||
* ```json
|
||||
* {}
|
||||
* ```
|
||||
*
|
||||
* ```
|
||||
* digraph { }
|
||||
* ```
|
||||
*
|
||||
* ## Simple Undirected Graph
|
||||
*
|
||||
* ```json
|
||||
* {
|
||||
* directed: false,
|
||||
* edges: [
|
||||
* { tail: "a", head: "b" },
|
||||
* { tail: "b", head: "c" },
|
||||
* { tail: "c", head: "a" }
|
||||
* ]
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* ```
|
||||
* graph {
|
||||
* a -- b
|
||||
* b -- c
|
||||
* c -- a
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* ## Attributes, Subgraphs, HTML Labels
|
||||
*
|
||||
* ```json
|
||||
* {
|
||||
* graphAttributes: {
|
||||
* rankdir: "LR"
|
||||
* },
|
||||
* nodeAttributes: {
|
||||
* shape: "circle"
|
||||
* },
|
||||
* nodes: [
|
||||
* { name: "a", attributes: { label: { html: "<i>A</i>" }, color: "red" } },
|
||||
* { name: "b", attributes: { label: { html: "<b>A</b>" }, color: "green" } }
|
||||
* ],
|
||||
* edges: [
|
||||
* { tail: "a", head: "b", attributes: { label: "1" } },
|
||||
* { tail: "b", head: "c", attributes: { label: "2", headport: "name" } }
|
||||
* ],
|
||||
* subgraphs: [
|
||||
* {
|
||||
* name: "cluster_1",
|
||||
* nodes: [
|
||||
* {
|
||||
* name: "c",
|
||||
* attributes: {
|
||||
* label: {
|
||||
* html: "<table><tr><td>test</td><td port=\"name\">C</td></tr></table>"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ]
|
||||
* }
|
||||
* ]
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* ```
|
||||
* digraph {
|
||||
* graph [rankdir="LR"]
|
||||
* node [shape="circle"]
|
||||
* a [label=<<i>A</i>>, color="red"]
|
||||
* b [label=<<b>B</b>>, color="green"]
|
||||
* a -> b [label="1"]
|
||||
* b -> c:name [label="2"]
|
||||
* subgraph cluster_1 {
|
||||
* c [label=<<table><tr><td port="name">C</td></tr></table>>]
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export interface Graph {
|
||||
name?: string
|
||||
strict?: boolean
|
||||
directed?: boolean
|
||||
graphAttributes?: Attributes
|
||||
nodeAttributes?: Attributes
|
||||
edgeAttributes?: Attributes
|
||||
nodes?: Node[]
|
||||
edges?: Edge[]
|
||||
subgraphs?: Subgraph[]
|
||||
}
|
||||
|
||||
export interface Attributes {
|
||||
[name: string]: string | number | boolean | HTMLString
|
||||
}
|
||||
|
||||
export interface HTMLString {
|
||||
html: string
|
||||
}
|
||||
|
||||
export interface Node {
|
||||
name: string
|
||||
attributes?: Attributes
|
||||
}
|
||||
|
||||
export interface Edge {
|
||||
tail: string
|
||||
head: string
|
||||
attributes?: Attributes
|
||||
}
|
||||
|
||||
export interface Subgraph {
|
||||
name?: string
|
||||
graphAttributes?: Attributes
|
||||
nodeAttributes?: Attributes
|
||||
edgeAttributes?: Attributes
|
||||
nodes?: Node[]
|
||||
edges?: Edge[]
|
||||
subgraphs?: Subgraph[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the size of an image used as a node's `image` attribute. See {@link RenderOptions.images}.
|
||||
*
|
||||
* `width` and `height` may be specified as numbers or strings with units: in, px, pc, pt, cm, or mm. If no units are given or measurements are given as numbers, points (pt) are used.
|
||||
*
|
||||
* @property name
|
||||
* The name of the image. In addition to filenames, names that look like absolute filesystem paths or URLs can be used. For example:
|
||||
*
|
||||
* - `"example.png"`
|
||||
* - `"/images/example.png"`
|
||||
* - `"http://example.com/image.png"`
|
||||
*
|
||||
* Names that look like relative filesystem paths, such as `"../example.png"`, are not supported.
|
||||
*
|
||||
* @property width
|
||||
* The width of the image.
|
||||
*
|
||||
* @property height
|
||||
* The height of the image.
|
||||
*/
|
||||
export interface ImageSize {
|
||||
name: string,
|
||||
width: string | number,
|
||||
height: string | number
|
||||
}
|
||||
Reference in New Issue
Block a user