Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
@aduh95/viz.js
Advanced tools
@aduh95/viz.js is a JavaScript wrapper for Graphviz, a popular open-source graph visualization software. It allows you to create, manipulate, and render graphs using the DOT language directly in JavaScript environments, including Node.js and browsers.
Render DOT to SVG
This feature allows you to render a DOT string into an SVG element. The code sample demonstrates how to create a simple directed graph from node 'a' to node 'b' and append the resulting SVG to the document body.
const viz = new Viz();
viz.renderSVGElement('digraph { a -> b; }')
.then(function(element) {
document.body.appendChild(element);
});
Render DOT to PNG
This feature allows you to render a DOT string into a PNG image element. The code sample shows how to create a simple directed graph and append the resulting PNG image to the document body.
const viz = new Viz();
viz.renderImageElement('digraph { a -> b; }')
.then(function(element) {
document.body.appendChild(element);
});
Render DOT to plain text
This feature allows you to render a DOT string into plain text. The code sample demonstrates how to create a simple directed graph and log the resulting plain text representation to the console.
const viz = new Viz();
viz.renderString('digraph { a -> b; }')
.then(function(result) {
console.log(result);
});
viz.js is another JavaScript wrapper for Graphviz. It is similar to @aduh95/viz.js but is more widely used and has a larger community. It also supports rendering graphs in various formats such as SVG, PNG, and plain text.
d3-graphviz is a D3-based library for rendering Graphviz DOT files. It integrates well with the D3.js ecosystem, allowing for more complex and interactive visualizations. It is more suitable for users who are already familiar with D3.js.
graphviz-cli is a command-line interface for Graphviz. It allows you to render DOT files to various formats using the command line. It is more suitable for users who prefer working with the command line rather than a JavaScript environment.
This project builds Graphviz with Emscripten and provides a simple wrapper for using it in the browser.
Have a look at Dagre, which is not a hack.
@aduh95/viz.js
package from
the npm registry.N.B.: This library has been fully tested with Node.js 12 LTS and Node.js
13.2+. If you need support for older versions of Node.js (E.G.: 10.x), you
should restrict the use of viz.js
to the synchronous API
only.
import Viz from "@aduh95/viz.js";
import getWorker from "@aduh95/viz.js/worker";
const worker = getWorker();
const viz = new Viz({ worker });
viz
.renderString("digraph{1 -> 2 }")
.then((svgString) => {
console.log(svgString);
})
.catch((error) => {
console.error(error);
})
.finally(
() =>
// You can either terminate explicitly:
viz.terminateWorker()
// or let it be auto-closed at the end of the process
);
If you want to use it from a CommonJS script, you can use the
@aduh95/viz.js/async
wrapper shortcut:
const dot2svg = require("@aduh95/viz.js/async");
dot2svg("digraph{1 -> 2 }")
.then((svgString) => {
console.log(svgString);
})
.catch((error) => {
console.error(error);
});
Note: If you want to your lib to be web-ready, it is recommended to build up from the first code example rather than the CommonJS one.
There is a synchronous version of renderString
method available:
const vizRenderStringSync = require("@aduh95/viz.js/sync");
console.log(vizRenderStringSync("digraph{1 -> 2 }"));
Key differences with async API:
WebAssembly
, this should come
with a performance hit and a bigger bundled file size (brotli size is 27%
bigger).Note: Using the sync API on the browser main thread is not recommended, it might degrade the overall user experience of the web page. It is strongly recommended to use web workers – with the sync or the async API.
You can either use the worker
or the workerURL
on the constructor. Note that
when using workerURL
, Viz
constructor will try to spawn a webworker using
type=module
. If you don't want a module worker, you should provide a worker
instead.
The Worker module exports a function that takes
an Emscripten Module object.
You can use that to tweak the defaults, the only requirement is to define a
locateFile
method that returns the URL of the WASM file.
// worker.js
import initWASM from "@aduh95/viz.js/worker";
// If you are not using a bundler that supports package.json#exports
// use "./node_modules/@aduh95/viz.js/dist/render.browser.js" instead.
// You need to configure your bundler to treat `.wasm` file as file to return a URL.
import wasmURL from "@aduh95/viz.js/wasm";
// With Rollup, use the `@rollup/plugin-url` plugin and add `**/*.wasm` to the
// `include` list in the plugin config.
// With Webpack, use the `file-loader` plugin: "file-loader!@aduh95/viz.js/wasm"
// If you are not using a bundler that supports package.json#exports
// or doesn't have a file-loader plugin to get URL of the asset:
// const wasmURL =
// new URL("./node_modules/@aduh95/viz.js/dist/render.wasm", import.meta.url);
initWASM({
locateFile() {
return wasmURL;
},
});
And give feed that module to the main thread:
//main.js
import Viz from "@aduh95/viz.js";
// If you are not using a bundler that supports package.json#exports:
// import Viz from "./node_modules/@aduh95/viz.js/dist/index.mjs";
// If you are using Rollup, use `@surma/rollup-plugin-off-main-thread` plugin.
// If you are using Webpack, use the `worker-loader` plugin and add this import:
// import VizWorker from "worker-loader!./worker.js";
let viz;
async function dot2svg(dot, options) {
if (viz === undefined) {
// No-bundler / auto-bundling version:
viz = new Viz({
worker: new Worker(new URL("./worker.js", import.meta.url), {
type: "module",
}),
});
// or if you are using Webpack:
// viz = new Viz({ worker: new VizWorker() });
}
return viz.renderString(dot, options);
}
If you are using a CDN and don't want a separate file for the worker module, there is a workaround:
import Viz from "https://unpkg.com/@aduh95/viz.js";
const locateFile = (fileName) =>
"https://unpkg.com/@aduh95/viz.js/dist/" + fileName;
const onmessage = async function (event) {
if (this.messageHandler === undefined) {
// Lazy loading actual handler
const { default: init, onmessage } = await import(
Module.locateFile("render.browser.js")
);
// Removing default MessageEvent handler
removeEventListener("message", onmessage);
await init(Module);
this.messageHandler = onmessage;
}
return this.messageHandler(event);
};
const vizOptions = {
workerURL: URL.createObjectURL(
new Blob(
[
"const Module = { locateFile:",
locateFile.toString(),
"};",
"onmessage=",
onmessage.toString(),
],
{ type: "application/javascript" }
)
),
};
async function dot2svg(dot, options) {
const viz = new Viz(vizOptions);
return viz.renderString(dot, options);
}
If you want to support browsers that do not support loading webworker as module, or want a custom message handling, you can use dynamic imports to help you:
// worker.js
/**
* Lazy-loads Viz.js message handler
* @returns {(event: MessageEvent) => Promise<any>}
*/
function getVizMessageHandler() {
if (this._messageHandler === undefined) {
const vizDistFolder = "https://unpkg.com/@aduh95/viz.js/dist";
const Module = {
// locateFile is used by render module to locate WASM file.
locateFile: (fileName) => `${vizDistFolder}/${fileName}`,
};
this._messageHandler = import(Module.locateFile("render.browser.js")).then(
({ default: init, onmessage }) => {
// to avoid conflicts, disable viz.js message handler
self.removeEventListener("message", onmessage);
return init(Module).then(() => onmessage);
}
);
}
return this._messageHandler;
}
self.addEventListener("message", (event) => {
if (event.data.id) {
// handling event sent by viz.js
getVizMessageHandler()
.then((onmessage) => onmessage(event))
.catch((error) => {
// handle dynamic import error here
console.error(error);
// Note: If an error is emitted by Viz.js internals (dot syntax error,
// WASM file initialization error, etc.), the error is catch and sent
// directly through postMessage.
// If you think this behavior is not ideal, please open an issue.
});
} else {
// handle other messages
}
});
The support is experimental. You would probably need to monkey-patch the unimplemented web APIs. Please check the test folder for an example of implementation.
As Deno aims to expose all the web API, you can use the browser implementation.
To build from source, first install the Emscripten SDK and Corepack. You'll also need Node.js 14+ and Deno to run the tests.
Using Homebrew (macOS or GNU/Linux):
brew install automake bison libtool node pkg-config
Note: Emscripten version number is pinned in the Makefile. If you are willing to use a different version, you'd need to change the Makefile variable to match the version you are using.
You will certainly need to tweak config files to make sure your system knows where it should find each binary.
The build process for Viz.js is split into two parts: building the Graphviz and Expat dependencies, and building the rendering script files and API.
EMCONFIGURE=emconfigure make deps
emmake make all -j4
emmake make test
FAQs
A hack to put Graphviz on the web.
The npm package @aduh95/viz.js receives a total of 300,230 weekly downloads. As such, @aduh95/viz.js popularity was classified as popular.
We found that @aduh95/viz.js demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.