123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627 |
- // Generated by CoffeeScript 1.4.0
- /*
- # Objects for dealing with the Graphviz dot/xdot format.
- # After obtaining an ast using DotParser.parser(source),
- # you may find the following useful:
- #
- # astToStr: Turn an ast back into a string
- #
- # new DotGraph(ast): Get a dotgraph object. Calling .walk on this
- # object will walk the ast and populate the .notes, .edges, and .graphs
- # properties.
- #
- # new XDotGraph(ast): Subclass of DotGraph. Calling .walk will populate
- # .nodes, .edges, and .graphs and will parse any of the known attributes
- # to javascript objects and convert their values to pixels if necessary.
- */
- var DotGraph, XDotGraph, astToStr,
- __hasProp = {}.hasOwnProperty,
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
- astToStr = function(ast, indentLevel, indentChar) {
- var attrListToStr, attrs, escape, indentStr, n, ret, _ref;
- if (indentLevel == null) {
- indentLevel = 0;
- }
- if (indentChar == null) {
- indentChar = '\t';
- }
- escape = function(s) {
- if (!(s != null)) {
- return "\"\"";
- }
- if (/^[a-zA-Z0-9]+$/.test(s) && !/^(graph|digraph|subgraph|node|edge|strict)$/.test(s)) {
- return s;
- } else {
- return "\"" + (('' + s).replace('"', '\\"')) + "\"";
- }
- };
- attrListToStr = function(l) {
- var attrStrings, e, s, _i, _len, _ref;
- if (!l || l.length === 0) {
- return "";
- }
- attrStrings = [];
- for (_i = 0, _len = l.length; _i < _len; _i++) {
- e = l[_i];
- s = e.id + "=";
- if ((_ref = e.eq) != null ? _ref.html : void 0) {
- s += "<" + e.eq.value + ">";
- } else {
- s += escape(e.eq);
- }
- attrStrings.push(s);
- }
- return "[" + (attrStrings.join(", ")) + "]";
- };
- ret = '';
- indentStr = new Array(indentLevel + 1).join(indentChar);
- if (ast instanceof Array) {
- ret = ((function() {
- var _i, _len, _results;
- _results = [];
- for (_i = 0, _len = ast.length; _i < _len; _i++) {
- n = ast[_i];
- _results.push(astToStr(n, indentLevel));
- }
- return _results;
- })()).join('\n');
- }
- switch (ast.type) {
- case 'digraph':
- case 'graph':
- case 'subgraph':
- if (ast.strict) {
- ret += indentStr + " strict " + ast.type;
- } else {
- ret += indentStr + ast.type;
- }
- if (ast.id) {
- ret += " " + ast.id;
- }
- ret += " {";
- if (ast.children.length === 0) {
- ret += " }\n";
- } else {
- ret += "\n";
- ret += astToStr(ast.children, indentLevel + 1);
- ret += "\n" + indentStr + "}";
- }
- break;
- case 'attr_stmt':
- ret += indentStr + ast.target;
- attrs = attrListToStr(ast.attr_list);
- if (attrs) {
- ret += " " + attrs;
- }
- break;
- case 'node_stmt':
- ret += indentStr + escape(ast.node_id.id);
- if (ast.node_id.port) {
- ret += ":" + (escape(ast.node_id.port.id));
- }
- if ((_ref = ast.node_id.port) != null ? _ref.compass_pt : void 0) {
- ret += ":" + ast.node_id.port.compass_pt;
- }
- attrs = attrListToStr(ast.attr_list);
- if (attrs) {
- ret += " " + attrs;
- }
- break;
- case 'edge_stmt':
- ret += indentStr + ((function() {
- var _i, _len, _ref1, _results;
- _ref1 = ast.edge_list;
- _results = [];
- for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
- n = _ref1[_i];
- _results.push(astToStr(n, 0));
- }
- return _results;
- })()).join(' -> ');
- attrs = attrListToStr(ast.attr_list);
- if (attrs) {
- ret += " " + attrs;
- }
- break;
- case 'node_id':
- ret += indentStr + escape(ast.id);
- }
- return ret;
- };
- /*
- # Takes in an AST of the dot/xdot file format
- # and produces a graph object where nodes/edges/subgraphs
- # may be queried for attributes
- */
- DotGraph = (function() {
- var DotSubgraph, attrListToObj, copy, doubleCopy, giveRandomKey, mergeLeftNoOverried, mergeLeftOverried;
- giveRandomKey = function() {
- return Math.random().toFixed(8).slice(2);
- };
- mergeLeftNoOverried = function(obj1, obj2) {
- var k, v;
- for (k in obj2) {
- v = obj2[k];
- if (!(obj1[k] != null)) {
- obj1[k] = v;
- }
- }
- return obj1;
- };
- mergeLeftOverried = function(obj1, obj2) {
- var k, v;
- for (k in obj2) {
- v = obj2[k];
- obj1[k] = v;
- }
- return obj1;
- };
- copy = function(obj) {
- var k, ret, v;
- ret = {};
- for (k in obj) {
- v = obj[k];
- ret[k] = v;
- }
- return ret;
- };
- doubleCopy = function(obj) {
- var k, ret, v;
- ret = {};
- for (k in obj) {
- v = obj[k];
- ret[k] = copy(v);
- }
- return ret;
- };
- attrListToObj = function(list) {
- var attr, ret, _i, _len;
- ret = {};
- for (_i = 0, _len = list.length; _i < _len; _i++) {
- attr = list[_i];
- ret[attr.id] = attr.eq;
- }
- return ret;
- };
- /*
- # Light object to hold nodes and attributes of subgraphs.
- # This is really just a container and doesn't have any processing capabilities
- */
- DotSubgraph = (function() {
- function DotSubgraph(id, type, parent) {
- this.id = id;
- this.type = type != null ? type : 'subgraph';
- this.parent = parent != null ? parent : null;
- if (!this.id) {
- this.id = giveRandomKey();
- this.autogeneratedId = true;
- }
- this.nodes = {};
- this.attrs = {};
- this.graphs = {};
- }
- DotSubgraph.prototype.toString = function() {
- return this.id;
- };
- return DotSubgraph;
- })();
- /****************************************
- # Here is where the DotGraph methods start
- */
- function DotGraph(ast) {
- this.ast = ast;
- this.nodes = {};
- this.edges = {};
- this.graphs = {};
- this.rootGraph = new DotSubgraph();
- }
- DotGraph.prototype.walk = function(ast) {
- var getAllNodes, walk,
- _this = this;
- if (ast == null) {
- ast = this.ast;
- }
- walk = function(tree, state, currentParentGraph) {
- var attrs, edge, elm, h, heads, id, node, oldParentGraph, t, tails, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _m, _ref, _ref1, _ref2;
- if (state == null) {
- state = {
- node: {},
- edge: {},
- graph: {}
- };
- }
- if (tree instanceof Array) {
- for (_i = 0, _len = tree.length; _i < _len; _i++) {
- elm = tree[_i];
- walk(elm, state, currentParentGraph);
- }
- }
- switch (tree.type) {
- case 'graph':
- case 'digraph':
- case 'subgraph':
- oldParentGraph = currentParentGraph;
- currentParentGraph = new DotSubgraph(tree.id || null, tree.type, currentParentGraph);
- if (_this.graphs[currentParentGraph] != null) {
- currentParentGraph = _this.graphs[currentParentGraph];
- }
- if (oldParentGraph) {
- oldParentGraph.graphs[currentParentGraph] = currentParentGraph;
- }
- _this.graphs[currentParentGraph] = currentParentGraph;
- if ((_ref = tree.type) === 'graph' || _ref === 'digraph') {
- _this.rootGraph = currentParentGraph;
- _this.rootGraph.strict = tree.strict;
- }
- state = doubleCopy(state);
- walk(tree.children, state, currentParentGraph);
- break;
- case 'node_stmt':
- id = tree.node_id.id;
- _this.nodes[id] = _this.nodes[id] || {
- attrs: {}
- };
- mergeLeftOverried(_this.nodes[id].attrs, attrListToObj(tree.attr_list));
- mergeLeftNoOverried(_this.nodes[id].attrs, state.node);
- currentParentGraph.nodes[id] = true;
- break;
- case 'attr_stmt':
- mergeLeftOverried(state[tree.target], attrListToObj(tree.attr_list));
- break;
- case 'edge_stmt':
- _ref1 = tree.edge_list;
- for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
- node = _ref1[_j];
- if (node.type === 'node_id' && !(_this.nodes[node.id] != null)) {
- walk({
- type: 'node_stmt',
- node_id: node,
- attr_list: []
- }, state, currentParentGraph);
- } else if (node.type === 'subgraph') {
- walk(node, state, currentParentGraph);
- }
- }
- heads = getAllNodes(tree.edge_list[0]);
- _ref2 = tree.edge_list.slice(1);
- for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
- node = _ref2[_k];
- tails = getAllNodes(node);
- for (_l = 0, _len3 = heads.length; _l < _len3; _l++) {
- h = heads[_l];
- for (_m = 0, _len4 = tails.length; _m < _len4; _m++) {
- t = tails[_m];
- edge = [h, t];
- attrs = mergeLeftNoOverried(attrListToObj(tree.attr_list), state.edge);
- _this.edges[edge] = _this.edges[edge] || [];
- _this.edges[edge].push({
- edge: edge,
- attrs: attrs
- });
- }
- }
- heads = tails;
- }
- }
- currentParentGraph.attrs = state.graph;
- };
- getAllNodes = function(tree) {
- var n, ret, _i, _len;
- ret = [];
- if (tree instanceof Array) {
- for (_i = 0, _len = tree.length; _i < _len; _i++) {
- n = tree[_i];
- ret = ret.concat(getAllNodes(n));
- }
- return ret;
- }
- switch (tree.type) {
- case 'node_id':
- ret.push(tree.id);
- break;
- case 'node_stmt':
- ret.push(tree.node_id.id);
- break;
- case 'edge_stmt':
- ret = ret.concat(getAllNodes(tree.edge_list));
- break;
- case 'graph':
- case 'digraph':
- case 'subgraph':
- ret = ret.concat(getAllNodes(tree.children));
- }
- return ret;
- };
- walk(ast);
- this.id = this.rootGraph.id;
- this.type = this.rootGraph.type;
- this.strict = this.rootGraph.strict;
- return this;
- };
- DotGraph.prototype.generateAst = function() {
- var e, genAttrsAst, genEdgesAst, genNodeAst, genSubgraphAst, k, root, v, _i, _len, _ref, _ref1;
- genAttrsAst = function(attrs) {
- var k, ret, v;
- if (!attrs || !attrs instanceof Object) {
- return null;
- }
- ret = [];
- for (k in attrs) {
- v = attrs[k];
- ret.push({
- type: 'attr',
- id: k,
- eq: v
- });
- }
- return ret;
- };
- genEdgesAst = function(edge) {
- var attrList, ret;
- ret = {
- type: 'edge_stmt',
- edge_list: [
- {
- type: 'node_id',
- id: edge.edge[0]
- }, {
- type: 'node_id',
- id: edge.edge[1]
- }
- ]
- };
- attrList = genAttrsAst(edge.attrs);
- if (attrList) {
- ret.attr_list = attrList;
- }
- return ret;
- };
- genNodeAst = function(id, attrs, html) {
- var attrList, ret;
- ret = {
- type: 'node_stmt',
- node_id: {
- type: 'node_id',
- id: id
- }
- };
- attrList = genAttrsAst(attrs.attrs);
- if (attrList) {
- ret.attr_list = attrList;
- }
- return ret;
- };
- genSubgraphAst = function(graph) {
- var k, ret, v, _ref, _ref1, _ref2;
- ret = {
- type: graph.type,
- id: graph.autogeneratedId ? null : graph.id,
- children: []
- };
- _ref = graph.graphs;
- for (k in _ref) {
- v = _ref[k];
- ret.children.push(genSubgraphAst(v));
- }
- _ref1 = graph.nodes;
- for (k in _ref1) {
- v = _ref1[k];
- ret.children.push(genNodeAst(k, v));
- }
- _ref2 = graph.edges;
- for (k in _ref2) {
- v = _ref2[k];
- ret.children.push(genEdgesAst(v));
- }
- if (Object.keys(graph.attrs).length > 0) {
- ret.children.push({
- type: 'attr_stmt',
- target: 'graph',
- attr_list: genAttrsAst(graph.attrs)
- });
- }
- return ret;
- };
- root = genSubgraphAst(this.rootGraph);
- if (this.strict) {
- root.strict = this.strict;
- }
- root.children = root.children || [];
- _ref = this.nodes;
- for (k in _ref) {
- v = _ref[k];
- root.children.push(genNodeAst(k, v));
- }
- _ref1 = this.edges;
- for (k in _ref1) {
- v = _ref1[k];
- for (_i = 0, _len = v.length; _i < _len; _i++) {
- e = v[_i];
- root.children.push(genEdgesAst(e));
- }
- }
- return root;
- };
- return DotGraph;
- })();
- /*
- # Extension of the DotGraph object that will parse node/edge/graph
- # attributes like pos, width, height, etc. into the appropriate javascript types.
- #
- # All attributes are normalized to pixels for easier drawing.
- */
- XDotGraph = (function(_super) {
- var Edge, toFloatList;
- __extends(XDotGraph, _super);
- function XDotGraph() {
- return XDotGraph.__super__.constructor.apply(this, arguments);
- }
- toFloatList = function(list) {
- var v;
- if (typeof list === 'string') {
- list = list.split(/[, ]/);
- }
- return (function() {
- var _i, _len, _results;
- _results = [];
- for (_i = 0, _len = list.length; _i < _len; _i++) {
- v = list[_i];
- _results.push(parseFloat(v));
- }
- return _results;
- })();
- };
- Edge = (function() {
- function Edge(val) {
- var controlPoints, i;
- val = toFloatList(val);
- controlPoints = [];
- i = 3;
- while (i + 6 < val.length) {
- controlPoints.push(val.slice(i, i + 6));
- i += 6;
- }
- this.type = 'edge';
- this.origin = val.slice(1, 3);
- this.controlPoints = controlPoints;
- this.arrow = val.slice(-4);
- }
- Edge.prototype.toString = function() {
- var i, l, points, _i, _len, _ref;
- points = [this.origin[0], this.origin[1]];
- _ref = this.controlPoints;
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- l = _ref[_i];
- points = points.concat(l);
- }
- points = points.concat(this.arrow.slice(-2));
- return "e," + (((function() {
- var _j, _ref1, _results;
- _results = [];
- for (i = _j = 0, _ref1 = points.length; _j < _ref1; i = _j += 2) {
- _results.push(points[i] + ',' + points[i + 1]);
- }
- return _results;
- })()).join(' '));
- };
- return Edge;
- })();
- XDotGraph.prototype.dpi = 36;
- XDotGraph.prototype.walk = function() {
- var processAttrs,
- _this = this;
- XDotGraph.__super__.walk.call(this);
- processAttrs = function(graph) {
- var attr, e, edge, g, h, n, val, _i, _len, _ref, _ref1, _ref2, _ref3, _ref4, _ref5;
- if (!(graph != null)) {
- return;
- }
- _ref = (graph != null ? graph.nodes : void 0) || {};
- for (h in _ref) {
- n = _ref[h];
- _ref1 = (n != null ? n.attrs : void 0) || {};
- for (attr in _ref1) {
- val = _ref1[attr];
- n.attrs[attr] = _this.parseAttr(attr, val);
- }
- }
- _ref2 = (graph != null ? graph.edges : void 0) || {};
- for (h in _ref2) {
- e = _ref2[h];
- for (_i = 0, _len = e.length; _i < _len; _i++) {
- edge = e[_i];
- _ref3 = (edge != null ? edge.attrs : void 0) || {};
- for (attr in _ref3) {
- val = _ref3[attr];
- edge.attrs[attr] = _this.parseAttr(attr, val);
- }
- }
- }
- _ref4 = (graph != null ? graph.attrs : void 0) || {};
- for (attr in _ref4) {
- val = _ref4[attr];
- graph.attrs[attr] = _this.parseAttr(attr, val);
- }
- _ref5 = (graph != null ? graph.graphs : void 0) || {};
- for (h in _ref5) {
- g = _ref5[h];
- processAttrs(g);
- }
- };
- return processAttrs(this);
- };
- XDotGraph.prototype.parseAttr = function(attr, val) {
- if (!val) {
- return null;
- }
- switch (attr) {
- case 'width':
- case 'height':
- return parseFloat(val) * this.dpi;
- case 'bb':
- case 'lp':
- return toFloatList(val);
- case 'pos':
- if (val.charAt(0) === 'e') {
- /*
- val = toFloatList(val)
- controlPoints = []
- # arrow pos are of the form "'e',startx,starty, <triplets of bzCurve xy-coords>, arrowTargetx, arrowTargety"
- i = 2
- while i + 6 < val.length
- controlPoints.push val.slice(i,i+6)
- i += 6
- return {type: 'edge', origin: val[1..2], controlPoints: controlPoints, arrow: val.slice(-4)}
- */
- return new Edge(val);
- } else {
- return toFloatList(val);
- }
- }
- return val;
- };
- return XDotGraph;
- })(DotGraph);
|