Sketchviz workflow

Making “sketchy” diagrams on your local machine

Roberto Bisceglie
4 min readFeb 6, 2023

--

I love Graphviz. It’s a really overlooked framework, surpassed in popularity by mermaid.js. Not that I think mermaid is bad, quite the opposite.

But Graphviz can be way more flexible when it comes to customization and rendering.

A diagram in Graphviz can be simple as this:

digraph G {

a1 -> a2
}

which renders like this:

Sketchviz

Sketchviz is a renderer for Graphviz, that generates layouts in a hand-made style.

Let’s take the code above, this is how it is shown in Sketchviz:

There are some limits on the use of Sketchviz:

  • you have to copy and paste the code on the website
  • you can only export the diagram in PNG format (no SVG exporting is provided)
  • if you increase the resolution, only the portion of the diagram shown on the screen is exported. So it is not possible to export the high-resolution diagram for printing.

The last point is critical to me, having the need to use diagrams in printed books.

So I looked for an alternative that would allow me to export the diagram at full resolution, starting with the code on my local machine.

Sketchviz on local

Fortunately, I dug up this repository containing a node.js version of Sketchviz that I could run locally.

Once cloned on my machine, I saved the code above in the local folder as dia.dot (dot is the file extension for Graphviz code) and called the function in bash (specifically Ubuntu WSL) as it follows:

node sketch.js dia.dot dia.svg

which returned the first exception of the test:

Error: Cannot find module 'roughjs'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:636:15)
at Function.Module._load (internal/modules/cjs/loader.js:562:25)
at Module.require (internal/modules/cjs/loader.js:692:17)
at require (internal/modules/cjs/helpers.js:25:18)
at Object.<anonymous> (/mnt/c/Users/utente/Documents/GitHub/sketchviz/sketch.js:5:15)
at Module._compile (internal/modules/cjs/loader.js:778:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Function.Module._load (internal/modules/cjs/loader.js:585:3)

taking a look at the sketch.js file, on top there is the list of requirements:

const fs = require('fs');
const path = require('path');
const rough = require('roughjs');
const jsdom = require('jsdom');

so, I installed rough.js (a graphical library that renders a drawing in a sketchy way) and jsdom

npm install --save roughjs
npm i jsdom

this created a node_modules subfolder in the local folder (below the Visual Studio Code workspace):

running again the sketch command `node sketch.js dia.dot dia.svg`the file dia.svg is created.

Note that sketch.js has a listener incorporated in its code. That’s great: if you make any edit to the dot file, the process will automatically update the svg.

Since I needed to make a one-time conversion, I brutally added a process.exit call at line 197 of the script,

dot.on('close', () => {
let result = preprocess(buffer.toString());
fs.writeFile(output, sketchy(result), function (err) {
if (err) {
console.log(err);
process.exit(1);
}
console.log("Written as '" + output + "'.");
// added this to stop the listener, comment if not necessary
process.exit(1);
});

A SVG file is sufficient to use it on the majority of websites, but I need also to convert it to a PNG. For this task I made use of the command line functions of Inkscape.

Converting the diagram to PNG

Inkscape has a practical command line tool to avoid opening each SVG file and editing it manually from GUI. The ultimate goal is to be able to process batch rendering and conversion of diagrams.

The Inkscape CLI has a list of functions that can be called with the command:

inkscape --help

Specifically, we are interested in the functions:

  • export-area-drawing: to export only the effective diagram and not the drawing “page”
  • export-background=white: to make the background solid white
  • export-filename: to give a name to the outfile (file format is inferred from the extension)
  • export-width: to specify the width of the output file
  • actions: it calls specific commands like selecting or transform objects elements (the complete list is callable with the action-list command)

to wrap up everything:

inkscape --actions="select-by-element:text;object-to-path" --export-area-drawing --export-background=white  --export-filename=dia.png --export-width=2000 dia.svg

note that if you specify a custom font installed on you machine and you are using Ubuntu WSL like me you’ll need to install it in the Ubuntu font folder before following the pipeline:

cp path/to/font/font.ttf ~/.fonts

Convert all at once

Now it’s time to make the batch converter! It’s a simple bash script which test if the font is existing in the right folder than loop through all the *.dot files in the current folder

if [ ! -f ~/.fonts/Takota-BRa8.ttf ]
then
cp assets/fonts/Takota-BRa8.ttf ~/.fonts
fi
dir=$(pwd)
for file in *.dot
do
filename=$(basename "$file")
f=${filename%.*}
cd ../assets/sketchviz-master/
node sketch.js ../../$dir/$f.dot ../../$dir/$f.svg
cd ..
cd ..
cd $dir/
inkscape --actions="select-by-element:text;object-to-path" --export-area-drawing --export-background=white --export-filename=$f.png --export-width=2000 $f.svg
done

Note that the sketchviz.js script is located in the assets/sketchviz-master subfolder of the root in my workspace.

--

--