35

Is there a standard way to read and parse DOT graph files in javascript, ideally in way that will work nicely in d3?

Currently, the only thing I can think of doing is reading plain text and doing my own parsing. Hopefully this'd be reinventing the wheel though.

d3.text("graph.dot", function(error, dotGraph) {
    ....
)};
ajwood
  • 18,227
  • 15
  • 61
  • 104

4 Answers4

42

⚠ Solution proposed here depends on two libraries marked as unsupported by their authors.

To get Graphviz DOT files rendered in Javascript, combine the graphlib-dot and dagre-d3 libraries.

The graphlibDot.read() method takes a graph or digraph definition in DOT syntax and produces a graph object. The dagreD3.render() method can then output this graph object to SVG.

You can then use additional D3 methods to add functionality to the graph, retrieving additional node and edge attributes from the graphlib graph object as needed.

A trivial self-contained example is:

window.onload = function() {
  // Parse the DOT syntax into a graphlib object.
  var g = graphlibDot.read(
    'digraph {\n' +
    '    a -> b;\n' +
    '    }'
  )

  // Render the graphlib object using d3.
  var render = new dagreD3.render();
  render(d3.select("svg g"), g);


  // Optional - resize the SVG element based on the contents.
  var svg = document.querySelector('#graphContainer');
  var bbox = svg.getBBox();
  svg.style.width = bbox.width + 40.0 + "px";
  svg.style.height = bbox.height + 40.0 + "px";
}
svg {
  overflow: hidden;
}
.node rect {
  stroke: #333;
  stroke-width: 1.5px;
  fill: #fff;
}
.edgeLabel rect {
  fill: #fff;
}
.edgePath {
  stroke: #333;
  stroke-width: 1.5px;
  fill: none;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://dagrejs.github.io/project/graphlib-dot/v0.6.4/graphlib-dot.min.js"></script>
<script src="https://dagrejs.github.io/project/dagre-d3/v0.5.0/dagre-d3.min.js"></script>

<html>

<body>
  <script type='text/javascript'>
  </script>
  <svg id="graphContainer">
    <g/>
  </svg>
</body>

</html>
kamaradclimber
  • 2,479
  • 1
  • 26
  • 45
Richard Neish
  • 8,414
  • 4
  • 39
  • 69
  • This looks great! I'm having a problem with your example though.. my graph is larger than my screen, and there are no scrollbars to pan around.. is there an easy way to fix that? – ajwood Jul 14 '14 at 13:21
  • You need to set the width and height of your SVG element. I haven't found a really good way of setting these automatically from the graph content, so I currently set them to really large values, or use trial and error. – Richard Neish Jul 14 '14 at 13:33
  • My graphs are generated dynamically, so it would definitely be nice to figure them out from content.. I'll let you know if I figure something out! – ajwood Jul 14 '14 at 13:35
  • 2
    I've got something working in Firefox and Chrome, but haven't tested it extensively. After rendering the graph, call getBBox() on your SVG element to get the bounding box of the contents, then set the style.width and style.height attributes based on the bounding box plus any padding. I will update the example to reflect this. – Richard Neish Jul 14 '14 at 15:25
  • Great! How do you change `var g` to read from a file? is it something lie: `fs.readFileSync('graph.dot', 'UTF-8')`? – sAguinaga Mar 15 '15 at 07:43
  • @sAguinaga that's a different question. I suggest you try a few things, see what problems you run into, search for solutions and ask another question if you don't find an answer. – Richard Neish Mar 16 '15 at 09:42
10

Late to the party, but if you're still interested, here's a way to do it with the new d3-graphviz plug-in that I just released:

<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="http://viz-js.com/bower_components/viz.js/viz-lite.js"></script>
<script src="https://github.com/magjac/d3-graphviz/releases/download/v0.0.4/d3-graphviz.min.js"></script>
<div id="graph" style="text-align: center;"></div>
<script>

d3.select("#graph").graphviz()
    .renderDot('digraph  {a -> b}');

</script>
magjac
  • 857
  • 1
  • 8
  • 12
  • Thanks for posting this snippet @magjac (and for the d3-graphgiz plugin)! I think there's a missing `https` in front of `//d3js.org` in the first ` – rambo Feb 10 '21 at 20:00
  • Thanks. Fixed. However, now I'm getting an error for https://github.com/magjac/d3-graphviz/releases/download/v0.0.4/d3-graphviz.min.js which I don't understand. – magjac Feb 11 '21 at 05:13
  • .@magjac hm, not having the same issue on my end ... maybe something to do with certificates on your machine since the url is using https? – rambo Feb 11 '21 at 16:49
  • beside the fact the example is not running but i tested it's the best solution it preserves the formatting of graph – Zain Ul Abidin Jun 05 '21 at 07:40
  • @magjac will your library also read json? – joshlsullivan Aug 31 '23 at 14:13
4

Same example, using latest version of graphlib-dot and dagre-d3.

window.onload = function() {
      // Parse the DOT syntax into a graphlib object.
      var g = graphlibDot.read(
        'digraph {\n' +
        '    a -> b;\n' +
        '    }'
      )

      // Render the graphlib object using d3.
      var renderer = dagreD3.render();
      d3.select("svg g").call(renderer, g);


      // Optional - resize the SVG element based on the contents.
      var svg = document.querySelector('#graphContainer');
      var bbox = svg.getBBox();
      svg.style.width = bbox.width + 40.0 + "px";
      svg.style.height = bbox.height + 40.0 + "px";
    }
svg {
  overflow: hidden;
}
.node rect {
  stroke: #333;
  stroke-width: 1.5px;
  fill: #fff;
}
.edgeLabel rect {
  fill: #fff;
}
.edgePath {
  stroke: #333;
  stroke-width: 1.5px;
  fill: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="http://cpettitt.github.io/project/graphlib-dot/latest/graphlib-dot.min.js"></script>
<script src="http://cpettitt.github.io/project/dagre-d3/latest/dagre-d3.js"></script>

    <html>

    <body>
      <script type='text/javascript'>
      </script>
      <svg id="graphContainer">
        <g/>
      </svg>
    </body>

    </html>
PokerFace
  • 811
  • 2
  • 9
  • 15
  • This updated code works, but the svg rendering of the DOT file output is very dependent on the parse order of the Nodes and Edges. The older versions seemed to render the DOT file without issue. – Bob Jordan Mar 12 '17 at 11:20
4

The question asks for a possibility to visualise .dot files einther in javascript or D3js. I think the solution from the highest rated answer will work for most of you.

I was unhappy because of these 3 reasons:

  1. It involves libraries like lowdash, dagre and graphlib additionally to D3js and is heavyweight.
  2. Parser output is not a D3js "friedly" data-structure.
  3. Usage (API) in not D3js style.

That's why I created an adapter which will basically allow you to use .dot files with any of thousands of D3js samples by changing just one statement. If you have some D3js visualisation working on following data-structure:

{
  "nodes": [ {"id": "Myriel"}, {"id": "Napoleon"}],
  "links": [ {"source": "Myriel"}, {"target": "Napoleon"}]
} 

Just include following script and call d3.dot:

<script src="https://cdn.jsdelivr.net/gh/gmamaladze/d3-dot-graph@1.0.0/build/d3-dot-graph.min.js"></script>
<script>

d3.dot(url, function(graph) {
   ...
});

</script>

instead of:

d3.json(url, function(graph) {...});

GitHub repository with code and examples

George Mamaladze
  • 7,593
  • 2
  • 36
  • 52
  • This is exactly what I was looking for. I'm amazed that there's 2.5k lines of code in this. Brilliant stuff - I'm going to give it a try and talk about it to others if it works because many of the other routes I have tried, as you say, involve zillions of dependencies. This deserves wider 'visibility' ;-) – Thomas Browne Dec 16 '18 at 11:07