Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial commit

  • Loading branch information...
commit 52de5754242015e059b8a58811210dc44bbf24d8 0 parents
@glejeune authored
19 LICENCE.txt
@@ -0,0 +1,19 @@
+Copyright (c) 2010 Gregoire Lejeune <gregoire.lejeune@free.fr>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
81 README.rdoc
@@ -0,0 +1,81 @@
+= Node.js GraphViz Module
+
+Copyright (C) 2010 Gregoire Lejeune
+
+* Sources : http://github.com/glejeune/Ruby-Graphviz
+
+== DESCRIPTION
+
+Interface to the GraphViz graphing tool
+
+== TODO
+
+* So many things!
+
+== CHANGELOG
+
+=== 0.0.1 :
+* Initial version
+
+== SYNOPSIS
+
+A basic example
+
+ var sys = require('sys'),
+ graphviz = require('node-graphviz/lib/graphviz');
+
+ // Create digraph G
+ var g = graphviz.digraph("G");
+
+ // Add node (ID: Hello)
+ var n1 = g.addNode( "Hello" );
+ n1.set( "color", "blue" );
+ n1.set( "style", "filled" );
+
+ // Add node (ID: World)
+ g.addNode( "World" );
+
+ // Add edge between the two nodes
+ var e = g.addEdge( n1, "World" );
+ e.set( "color", "red" );
+
+ // Print the dot script
+ console.log( g.to_dot() );
+
+ // Set GraphViz path (if not in your path)
+ g.setGraphVizPath( "/usr/local/bin" );
+ // Generate a PNG output
+ g.output( "png", "test01.png" );
+
+== INSTALLATION
+
+ $ cd ~/.node_libraries
+ $ git clone git://github.com/glejeune/node-graphviz.git
+
+Or (one day) :
+
+ $ npm install node-graphviz
+
+You also need to install GraphViz[http://www.graphviz.org]
+
+== LICENCES
+
+Copyright (c) 2010 Gregoire Lejeune <gregoire.lejeune@free.fr>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
BIN  lib/deps/.DS_Store
Binary file not shown
29 lib/deps/attributs.js
@@ -0,0 +1,29 @@
+var Hash = require( './core_ext/hash' ).Hash;
+
+var Attributs = exports.Attributs = function() {
+ this.attributs = new Hash();
+}
+
+Attributs.prototype.set = function( name, value ) {
+ this.attributs.setItem(name, value);
+}
+
+Attributs.prototype.get = function( name ) {
+ return this.attributs.items[name];
+}
+
+Attributs.prototype.to_dot = function(link) {
+ var attrsOutput = "";
+ var sep = "";
+
+ if( this.attributs.length > 0 ) {
+ attrsOutput = attrsOutput + " [ "
+ for( var name in this.attributs.items ) {
+ attrsOutput = attrsOutput + sep + name + " = " + this.attributs.items[name]
+ sep = ", "
+ }
+ attrsOutput = attrsOutput + " ]"
+ }
+
+ return attrsOutput;
+}
BIN  lib/deps/core_ext/.DS_Store
Binary file not shown
53 lib/deps/core_ext/hash.js
@@ -0,0 +1,53 @@
+var Hash = exports.Hash = function() {
+ this.length = 0;
+ this.items = new Array();
+ for (var i = 0; i < arguments.length; i += 2) {
+ if (typeof(arguments[i + 1]) != 'undefined') {
+ this.items[arguments[i]] = arguments[i + 1];
+ this.length++;
+ }
+ }
+}
+
+Hash.prototype.removeItem = function(in_key) {
+ var tmp_previous;
+ if (typeof(this.items[in_key]) != 'undefined') {
+ this.length--;
+ var tmp_previous = this.items[in_key];
+ delete this.items[in_key];
+ }
+
+ return tmp_previous;
+}
+
+Hash.prototype.getItem = function(in_key) {
+ return this.items[in_key];
+}
+
+Hash.prototype.setItem = function(in_key, in_value) {
+ var tmp_previous;
+ if (typeof(in_value) != 'undefined') {
+ if (typeof(this.items[in_key]) == 'undefined') {
+ this.length++;
+ }
+ else {
+ tmp_previous = this.items[in_key];
+ }
+
+ this.items[in_key] = in_value;
+ }
+
+ return tmp_previous;
+}
+
+Hash.prototype.hasItem = function(in_key) {
+ return typeof(this.items[in_key]) != 'undefined';
+}
+
+Hash.prototype.clear = function() {
+ for (var i in this.items) {
+ delete this.items[i];
+ }
+
+ this.length = 0;
+}
28 lib/deps/edge.js
@@ -0,0 +1,28 @@
+var Hash = require( './core_ext/hash' ).Hash,
+ Attributs = require( './attributs' ).Attributs;
+
+var Edge = exports.Edge = function(graph, nodeOne, nodeTwo) {
+ this.relativeGraph = graph;
+ this.nodeOne = nodeOne;
+ this.nodeTwo = nodeTwo;
+ this.attributs = new Attributs();
+};
+
+Edge.prototype.set = function( name, value ) {
+ this.attributs.set(name, value);
+}
+
+Edge.prototype.get = function( name ) {
+ return this.attributs.get(name);
+}
+
+Edge.prototype.to_dot = function() {
+ var edgeLink = "->";
+ if( this.relativeGraph.type == "graph" ) {
+ edgeLink = "--";
+ }
+
+ var edgeOutput = this.nodeOne.id + " " + edgeLink + " " + this.nodeTwo.id;
+ edgeOutput = edgeOutput + this.attributs.to_dot()
+ return edgeOutput;
+}
151 lib/deps/graph.js
@@ -0,0 +1,151 @@
+var Hash = require( './core_ext/hash' ).Hash,
+ Node = require( './node' ).Node,
+ Edge = require( './edge' ).Edge,
+ sys = require('sys'),
+ fs = require('fs'),
+ exec = require('child_process').exec,
+ child;
+
+var Graph = exports.Graph = function(graph, id) {
+ this.relativeGraph = graph;
+ this.id = id;
+ this.type = "graph";
+ this.gvPath = "";
+ this.nodes = new Hash();
+ this.edges = new Array();
+ this.clusters = new Hash();
+ this.graphAttributs = new Hash();
+};
+
+//
+// Set the graph type
+//
+// This method may not be called directly but internaly
+//
+Graph.prototype.setType = function(type) {
+ this.type = type;
+}
+
+Graph.prototype.getType = function(type) {
+ return this.type;
+}
+
+Graph.prototype.addNode = function(id) {
+ this.nodes.setItem(id, new Node(this, id));
+ return this.nodes.items[id];
+}
+
+Graph.prototype.getNode = function(id) {
+ return this.nodes.items[id];
+}
+
+Graph.prototype.nodeCount = function() {
+ return this.nodes.length;
+}
+
+Graph.prototype.addEdge = function(nodeOne, nodeTwo) {
+ var _nodeOne = nodeOne;
+ var _nodeTwo = nodeTwo;
+ if( typeof(nodeOne) == 'string' ) {
+ _nodeOne = this.nodes.items[nodeOne];
+ if( _nodeOne == null ) {
+ _nodeOne = this.addNode( nodeOne );
+ }
+ }
+ if( typeof(nodeTwo) == 'string' ) {
+ _nodeTwo = this.nodes.items[nodeTwo];
+ if( _nodeTwo == null ) {
+ _nodeTwo = this.addNode( nodeTwo );
+ }
+ }
+
+ var edge = new Edge(this, _nodeOne, _nodeTwo);
+ this.edges.push( edge );
+
+ return edge;
+}
+
+Graph.prototype.edgeCount = function() {
+ return this.edges.length;
+};
+
+Graph.prototype.addCluster = function(id) {
+ var cluster = new Graph(this, id);
+ cluster.setType( this.type );
+ this.clusters.setItem(id, cluster);
+ return cluster;
+}
+
+Graph.prototype.getCluster = function(id) {
+ return this.clusters.items[id];
+}
+
+Graph.prototype.clusterCount = function() {
+ return this.clusters.length;
+}
+
+Graph.prototype.set = function(name, value) {
+ this.graphAttributs.setItem(name, value);
+}
+
+Graph.prototype.get = function(name) {
+ return this.graphAttributs.items[name];
+}
+
+Graph.prototype.to_dot = function() {
+ var dotScript = "";
+ if( this.relativeGraph == null ) {
+ dotScript = this.type + " " + this.id + " {\n"
+ } else {
+ dotScript = "subgraph " + this.id + " {\n"
+ }
+
+ // Graph attributs
+ for( var name in this.graphAttributs.items ) {
+ dotScript = dotScript + " " + name + " = \"" + this.graphAttributs.items[name] + "\";\n"
+ }
+
+ // Each clusters
+ for( var id in this.clusters.items ) {
+ dotScript = dotScript + this.clusters.items[id].to_dot() + "\n"
+ }
+
+ // Each nodes
+ for( var id in this.nodes.items ) {
+ dotScript = dotScript + " " + this.nodes.items[id].to_dot() + ";\n"
+ }
+
+ // Each edges
+ for( var i in this.edges ) {
+ // dotScript = dotScript + " " + this.edges[i].nodeOne.id + " " + edgeLink + " " + this.edges[i].nodeTwo.id + ";\n"
+ dotScript = dotScript + " " + this.edges[i].to_dot() + ";\n"
+ }
+
+ dotScript = dotScript + "}\n"
+
+ return dotScript;
+}
+
+Graph.prototype.output = function(type, name) {
+ var dotFile = name+".dot"
+ fs.writeFile(dotFile, this.to_dot(), function (err) {
+ if (err) throw err;
+ });
+
+ var cmd = this.gvPath + "dot -T" + type + " -o" + name + " " + dotFile;
+ child = exec(cmd,
+ function (error, stdout, stderr) {
+ sys.print('stdout: ' + stdout + "\n");
+ sys.print('stderr: ' + stderr + "\n");
+ if (error !== null) {
+ console.log('exec error: ' + error);
+ }
+ });
+
+ // TODO: this does not work ! -- Need a Tempfile class "à la" Ruby
+ // fs.unlink(dotFile);
+}
+
+Graph.prototype.setGraphVizPath = function(path) {
+ this.gvPath = path + "/";
+}
29 lib/deps/node.js
@@ -0,0 +1,29 @@
+var Hash = require( './core_ext/hash' ).Hash,
+ Attributs = require( './attributs' ).Attributs;
+
+var Node = exports.Node = function(graph, id) {
+ this.relativeGraph = graph;
+ this.id = id;
+ this.attributs = new Attributs();
+};
+
+Node.prototype.setId = function(id) {
+ this.id = id
+}
+
+Node.prototype.id = function() {
+ return this.id;
+}
+
+Node.prototype.set = function( name, value ) {
+ this.attributs.set(name, value);
+}
+
+Node.prototype.get = function( name ) {
+ return this.attributs.get(name);
+}
+
+Node.prototype.to_dot = function() {
+ var nodeOutput = this.id + this.attributs.to_dot();
+ return nodeOutput;
+}
14 lib/graphviz.js
@@ -0,0 +1,14 @@
+var sys = require('sys'),
+ Graph = require('./deps/graph').Graph;
+
+exports.graph = function(id) {
+ var graph = new Graph(null, id);
+ graph.setType( 'graph' );
+ return graph;
+}
+
+exports.digraph = function(id) {
+ var graph = new Graph(null, id);
+ graph.setType( 'digraph' );
+ return graph;
+}
10 package.json
@@ -0,0 +1,10 @@
+{
+ "name" : "node-graphviz",
+ "version" : "0.0.1",
+ "author" : "Gregoire Lejeune <gregoire.lejeune@free.fr>",
+ "description" : "Node.js interface to the GraphViz graphing tool",
+ "keywords" : ["graphviz", "dot"],
+ "engines" : ["node"],
+ "directories" : { "lib" : "lib" },
+ "main" : "lib/graphviz"
+}
58 tests/cluster.js
@@ -0,0 +1,58 @@
+var sys = require('sys'),
+ graphviz = require('../lib/graphviz');
+
+// digraph G {
+var g = graphviz.digraph("G");
+// subgraph cluster_0 {
+var cluster_0 = g.addCluster("cluster_0");
+// style=filled;
+cluster_0.set( "style", "filled" );
+// color=lightgrey;
+cluster_0.set( "color", "lightgrey" );
+// node [style=filled,color=white];
+
+// a0 -> a1 -> a2 -> a3;
+cluster_0.addEdge( "a0", "a1" );
+cluster_0.addEdge( "a1", "a2" );
+cluster_0.addEdge( "a2", "a3" );
+// label = "process #1";
+cluster_0.set( "label", "process #1" )
+// }
+
+// subgraph cluster_1 {
+var cluster_1 = g.addCluster("cluster_1");
+// node [style=filled];
+
+// b0 -> b1 -> b2 -> b3;
+cluster_1.addEdge( "b0", "b1" );
+cluster_1.addEdge( "b1", "b2" );
+cluster_1.addEdge( "b2", "b3" );
+// label = "process #2";
+cluster_1.set( "label", "process #2" );
+// color = blue
+cluster_1.set( "color", "blue" );
+// }
+
+// start -> a0;
+g.addEdge( "start", cluster_0.getNode("a0") );
+// start -> b0;
+g.addEdge( "start", cluster_1.getNode("b0") );
+// a1 -> b3;
+g.addEdge( cluster_0.getNode("a1"), cluster_1.getNode("b3") );
+// b2 -> a3;
+g.addEdge( cluster_1.getNode("b2"), cluster_0.getNode("a3") );
+// a3 -> a0;
+g.addEdge( cluster_0.getNode("a3"), cluster_0.getNode("a0") );
+// a3 -> end;
+g.addEdge( cluster_0.getNode("a3"), "end" );
+// b3 -> end;
+g.addEdge( cluster_1.getNode("b3"), "end" );
+//
+// start [shape=Mdiamond];
+g.getNode("start").set( "shape", "Mdiamond" );
+// end [shape=Msquare];
+g.getNode("end").set( "shape", "Msquare" );
+// }
+
+console.log( g.to_dot() );
+g.output( "png", "cluster.png" );
23 tests/hello_world.js
@@ -0,0 +1,23 @@
+var sys = require('sys'),
+ graphviz = require('../lib/graphviz');
+
+// Create digraph G
+var g = graphviz.digraph("G");
+
+// Add node (ID: Hello)
+var n1 = g.addNode( "Hello" );
+n1.set( "color", "blue" );
+n1.set( "style", "filled" );
+
+// Add node (ID: World)
+g.addNode( "World" );
+
+// Add edge between the two nodes
+var e = g.addEdge( n1, "World" );
+e.set( "color", "red" );
+
+// Print the dot script
+console.log( g.to_dot() );
+
+// Generate a PNG output
+g.output( "png", "hello_world.png" );
Please sign in to comment.
Something went wrong with that request. Please try again.