Refactor code

This commit is contained in:
Tyler Long
2017-04-16 23:48:36 +08:00
parent 87c7f73245
commit 5624453c87
17 changed files with 632 additions and 923 deletions

View File

@@ -4,12 +4,9 @@ var log = Logger.Log
var relations = [] var relations = []
var classes var classes
// var idCache
classes = { classes = {
} }
// Functions to be run after graph rendering
// var funs = []
/** /**
* Function called by parser when a node definition has been found. * Function called by parser when a node definition has been found.
* @param id * @param id

View File

@@ -39,88 +39,88 @@ var getGraphId = function (label) {
*/ */
var insertMarkers = function (elem) { var insertMarkers = function (elem) {
elem.append('defs').append('marker') elem.append('defs').append('marker')
.attr('id', 'extensionStart') .attr('id', 'extensionStart')
.attr('class', 'extension') .attr('class', 'extension')
.attr('refX', 0) .attr('refX', 0)
.attr('refY', 7) .attr('refY', 7)
.attr('markerWidth', 190) .attr('markerWidth', 190)
.attr('markerHeight', 240) .attr('markerHeight', 240)
.attr('orient', 'auto') .attr('orient', 'auto')
.append('path') .append('path')
.attr('d', 'M 1,7 L18,13 V 1 Z') .attr('d', 'M 1,7 L18,13 V 1 Z')
elem.append('defs').append('marker') elem.append('defs').append('marker')
.attr('id', 'extensionEnd') .attr('id', 'extensionEnd')
.attr('refX', 19) .attr('refX', 19)
.attr('refY', 7) .attr('refY', 7)
.attr('markerWidth', 20) .attr('markerWidth', 20)
.attr('markerHeight', 28) .attr('markerHeight', 28)
.attr('orient', 'auto') .attr('orient', 'auto')
.append('path') .append('path')
.attr('d', 'M 1,1 V 13 L18,7 Z') // this is actual shape for arrowhead .attr('d', 'M 1,1 V 13 L18,7 Z') // this is actual shape for arrowhead
elem.append('defs').append('marker') elem.append('defs').append('marker')
.attr('id', 'compositionStart') .attr('id', 'compositionStart')
.attr('class', 'extension') .attr('class', 'extension')
.attr('refX', 0) .attr('refX', 0)
.attr('refY', 7) .attr('refY', 7)
.attr('markerWidth', 190) .attr('markerWidth', 190)
.attr('markerHeight', 240) .attr('markerHeight', 240)
.attr('orient', 'auto') .attr('orient', 'auto')
.append('path') .append('path')
.attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z') .attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z')
elem.append('defs').append('marker') elem.append('defs').append('marker')
.attr('id', 'compositionEnd') .attr('id', 'compositionEnd')
.attr('refX', 19) .attr('refX', 19)
.attr('refY', 7) .attr('refY', 7)
.attr('markerWidth', 20) .attr('markerWidth', 20)
.attr('markerHeight', 28) .attr('markerHeight', 28)
.attr('orient', 'auto') .attr('orient', 'auto')
.append('path') .append('path')
.attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z') .attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z')
elem.append('defs').append('marker') elem.append('defs').append('marker')
.attr('id', 'aggregationStart') .attr('id', 'aggregationStart')
.attr('class', 'extension') .attr('class', 'extension')
.attr('refX', 0) .attr('refX', 0)
.attr('refY', 7) .attr('refY', 7)
.attr('markerWidth', 190) .attr('markerWidth', 190)
.attr('markerHeight', 240) .attr('markerHeight', 240)
.attr('orient', 'auto') .attr('orient', 'auto')
.append('path') .append('path')
.attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z') .attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z')
elem.append('defs').append('marker') elem.append('defs').append('marker')
.attr('id', 'aggregationEnd') .attr('id', 'aggregationEnd')
.attr('refX', 19) .attr('refX', 19)
.attr('refY', 7) .attr('refY', 7)
.attr('markerWidth', 20) .attr('markerWidth', 20)
.attr('markerHeight', 28) .attr('markerHeight', 28)
.attr('orient', 'auto') .attr('orient', 'auto')
.append('path') .append('path')
.attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z') .attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z')
elem.append('defs').append('marker') elem.append('defs').append('marker')
.attr('id', 'dependencyStart') .attr('id', 'dependencyStart')
.attr('class', 'extension') .attr('class', 'extension')
.attr('refX', 0) .attr('refX', 0)
.attr('refY', 7) .attr('refY', 7)
.attr('markerWidth', 190) .attr('markerWidth', 190)
.attr('markerHeight', 240) .attr('markerHeight', 240)
.attr('orient', 'auto') .attr('orient', 'auto')
.append('path') .append('path')
.attr('d', 'M 5,7 L9,13 L1,7 L9,1 Z') .attr('d', 'M 5,7 L9,13 L1,7 L9,1 Z')
elem.append('defs').append('marker') elem.append('defs').append('marker')
.attr('id', 'dependencyEnd') .attr('id', 'dependencyEnd')
.attr('refX', 19) .attr('refX', 19)
.attr('refY', 7) .attr('refY', 7)
.attr('markerWidth', 20) .attr('markerWidth', 20)
.attr('markerHeight', 28) .attr('markerHeight', 28)
.attr('orient', 'auto') .attr('orient', 'auto')
.append('path') .append('path')
.attr('d', 'M 18,7 L9,13 L14,7 L9,1 Z') .attr('d', 'M 18,7 L9,13 L14,7 L9,1 Z')
} }
var edgeCount = 0 var edgeCount = 0
@@ -138,24 +138,23 @@ var drawEdge = function (elem, path, relation) {
} }
} }
// The data for our line // The data for our line
var lineData = path.points var lineData = path.points
// This is the accessor function we talked about above // This is the accessor function we talked about above
var lineFunction = d3.svg.line() var lineFunction = d3.svg.line()
.x(function (d) { .x(function (d) {
return d.x return d.x
}) })
.y(function (d) { .y(function (d) {
return d.y return d.y
}) })
// .interpolate('cardinal'); .interpolate('basis')
.interpolate('basis')
var svgPath = elem.append('path') var svgPath = elem.append('path')
.attr('d', lineFunction(lineData)) .attr('d', lineFunction(lineData))
.attr('id', 'edge' + edgeCount) .attr('id', 'edge' + edgeCount)
.attr('class', 'relation') .attr('class', 'relation')
var url = '' var url = ''
if (conf.arrowMarkerAbsolute) { if (conf.arrowMarkerAbsolute) {
url = window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.search url = window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.search
@@ -163,7 +162,6 @@ var drawEdge = function (elem, path, relation) {
url = url.replace(/\)/g, '\\)') url = url.replace(/\)/g, '\\)')
} }
// console.log(relation.relation.type1);
if (relation.relation.type1 !== 'none') { if (relation.relation.type1 !== 'none') {
svgPath.attr('marker-start', 'url(' + url + '#' + getRelationType(relation.relation.type1) + 'Start' + ')') svgPath.attr('marker-start', 'url(' + url + '#' + getRelationType(relation.relation.type1) + 'Start' + ')')
} }
@@ -171,9 +169,6 @@ var drawEdge = function (elem, path, relation) {
svgPath.attr('marker-end', 'url(' + url + '#' + getRelationType(relation.relation.type2) + 'End' + ')') svgPath.attr('marker-end', 'url(' + url + '#' + getRelationType(relation.relation.type2) + 'End' + ')')
} }
// var bbox = svgPath[0][0].getBBox();
// var x = Math.floor(bbox.x + bbox.width/2.0);
// var y = Math.floor(bbox.y + bbox.height/2.0);
var x, y var x, y
var l = path.points.length var l = path.points.length
if ((l % 2) !== 0) { if ((l % 2) !== 0) {
@@ -189,28 +184,24 @@ var drawEdge = function (elem, path, relation) {
if (typeof relation.title !== 'undefined') { if (typeof relation.title !== 'undefined') {
var g = elem.append('g') var g = elem.append('g')
.attr('class', 'classLabel') .attr('class', 'classLabel')
var label = g.append('text') var label = g.append('text')
.attr('class', 'label') .attr('class', 'label')
.attr('x', x) .attr('x', x)
.attr('y', y) .attr('y', y)
.attr('fill', 'red') .attr('fill', 'red')
.attr('text-anchor', 'middle') .attr('text-anchor', 'middle')
.text(relation.title) .text(relation.title)
window.label = label window.label = label
var bounds = label.node().getBBox() var bounds = label.node().getBBox()
g.insert('rect', ':first-child') g.insert('rect', ':first-child')
.attr('class', 'box') .attr('class', 'box')
.attr('x', bounds.x - conf.padding / 2) .attr('x', bounds.x - conf.padding / 2)
.attr('y', bounds.y - conf.padding / 2) .attr('y', bounds.y - conf.padding / 2)
.attr('width', bounds.width + 2 * conf.padding / 2) .attr('width', bounds.width + 2 * conf.padding / 2)
.attr('height', bounds.height + 2 * conf.padding / 2) .attr('height', bounds.height + 2 * conf.padding / 2)
// .append('textpath')
// .attr('xlink:href','#edge'+edgeCount)
// .attr('text-anchor','middle')
// .attr('startOffset','50%')
} }
edgeCount++ edgeCount++
@@ -221,8 +212,8 @@ var drawClass = function (elem, classDef) {
var addTspan = function (textEl, txt, isFirst) { var addTspan = function (textEl, txt, isFirst) {
var tSpan = textEl.append('tspan') var tSpan = textEl.append('tspan')
.attr('x', conf.padding) .attr('x', conf.padding)
.text(txt) .text(txt)
if (!isFirst) { if (!isFirst) {
tSpan.attr('dy', conf.textHeight) tSpan.attr('dy', conf.textHeight)
} }
@@ -237,25 +228,25 @@ var drawClass = function (elem, classDef) {
} }
var g = elem.append('g') var g = elem.append('g')
.attr('id', id) .attr('id', id)
.attr('class', 'classGroup') .attr('class', 'classGroup')
var title = g.append('text') var title = g.append('text')
.attr('x', conf.padding) .attr('x', conf.padding)
.attr('y', conf.textHeight + conf.padding) .attr('y', conf.textHeight + conf.padding)
.text(classDef.id) .text(classDef.id)
var titleHeight = title.node().getBBox().height var titleHeight = title.node().getBBox().height
var membersLine = g.append('line') // text label for the x axis var membersLine = g.append('line') // text label for the x axis
.attr('x1', 0) .attr('x1', 0)
.attr('y1', conf.padding + titleHeight + conf.dividerMargin / 2) .attr('y1', conf.padding + titleHeight + conf.dividerMargin / 2)
.attr('y2', conf.padding + titleHeight + conf.dividerMargin / 2) .attr('y2', conf.padding + titleHeight + conf.dividerMargin / 2)
var members = g.append('text') // text label for the x axis var members = g.append('text') // text label for the x axis
.attr('x', conf.padding) .attr('x', conf.padding)
.attr('y', titleHeight + (conf.dividerMargin) + conf.textHeight) .attr('y', titleHeight + (conf.dividerMargin) + conf.textHeight)
.attr('fill', 'white') .attr('fill', 'white')
.attr('class', 'classText') .attr('class', 'classText')
var isFirst = true var isFirst = true
@@ -263,23 +254,19 @@ var drawClass = function (elem, classDef) {
addTspan(members, member, isFirst) addTspan(members, member, isFirst)
isFirst = false isFirst = false
}) })
// for (var member of classDef.members) {
// addTspan(members, member, isFirst);
// isFirst = false;
// }
var membersBox = members.node().getBBox() var membersBox = members.node().getBBox()
var methodsLine = g.append('line') // text label for the x axis var methodsLine = g.append('line') // text label for the x axis
.attr('x1', 0) .attr('x1', 0)
.attr('y1', conf.padding + titleHeight + 3 * conf.dividerMargin / 2 + membersBox.height) .attr('y1', conf.padding + titleHeight + 3 * conf.dividerMargin / 2 + membersBox.height)
.attr('y2', conf.padding + titleHeight + 3 * conf.dividerMargin / 2 + membersBox.height) .attr('y2', conf.padding + titleHeight + 3 * conf.dividerMargin / 2 + membersBox.height)
var methods = g.append('text') // text label for the x axis var methods = g.append('text') // text label for the x axis
.attr('x', conf.padding) .attr('x', conf.padding)
.attr('y', titleHeight + 2 * conf.dividerMargin + membersBox.height + conf.textHeight) .attr('y', titleHeight + 2 * conf.dividerMargin + membersBox.height + conf.textHeight)
.attr('fill', 'white') .attr('fill', 'white')
.attr('class', 'classText') .attr('class', 'classText')
isFirst = true isFirst = true
@@ -287,17 +274,13 @@ var drawClass = function (elem, classDef) {
addTspan(methods, method, isFirst) addTspan(methods, method, isFirst)
isFirst = false isFirst = false
}) })
// for (var method of classDef.methods) {
// addTspan(methods, method, isFirst);
// isFirst = false;
// }
var classBox = g.node().getBBox() var classBox = g.node().getBBox()
g.insert('rect', ':first-child') g.insert('rect', ':first-child')
.attr('x', 0) .attr('x', 0)
.attr('y', 0) .attr('y', 0)
.attr('width', classBox.width + 2 * conf.padding) .attr('width', classBox.width + 2 * conf.padding)
.attr('height', classBox.height + conf.padding + 0.5 * conf.dividerMargin) .attr('height', classBox.height + conf.padding + 0.5 * conf.dividerMargin)
membersLine.attr('x2', classBox.width + 2 * conf.padding) membersLine.attr('x2', classBox.width + 2 * conf.padding)
methodsLine.attr('x2', classBox.width + 2 * conf.padding) methodsLine.attr('x2', classBox.width + 2 * conf.padding)
@@ -328,22 +311,21 @@ module.exports.draw = function (text, id) {
log.info('Rendering diagram ' + text) log.info('Rendering diagram ' + text)
/// / Fetch the default direction, use TD if none was found /// / Fetch the default direction, use TD if none was found
var diagram = d3.select('#' + id) var diagram = d3.select('#' + id)
insertMarkers(diagram) insertMarkers(diagram)
// var svg = diagram.append('svg');
// Layout graph, Create a new directed graph // Layout graph, Create a new directed graph
var g = new dagre.graphlib.Graph({ var g = new dagre.graphlib.Graph({
multigraph: true multigraph: true
}) })
// Set an object for the graph label // Set an object for the graph label
g.setGraph({ g.setGraph({
isMultiGraph: true isMultiGraph: true
}) })
// Default to assigning a new object as a label for each new edge. // Default to assigning a new object as a label for each new edge.
g.setDefaultEdgeLabel(function () { g.setDefaultEdgeLabel(function () {
return {} return {}
}) })
@@ -354,37 +336,23 @@ module.exports.draw = function (text, id) {
for (i = 0; i < keys.length; i++) { for (i = 0; i < keys.length; i++) {
var classDef = classes[keys[i]] var classDef = classes[keys[i]]
var node = drawClass(diagram, classDef) var node = drawClass(diagram, classDef)
// Add nodes to the graph. The first argument is the node id. The second is // Add nodes to the graph. The first argument is the node id. The second is
// metadata about the node. In this case we're going to add labels to each of // metadata about the node. In this case we're going to add labels to each of
// our nodes. // our nodes.
g.setNode(node.id, node) g.setNode(node.id, node)
log.info('Org height: ' + node.height) log.info('Org height: ' + node.height)
// g.setNode("swilliams", { label: "Saul Williams", width: 160, height: 100 });
// g.setNode("bpitt", { label: "Brad Pitt", width: 108, height: 100 });
// g.setNode("hford", { label: "Harrison Ford", width: 168, height: 100 });
// g.setNode("lwilson", { label: "Luke Wilson", width: 144, height: 100 });
// g.setNode("kbacon", { label: "Kevin Bacon", width: 121, height: 100 });
} }
var relations = cDDb.getRelations() var relations = cDDb.getRelations()
// var i = 0
relations.forEach(function (relation) { relations.forEach(function (relation) {
// i = i + 1
log.info('tjoho' + getGraphId(relation.id1) + getGraphId(relation.id2) + JSON.stringify(relation)) log.info('tjoho' + getGraphId(relation.id1) + getGraphId(relation.id2) + JSON.stringify(relation))
g.setEdge(getGraphId(relation.id1), getGraphId(relation.id2), {relation: relation}) g.setEdge(getGraphId(relation.id1), getGraphId(relation.id2), { relation: relation })
}) })
// for (var relation of relations) {
// i = i + 1;
// log.info('tjoho' + getGraphId(relation.id1) + getGraphId(relation.id2) + JSON.stringify(relation));
// g.setEdge(getGraphId(relation.id1), getGraphId(relation.id2), {relation: relation});
// }
dagre.layout(g) dagre.layout(g)
g.nodes().forEach(function (v) { g.nodes().forEach(function (v) {
if (typeof v !== 'undefined') { if (typeof v !== 'undefined') {
log.debug('Node ' + v + ': ' + JSON.stringify(g.node(v))) log.debug('Node ' + v + ': ' + JSON.stringify(g.node(v)))
d3.select('#' + v).attr('transform', 'translate(' + (g.node(v).x - (g.node(v).width / 2)) + ',' + (g.node(v).y - (g.node(v).height / 2)) + ' )') d3.select('#' + v).attr('transform', 'translate(' + (g.node(v).x - (g.node(v).width / 2)) + ',' + (g.node(v).y - (g.node(v).height / 2)) + ' )')
// d3.select('#' +v +' rect').attr('x',(g.node(v).x-(g.node(v).width/2)))
// .attr('y',(g.node(v).y-(g.node(v).height/2)));
} }
}) })
g.edges().forEach(function (e) { g.edges().forEach(function (e) {
@@ -392,21 +360,7 @@ module.exports.draw = function (text, id) {
drawEdge(diagram, g.edge(e), g.edge(e).relation) drawEdge(diagram, g.edge(e), g.edge(e).relation)
}) })
//
diagram.attr('height', '100%') diagram.attr('height', '100%')
diagram.attr('width', '100%') diagram.attr('width', '100%')
diagram.attr('viewBox', '0 0 ' + (g.graph().width + 20) + ' ' + (g.graph().height + 20)) diagram.attr('viewBox', '0 0 ' + (g.graph().width + 20) + ' ' + (g.graph().height + 20))
//
//
//
//
// if(conf.useMaxWidth) {
// diagram.attr('height', '100%');
// diagram.attr('width', '100%');
// diagram.attr('style', 'max-width:' + (width) + 'px;');
// }else{
// diagram.attr('height',height);
// diagram.attr('width', width );
// }
// diagram.attr('viewBox', (box.startx-conf.diagramMarginX) + ' -' +conf.diagramMarginY + ' ' + width + ' ' + height);
} }

View File

@@ -1,90 +1,14 @@
/* eslint-env jasmine */ /* eslint-env jasmine */
// var proxyquire = require('proxyquire'); /**
// var newD3; * Created by knut on 14-11-18.
/// ** */
// * Created by knut on 14-11-18.
// */
//
// var d3 = {
// select:function(){
// return new newD3();
// },
// selectAll:function(){
// return new newD3();
// }
// };
// var classRenderer = proxyquire('./classRenderer', { '../../d3': d3 });
// var testDom = require('testdom')('<html><body><div id="tst"></div></body></html>');
// var classRenderer = require('./classRenderer')
// var parser = require('./parser/classDiagram').parser
describe('class diagram, ', function () { describe('class diagram, ', function () {
describe('when rendering a classDiagram', function () { describe('when rendering a classDiagram', function () {
// var conf
beforeEach(function () { beforeEach(function () {
/// /parser.yy = require('./classDb');
/// /parser.yy.clear();
/// /parseError = function(err, hash) {
/// / log.debug('Syntax error:' + err);
/// / log.debug(hash);
/// /};
/// /sq.yy.parseError = parseError;
//
// newD3 = function() {
// var o = {
// append: function () {
// return newD3();
// },
// attr: function () {
// return this;
// },
// style: function () {
// return this;
// },
// text: function () {
// return this;
// },
// 0:{
// 0: {
// getBBox: function () {
// return {
// height: 10,
// width: 20
// };
// }
// }
//
// }
// };
//
// return o;
// };
//
// conf = {
// diagramMarginX:50,
// diagramMarginY:10,
// actorMargin:50,
// width:150,
// // Height of actor boxes
// height:65,
// boxMargin:10,
// messageMargin:40,
// boxTextMargin:15,
// noteMargin:25,
// mirrorActors:true,
// // Depending on css styling this might need adjustment
// // Prolongs the edge of the diagram downwards
// bottomMarginAdj:1
// };
// classRenderer.setConf(conf);
// ... add whatever browser globals your tests might need ...
// }
Object.defineProperties(window.HTMLElement.prototype, { Object.defineProperties(window.HTMLElement.prototype, {
getBBox: { getBBox: {
get: function () { return {x: 10, y: 10, width: 100, height: 100} } get: function () { return { x: 10, y: 10, width: 100, height: 100 } }
}, },
offsetLeft: { offsetLeft: {
get: function () { return parseFloat(window.getComputedStyle(this).marginLeft) || 0 } get: function () { return parseFloat(window.getComputedStyle(this).marginLeft) || 0 }
@@ -100,13 +24,5 @@ describe('class diagram, ', function () {
} }
}) })
}) })
it('it should handle one actor', function () {
// var str = 'classDiagram\n' +
// 'Class01 --|> Class02'
// classRenderer.draw(str,'tst');
// console.log(document.body.innerHTML);
})
}) })
}) })

View File

@@ -7,7 +7,6 @@ var d3 = require('../../d3')
var Logger = require('../../logger') var Logger = require('../../logger')
var log = Logger.Log var log = Logger.Log
// var log = new Logger.Log();
/** /**
* Draws a an info picture in the tag with id: id based on the graph definition in text. * Draws a an info picture in the tag with id: id based on the graph definition in text.
@@ -19,29 +18,22 @@ exports.draw = function (txt, id, ver) {
parser = exampleParser.parser parser = exampleParser.parser
parser.yy = db parser.yy = db
log.debug('Renering example diagram') log.debug('Renering example diagram')
// Parse the graph definition // Parse the graph definition
parser.parse(txt) parser.parse(txt)
// Fetch the default direction, use TD if none was found // Fetch the default direction, use TD if none was found
var svg = d3.select('#' + id) var svg = d3.select('#' + id)
var g = svg.append('g') var g = svg.append('g')
g.append('text') // text label for the x axis g.append('text') // text label for the x axis
.attr('x', 100) .attr('x', 100)
.attr('y', 40) .attr('y', 40)
.attr('class', 'version') .attr('class', 'version')
.attr('font-size', '32px') .attr('font-size', '32px')
.style('text-anchor', 'middle') .style('text-anchor', 'middle')
.text('mermaid ' + ver) .text('mermaid ' + ver)
/*
var box = exports.bounds.getBounds();
var height = box.stopy-box.starty+2*conf.diagramMarginY;
var width = box.stopx-box.startx+2*conf.diagramMarginX; */
svg.attr('height', 100) svg.attr('height', 100)
svg.attr('width', 400) svg.attr('width', 400)
// svg.attr('viewBox', '0 0 300 150');
} }

View File

@@ -50,8 +50,6 @@ exports.addVertices = function (vert, g) {
*/ */
var classStr = '' var classStr = ''
// log.debug(vertice.classes);
if (vertice.classes.length > 0) { if (vertice.classes.length > 0) {
classStr = vertice.classes.join(' ') classStr = vertice.classes.join(' ')
} }
@@ -94,9 +92,6 @@ exports.addVertices = function (vert, g) {
labelTypeStr = 'svg' labelTypeStr = 'svg'
verticeText = svgLabel verticeText = svgLabel
// verticeText = verticeText.replace(/<br\/>/g, '\n');
// labelTypeStr = 'text';
} }
var radious = 0 var radious = 0
@@ -242,7 +237,6 @@ exports.getClasses = function (text, isDot) {
// Add default class if undefined // Add default class if undefined
if (typeof (classes.default) === 'undefined') { if (typeof (classes.default) === 'undefined') {
classes.default = { id: 'default' } classes.default = { id: 'default' }
// classes.default.styles = ['fill:#ffa','stroke:#666','stroke-width:3px'];
classes.default.styles = [] classes.default.styles = []
classes.default.clusterStyles = ['rx:4px', 'fill: rgb(255, 255, 222)', 'rx: 4px', 'stroke: rgb(170, 170, 51)', 'stroke-width: 1px'] classes.default.clusterStyles = ['rx:4px', 'fill: rgb(255, 255, 222)', 'rx: 4px', 'stroke: rgb(170, 170, 51)', 'stroke-width: 1px']
classes.default.nodeLabelStyles = ['fill:#000', 'stroke:none', 'font-weight:300', 'font-family:"Helvetica Neue",Helvetica,Arial,sans-serf', 'font-size:14px'] classes.default.nodeLabelStyles = ['fill:#000', 'stroke:none', 'font-weight:300', 'font-family:"Helvetica Neue",Helvetica,Arial,sans-serf', 'font-size:14px']
@@ -307,7 +301,6 @@ exports.draw = function (text, id, isDot) {
// Fetch the verices/nodes and edges/links from the parsed graph definition // Fetch the verices/nodes and edges/links from the parsed graph definition
var vert = graph.getVertices() var vert = graph.getVertices()
// log.debug(vert);
var edges = graph.getEdges() var edges = graph.getEdges()
i = 0 i = 0
@@ -318,7 +311,6 @@ exports.draw = function (text, id, isDot) {
d3.selectAll('cluster').append('text') d3.selectAll('cluster').append('text')
for (j = 0; j < subG.nodes.length; j++) { for (j = 0; j < subG.nodes.length; j++) {
// log.debug('Setting node',subG.nodes[j],' to subgraph '+id);
g.setParent(subG.nodes[j], subG.id) g.setParent(subG.nodes[j], subG.id)
} }
} }
@@ -435,35 +427,20 @@ exports.draw = function (text, id, isDot) {
// Set up an SVG group so that we can translate the final graph. // Set up an SVG group so that we can translate the final graph.
var svg = d3.select('#' + id) var svg = d3.select('#' + id)
// svgGroup = d3.select('#' + id + ' g');
// Run the renderer. This is what draws the final graph. // Run the renderer. This is what draws the final graph.
var element = d3.select('#' + id + ' g') var element = d3.select('#' + id + ' g')
render(element, g) render(element, g)
// var tip = d3.tip().html(function(d) { return d; });
element.selectAll('g.node') element.selectAll('g.node')
.attr('title', function () { .attr('title', function () {
return graph.getTooltip(this.id) return graph.getTooltip(this.id)
}) })
/*
var xPos = document.querySelectorAll('.clusters rect')[0].x.baseVal.value;
var width = document.querySelectorAll('.clusters rect')[0].width.baseVal.value;
var cluster = d3.selectAll('.cluster');
var te = cluster.append('text');
te.attr('x', xPos+width/2);
te.attr('y', 12);
//te.stroke('black');
te.attr('id', 'apa12');
te.style('text-anchor', 'middle');
te.text('Title for cluster');
*/
if (conf.useMaxWidth) { if (conf.useMaxWidth) {
// Center the graph // Center the graph
svg.attr('height', '100%') svg.attr('height', '100%')
svg.attr('width', conf.width) svg.attr('width', conf.width)
// svg.attr('viewBox', svgb.getBBox().x + ' 0 '+ g.graph().width+' '+ g.graph().height);
svg.attr('viewBox', '0 0 ' + (g.graph().width + 20) + ' ' + (g.graph().height + 20)) svg.attr('viewBox', '0 0 ' + (g.graph().width + 20) + ' ' + (g.graph().height + 20))
svg.attr('style', 'max-width:' + (g.graph().width + 20) + 'px;') svg.attr('style', 'max-width:' + (g.graph().width + 20) + 'px;')
} else { } else {
@@ -474,7 +451,6 @@ exports.draw = function (text, id, isDot) {
} else { } else {
svg.attr('width', conf.width) svg.attr('width', conf.width)
} }
// svg.attr('viewBox', svgb.getBBox().x + ' 0 '+ g.graph().width+' '+ g.graph().height);
svg.attr('viewBox', '0 0 ' + (g.graph().width + 20) + ' ' + (g.graph().height + 20)) svg.attr('viewBox', '0 0 ' + (g.graph().width + 20) + ' ' + (g.graph().height + 20))
} }
@@ -486,7 +462,6 @@ exports.draw = function (text, id, isDot) {
if (subG.title !== 'undefined') { if (subG.title !== 'undefined') {
var clusterRects = document.querySelectorAll('#' + id + ' #' + subG.id + ' rect') var clusterRects = document.querySelectorAll('#' + id + ' #' + subG.id + ' rect')
// log.debug('looking up: #' + id + ' #' + subG.id)
var clusterEl = document.querySelectorAll('#' + id + ' #' + subG.id) var clusterEl = document.querySelectorAll('#' + id + ' #' + subG.id)
var xPos = clusterRects[0].x.baseVal.value var xPos = clusterRects[0].x.baseVal.value
@@ -504,7 +479,6 @@ exports.draw = function (text, id, isDot) {
if (typeof subG.title === 'undefined') { if (typeof subG.title === 'undefined') {
te.text('Undef') te.text('Undef')
} else { } else {
// te.text(subGraphs[subGraphs.length-i-1].title);
te.text(subG.title) te.text(subG.title)
} }
} }

View File

@@ -33,12 +33,12 @@ exports.addVertex = function (id, text, type, style) {
} }
if (typeof vertices[id] === 'undefined') { if (typeof vertices[id] === 'undefined') {
vertices[id] = {id: id, styles: [], classes: []} vertices[id] = { id: id, styles: [], classes: [] }
} }
if (typeof text !== 'undefined') { if (typeof text !== 'undefined') {
txt = text.trim() txt = text.trim()
// strip quotes if string starts and exnds with a quote // strip quotes if string starts and exnds with a quote
if (txt[0] === '"' && txt[txt.length - 1] === '"') { if (txt[0] === '"' && txt[txt.length - 1] === '"') {
txt = txt.substring(1, txt.length - 1) txt = txt.substring(1, txt.length - 1)
} }
@@ -69,13 +69,13 @@ exports.addVertex = function (id, text, type, style) {
*/ */
exports.addLink = function (start, end, type, linktext) { exports.addLink = function (start, end, type, linktext) {
log.info('Got edge...', start, end) log.info('Got edge...', start, end)
var edge = {start: start, end: end, type: undefined, text: ''} var edge = { start: start, end: end, type: undefined, text: '' }
linktext = type.text linktext = type.text
if (typeof linktext !== 'undefined') { if (typeof linktext !== 'undefined') {
edge.text = linktext.trim() edge.text = linktext.trim()
// strip quotes if string starts and exnds with a quote // strip quotes if string starts and exnds with a quote
if (edge.text[0] === '"' && edge.text[edge.text.length - 1] === '"') { if (edge.text[0] === '"' && edge.text[edge.text.length - 1] === '"') {
edge.text = edge.text.substring(1, edge.text.length - 1) edge.text = edge.text.substring(1, edge.text.length - 1)
} }
@@ -119,7 +119,7 @@ exports.updateLink = function (pos, style) {
exports.addClass = function (id, style) { exports.addClass = function (id, style) {
if (typeof classes[id] === 'undefined') { if (typeof classes[id] === 'undefined') {
classes[id] = {id: id, styles: []} classes[id] = { id: id, styles: [] }
} }
if (typeof style !== 'undefined') { if (typeof style !== 'undefined') {
@@ -252,39 +252,39 @@ var setupToolTips = function (element) {
var tooltipElem = d3.select('.mermaidTooltip') var tooltipElem = d3.select('.mermaidTooltip')
if (tooltipElem[0][0] === null) { if (tooltipElem[0][0] === null) {
tooltipElem = d3.select('body') tooltipElem = d3.select('body')
.append('div') .append('div')
.attr('class', 'mermaidTooltip') .attr('class', 'mermaidTooltip')
.style('opacity', 0) .style('opacity', 0)
} }
var svg = d3.select(element).select('svg') var svg = d3.select(element).select('svg')
var nodes = svg.selectAll('g.node') var nodes = svg.selectAll('g.node')
nodes nodes
.on('mouseover', function () { .on('mouseover', function () {
var el = d3.select(this) var el = d3.select(this)
var title = el.attr('title') var title = el.attr('title')
// Dont try to draw a tooltip if no data is provided // Dont try to draw a tooltip if no data is provided
if (title === null) { if (title === null) {
return return
} }
var rect = this.getBoundingClientRect() var rect = this.getBoundingClientRect()
tooltipElem.transition() tooltipElem.transition()
.duration(200) .duration(200)
.style('opacity', '.9') .style('opacity', '.9')
tooltipElem.html(el.attr('title')) tooltipElem.html(el.attr('title'))
.style('left', (rect.left + (rect.right - rect.left) / 2) + 'px') .style('left', (rect.left + (rect.right - rect.left) / 2) + 'px')
.style('top', (rect.top - 14 + document.body.scrollTop) + 'px') .style('top', (rect.top - 14 + document.body.scrollTop) + 'px')
el.classed('hover', true) el.classed('hover', true)
}) })
.on('mouseout', function () { .on('mouseout', function () {
tooltipElem.transition() tooltipElem.transition()
.duration(500) .duration(500)
.style('opacity', 0) .style('opacity', 0)
var el = d3.select(this) var el = d3.select(this)
el.classed('hover', false) el.classed('hover', false)
}) })
} }
funs.push(setupToolTips) funs.push(setupToolTips)
@@ -314,7 +314,7 @@ exports.defaultStyle = function () {
*/ */
exports.addSubGraph = function (list, title) { exports.addSubGraph = function (list, title) {
function uniq (a) { function uniq (a) {
var prims = {'boolean': {}, 'number': {}, 'string': {}} var prims = { 'boolean': {}, 'number': {}, 'string': {} }
var objs = [] var objs = []
return a.filter(function (item) { return a.filter(function (item) {
@@ -330,9 +330,7 @@ exports.addSubGraph = function (list, title) {
nodeList = uniq(nodeList.concat.apply(nodeList, list)) nodeList = uniq(nodeList.concat.apply(nodeList, list))
var subGraph = {id: 'subGraph' + subCount, nodes: nodeList, title: title} var subGraph = { id: 'subGraph' + subCount, nodes: nodeList, title: title }
// log.debug('subGraph:' + subGraph.title + subGraph.id);
// log.debug(subGraph.nodes);
subGraphs.push(subGraph) subGraphs.push(subGraph)
subCount = subCount + 1 subCount = subCount + 1
return subGraph.id return subGraph.id
@@ -342,11 +340,9 @@ var getPosForId = function (id) {
var i var i
for (i = 0; i < subGraphs.length; i++) { for (i = 0; i < subGraphs.length; i++) {
if (subGraphs[i].id === id) { if (subGraphs[i].id === id) {
// log.debug('Found pos for ',id,' ',i);
return i return i
} }
} }
// log.debug('No pos found for ',id,' ',i);
return -1 return -1
} }
var secCount = -1 var secCount = -1
@@ -357,9 +353,8 @@ var indexNodes = function (id, pos) {
if (secCount > 2000) { if (secCount > 2000) {
return return
} }
// var nPos = getPosForId(subGraphs[pos].id);
posCrossRef[secCount] = pos posCrossRef[secCount] = pos
// Check if match // Check if match
if (subGraphs[pos].id === id) { if (subGraphs[pos].id === id) {
return { return {
result: true, result: true,
@@ -371,7 +366,7 @@ var indexNodes = function (id, pos) {
var posCount = 1 var posCount = 1
while (count < nodes.length) { while (count < nodes.length) {
var childPos = getPosForId(nodes[count]) var childPos = getPosForId(nodes[count])
// Ignore regular nodes (pos will be -1) // Ignore regular nodes (pos will be -1)
if (childPos >= 0) { if (childPos >= 0) {
var res = indexNodes(id, childPos) var res = indexNodes(id, childPos)
if (res.result) { if (res.result) {

View File

@@ -7,8 +7,6 @@ describe('when parsing a gantt diagram it', function () {
beforeEach(function () { beforeEach(function () {
gantt = require('./parser/gantt').parser gantt = require('./parser/gantt').parser
gantt.yy = require('./ganttDb') gantt.yy = require('./ganttDb')
// ex.yy.parseError = parseError;
}) })
it('should handle an dateFormat definition', function () { it('should handle an dateFormat definition', function () {
@@ -31,26 +29,24 @@ describe('when parsing a gantt diagram it', function () {
gantt.parse(str) gantt.parse(str)
}) })
/** /**
* Beslutsflöde inligt nedan. Obs bla bla bla * Beslutsflöde inligt nedan. Obs bla bla bla
* ``` * ```
* graph TD * graph TD
* A[Hard pledge] -- text on link -->B(Round edge) * A[Hard pledge] -- text on link -->B(Round edge)
* B --> C{to do or not to do} * B --> C{to do or not to do}
* C -->|Too| D[Result one] * C -->|Too| D[Result one]
* C -->|Doo| E[Result two] * C -->|Doo| E[Result two]
``` ```
* params bapa - a unique bapap * params bapa - a unique bapap
*/ */
it('should handle a task definition', function () { it('should handle a task definition', function () {
var str = 'gantt\n' + var str = 'gantt\n' +
'dateFormat yyyy-mm-dd\n' + 'dateFormat yyyy-mm-dd\n' +
'title Adding gantt diagram functionality to mermaid\n' + 'title Adding gantt diagram functionality to mermaid\n' +
'section Documentation\n' + 'section Documentation\n' +
'Design jison grammar:des1, 2014-01-01, 2014-01-04' 'Design jison grammar:des1, 2014-01-01, 2014-01-04'
gantt.parse(str) gantt.parse(str)
}) })
}) })
// Ogiltigt id i after id

View File

@@ -53,23 +53,13 @@ exports.getTasks = function () {
tasks = rawTasks tasks = rawTasks
// var i;
// for(i=10000;i<tasks.length;i++){
// tasks[i].startTime = moment(tasks[i].startTime).format(dateFormat);
// tasks[i].endTime = moment(tasks[i].endTime).format(dateFormat);
// }
return tasks return tasks
} }
var getStartDate = function (prevTime, dateFormat, str) { var getStartDate = function (prevTime, dateFormat, str) {
// console.log('Deciding start date:'+JSON.stringify(str));
// log.debug('Deciding start date:'+str);
// log.debug('with dateformat:'+dateFormat);
str = str.trim() str = str.trim()
// Test for after // Test for after
var re = /^after\s+([\d\w-]+)/ var re = /^after\s+([\d\w-]+)/
var afterStatement = re.exec(str.trim()) var afterStatement = re.exec(str.trim())
@@ -80,34 +70,32 @@ var getStartDate = function (prevTime, dateFormat, str) {
var dt = new Date() var dt = new Date()
dt.setHours(0, 0, 0, 0) dt.setHours(0, 0, 0, 0)
return dt return dt
// return undefined;
} }
return task.endTime return task.endTime
} }
// Check for actual date set // Check for actual date set
if (moment(str, dateFormat.trim(), true).isValid()) { if (moment(str, dateFormat.trim(), true).isValid()) {
return moment(str, dateFormat.trim(), true).toDate() return moment(str, dateFormat.trim(), true).toDate()
} else { } else {
log.debug('Invalid date:' + str) log.debug('Invalid date:' + str)
log.debug('With date format:' + dateFormat.trim()) log.debug('With date format:' + dateFormat.trim())
// log.debug('----');
} }
// Default date - now // Default date - now
return new Date() return new Date()
} }
var getEndDate = function (prevTime, dateFormat, str) { var getEndDate = function (prevTime, dateFormat, str) {
str = str.trim() str = str.trim()
// Check for actual date // Check for actual date
if (moment(str, dateFormat.trim(), true).isValid()) { if (moment(str, dateFormat.trim(), true).isValid()) {
return moment(str, dateFormat.trim()).toDate() return moment(str, dateFormat.trim()).toDate()
} }
var d = moment(prevTime) var d = moment(prevTime)
// Check for length // Check for length
var re = /^([\d]+)([wdhms])/ var re = /^([\d]+)([wdhms])/
var durationStatement = re.exec(str.trim()) var durationStatement = re.exec(str.trim())
@@ -131,7 +119,7 @@ var getEndDate = function (prevTime, dateFormat, str) {
} }
return d.toDate() return d.toDate()
} }
// Default date - now // Default date - now
return d.toDate() return d.toDate()
} }
@@ -168,7 +156,7 @@ var compileData = function (prevTask, dataStr) {
var task = {} var task = {}
var df = exports.getDateFormat() var df = exports.getDateFormat()
// Get tags like active, done cand crit // Get tags like active, done cand crit
var matchFound = true var matchFound = true
while (matchFound) { while (matchFound) {
matchFound = false matchFound = false
@@ -228,7 +216,7 @@ var parseData = function (prevTaskId, dataStr) {
var task = {} var task = {}
// Get tags like active, done cand crit // Get tags like active, done cand crit
var matchFound = true var matchFound = true
while (matchFound) { while (matchFound) {
matchFound = false matchFound = false
@@ -256,18 +244,18 @@ var parseData = function (prevTaskId, dataStr) {
switch (data.length) { switch (data.length) {
case 1: case 1:
task.id = parseId() task.id = parseId()
task.startTime = {type: 'prevTaskEnd', id: prevTaskId} task.startTime = { type: 'prevTaskEnd', id: prevTaskId }
task.endTime = {data: data[0]} task.endTime = { data: data[0] }
break break
case 2: case 2:
task.id = parseId() task.id = parseId()
task.startTime = {type: 'getStartDate', startData: data[0]} task.startTime = { type: 'getStartDate', startData: data[0] }
task.endTime = {data: data[1]} task.endTime = { data: data[1] }
break break
case 3: case 3:
task.id = parseId(data[0]) task.id = parseId(data[0])
task.startTime = {type: 'getStartDate', startData: data[1]} task.startTime = { type: 'getStartDate', startData: data[1] }
task.endTime = {data: data[2]} task.endTime = { data: data[2] }
break break
default: default:
} }
@@ -284,7 +272,7 @@ exports.addTask = function (descr, data) {
section: currentSection, section: currentSection,
type: currentSection, type: currentSection,
processed: false, processed: false,
raw: {data: data}, raw: { data: data },
task: descr task: descr
} }
var taskInfo = parseData(lastTaskID, data) var taskInfo = parseData(lastTaskID, data)
@@ -299,18 +287,11 @@ exports.addTask = function (descr, data) {
var pos = rawTasks.push(rawTask) var pos = rawTasks.push(rawTask)
lastTaskID = rawTask.id lastTaskID = rawTask.id
// Store cross ref // Store cross ref
taskDb[rawTask.id] = pos - 1 taskDb[rawTask.id] = pos - 1
} }
exports.findTaskById = function (id) { exports.findTaskById = function (id) {
// var i;
// for(i=0;i<tasks.length;i++){
// if(tasks[i].id === id){
// return tasks[i];
// }
// }
var pos = taskDb[id] var pos = taskDb[id]
return rawTasks[pos] return rawTasks[pos]
} }

View File

@@ -7,11 +7,8 @@ describe('when using the ganttDb', function () {
var moment = require('moment') var moment = require('moment')
beforeEach(function () { beforeEach(function () {
// gantt = require('./parser/gantt').parser;
gDb = require('./ganttDb') gDb = require('./ganttDb')
gDb.clear() gDb.clear()
// ex.yy.parseError = parseError;
}) })
it('should handle an fixed dates', function () { it('should handle an fixed dates', function () {
@@ -180,5 +177,3 @@ describe('when using the ganttDb', function () {
expect(tasks[2].endTime).toEqual(moment('2013-01-17', 'YYYY-MM-DD').toDate()) expect(tasks[2].endTime).toEqual(moment('2013-01-17', 'YYYY-MM-DD').toDate())
}) })
}) })
// Ogiltigt id i after id

View File

@@ -2,7 +2,6 @@ var gantt = require('./parser/gantt').parser
gantt.yy = require('./ganttDb') gantt.yy = require('./ganttDb')
var d3 = require('../../d3') var d3 = require('../../d3')
var moment = require('moment') var moment = require('moment')
// var log = require('../../logger').create();
var daysInChart var daysInChart
var conf = { var conf = {
@@ -49,8 +48,6 @@ module.exports.draw = function (text, id) {
elem.setAttribute('viewBox', '0 0 ' + w + ' ' + h) elem.setAttribute('viewBox', '0 0 ' + w + ' ' + h)
var svg = d3.select('#' + id) var svg = d3.select('#' + id)
// var dateFormat = d3.time.format('%Y-%m-%d');
var startDate = d3.min(taskArray, function (d) { var startDate = d3.min(taskArray, function (d) {
return d.startTime return d.startTime
}) })
@@ -67,7 +64,6 @@ module.exports.draw = function (text, id) {
return d.endTime return d.endTime
})]) })])
.rangeRound([0, w - conf.leftPadding - conf.rightPadding]) .rangeRound([0, w - conf.leftPadding - conf.rightPadding])
// .nice(d3.time.monday);
var categories = [] var categories = []
@@ -188,7 +184,6 @@ module.exports.draw = function (text, id) {
return d.task return d.task
}) })
.attr('font-size', conf.fontSize) .attr('font-size', conf.fontSize)
// .attr('font-family',conf.fontFamily)
.attr('x', function (d) { .attr('x', function (d) {
var startX = timeScale(d.startTime) var startX = timeScale(d.startTime)
var endX = timeScale(d.endTime) var endX = timeScale(d.endTime)
@@ -208,7 +203,6 @@ module.exports.draw = function (text, id) {
.attr('y', function (d, i) { .attr('y', function (d, i) {
return i * theGap + (conf.barHeight / 2) + (conf.fontSize / 2 - 2) + theTopPad return i * theGap + (conf.barHeight / 2) + (conf.fontSize / 2 - 2) + theTopPad
}) })
// .attr('text-anchor', 'middle')
.attr('text-height', theBarHeight) .attr('text-height', theBarHeight)
.attr('class', function (d) { .attr('class', function (d) {
var startX = timeScale(d.startTime) var startX = timeScale(d.startTime)
@@ -279,7 +273,6 @@ module.exports.draw = function (text, id) {
}], }],
// Day within a week (not monday) // Day within a week (not monday)
['%a %d', function (d) { ['%a %d', function (d) {
// return d.getDay() ==1;
return d.getDay() && d.getDate() !== 1 return d.getDay() && d.getDate() !== 1
}], }],
// within a month // within a month
@@ -346,7 +339,6 @@ module.exports.draw = function (text, id) {
if (i > 0) { if (i > 0) {
for (var j = 0; j < i; j++) { for (var j = 0; j < i; j++) {
prevGap += numOccurances[i - 1][1] prevGap += numOccurances[i - 1][1]
// log.debug(prevGap);
return d[1] * theGap / 2 + prevGap * theGap + theTopPad return d[1] * theGap / 2 + prevGap * theGap + theTopPad
} }
} else { } else {

View File

@@ -25,12 +25,12 @@ function getId () {
function isfastforwardable (currentCommit, otherCommit) { function isfastforwardable (currentCommit, otherCommit) {
log.debug('Entering isfastforwardable:', currentCommit.id, otherCommit.id) log.debug('Entering isfastforwardable:', currentCommit.id, otherCommit.id)
while (currentCommit.seq <= otherCommit.seq && currentCommit !== otherCommit) { while (currentCommit.seq <= otherCommit.seq && currentCommit !== otherCommit) {
// only if other branch has more commits // only if other branch has more commits
if (otherCommit.parent == null) break if (otherCommit.parent == null) break
if (Array.isArray(otherCommit.parent)) { if (Array.isArray(otherCommit.parent)) {
log.debug('In merge commit:', otherCommit.parent) log.debug('In merge commit:', otherCommit.parent)
return isfastforwardable(currentCommit, commits[otherCommit.parent[0]]) || return isfastforwardable(currentCommit, commits[otherCommit.parent[0]]) ||
isfastforwardable(currentCommit, commits[otherCommit.parent[1]]) isfastforwardable(currentCommit, commits[otherCommit.parent[1]])
} else { } else {
otherCommit = commits[otherCommit.parent] otherCommit = commits[otherCommit.parent]
} }
@@ -66,10 +66,12 @@ exports.getOptions = function () {
} }
exports.commit = function (msg) { exports.commit = function (msg) {
var commit = { id: getId(), var commit = {
id: getId(),
message: msg, message: msg,
seq: seq++, seq: seq++,
parent: head == null ? null : head.id} parent: head == null ? null : head.id
}
head = commit head = commit
commits[commit.id] = commit commits[commit.id] = commit
branches[curBranch] = commit.id branches[curBranch] = commit.id
@@ -92,7 +94,7 @@ exports.merge = function (otherBranch) {
branches[curBranch] = branches[otherBranch] branches[curBranch] = branches[otherBranch]
head = commits[branches[curBranch]] head = commits[branches[curBranch]]
} else { } else {
// create merge commit // create merge commit
var commit = { var commit = {
id: getId(), id: getId(),
message: 'merged branch ' + otherBranch + ' into ' + curBranch, message: 'merged branch ' + otherBranch + ' into ' + curBranch,
@@ -141,7 +143,6 @@ function upsert (arr, key, newval) {
} else { } else {
arr.push(newval) arr.push(newval)
} }
// console.log(arr);
} }
function prettyPrintCommitHistory (commitArr) { function prettyPrintCommitHistory (commitArr) {
@@ -160,11 +161,9 @@ function prettyPrintCommitHistory (commitArr) {
}) })
log.debug(label.join(' ')) log.debug(label.join(' '))
if (Array.isArray(commit.parent)) { if (Array.isArray(commit.parent)) {
// console.log("here", commit.parent);
var newCommit = commits[commit.parent[0]] var newCommit = commits[commit.parent[0]]
upsert(commitArr, commit, newCommit) upsert(commitArr, commit, newCommit)
commitArr.push(commits[commit.parent[1]]) commitArr.push(commits[commit.parent[1]])
// console.log("shoudl have 2", commitArr);
} else if (commit.parent == null) { } else if (commit.parent == null) {
return return
} else { } else {
@@ -191,9 +190,8 @@ exports.clear = function () {
exports.getBranchesAsObjArray = function () { exports.getBranchesAsObjArray = function () {
var branchArr = _.map(branches, function (v, k) { var branchArr = _.map(branches, function (v, k) {
return {'name': k, 'commit': commits[v]} return { 'name': k, 'commit': commits[v] }
}) })
// return _.orderBy(branchArr, [function(b) { return b.commit.seq}], ['desc']);
return branchArr return branchArr
} }

View File

@@ -11,11 +11,10 @@ describe('when parsing a gitGraph', function () {
}) })
it('should handle a gitGraph defintion', function () { it('should handle a gitGraph defintion', function () {
var str = 'gitGraph:\n' + var str = 'gitGraph:\n' +
'commit\n' 'commit\n'
parser.parse(str) parser.parse(str)
var commits = parser.yy.getCommits() var commits = parser.yy.getCommits()
// console.log(commits);
expect(Object.keys(commits).length).toBe(1) expect(Object.keys(commits).length).toBe(1)
expect(parser.yy.getCurrentBranch()).toBe('master') expect(parser.yy.getCurrentBranch()).toBe('master')
@@ -25,13 +24,12 @@ describe('when parsing a gitGraph', function () {
it('should handle a gitGraph defintion with empty options', function () { it('should handle a gitGraph defintion with empty options', function () {
var str = 'gitGraph:\n' + var str = 'gitGraph:\n' +
'options\n' + 'options\n' +
'end\n' + 'end\n' +
'commit\n' 'commit\n'
parser.parse(str) parser.parse(str)
var commits = parser.yy.getCommits() var commits = parser.yy.getCommits()
// console.log(commits);
expect(parser.yy.getOptions()).toEqual({}) expect(parser.yy.getOptions()).toEqual({})
expect(Object.keys(commits).length).toBe(1) expect(Object.keys(commits).length).toBe(1)
@@ -42,15 +40,13 @@ describe('when parsing a gitGraph', function () {
it('should handle a gitGraph defintion with valid options', function () { it('should handle a gitGraph defintion with valid options', function () {
var str = 'gitGraph:\n' + var str = 'gitGraph:\n' +
'options\n' + 'options\n' +
'{"key": "value"}\n' + '{"key": "value"}\n' +
'end\n' + 'end\n' +
'commit\n' 'commit\n'
parser.parse(str) parser.parse(str)
var commits = parser.yy.getCommits() var commits = parser.yy.getCommits()
// console.log(commits);
// console.log('options object', parser.yy.getOptions());
expect(parser.yy.getOptions()['key']).toBe('value') expect(parser.yy.getOptions()['key']).toBe('value')
expect(Object.keys(commits).length).toBe(1) expect(Object.keys(commits).length).toBe(1)
expect(parser.yy.getCurrentBranch()).toBe('master') expect(parser.yy.getCurrentBranch()).toBe('master')
@@ -60,14 +56,13 @@ describe('when parsing a gitGraph', function () {
it('should not fail on a gitGraph with malformed json', function () { it('should not fail on a gitGraph with malformed json', function () {
var str = 'gitGraph:\n' + var str = 'gitGraph:\n' +
'options\n' + 'options\n' +
'{"key": "value"\n' + '{"key": "value"\n' +
'end\n' + 'end\n' +
'commit\n' 'commit\n'
parser.parse(str) parser.parse(str)
var commits = parser.yy.getCommits() var commits = parser.yy.getCommits()
// console.log(commits);
expect(Object.keys(commits).length).toBe(1) expect(Object.keys(commits).length).toBe(1)
expect(parser.yy.getCurrentBranch()).toBe('master') expect(parser.yy.getCurrentBranch()).toBe('master')
expect(parser.yy.getDirection()).toBe('LR') expect(parser.yy.getDirection()).toBe('LR')
@@ -76,11 +71,10 @@ describe('when parsing a gitGraph', function () {
it('should handle set direction', function () { it('should handle set direction', function () {
var str = 'gitGraph BT:\n' + var str = 'gitGraph BT:\n' +
'commit\n' 'commit\n'
parser.parse(str) parser.parse(str)
var commits = parser.yy.getCommits() var commits = parser.yy.getCommits()
// console.log(commits);
expect(Object.keys(commits).length).toBe(1) expect(Object.keys(commits).length).toBe(1)
expect(parser.yy.getCurrentBranch()).toBe('master') expect(parser.yy.getCurrentBranch()).toBe('master')
@@ -90,8 +84,8 @@ describe('when parsing a gitGraph', function () {
it('should checkout a branch', function () { it('should checkout a branch', function () {
var str = 'gitGraph:\n' + var str = 'gitGraph:\n' +
'branch new\n' + 'branch new\n' +
'checkout new\n' 'checkout new\n'
parser.parse(str) parser.parse(str)
var commits = parser.yy.getCommits() var commits = parser.yy.getCommits()
@@ -102,10 +96,10 @@ describe('when parsing a gitGraph', function () {
it('should add commits to checked out branch', function () { it('should add commits to checked out branch', function () {
var str = 'gitGraph:\n' + var str = 'gitGraph:\n' +
'branch new\n' + 'branch new\n' +
'checkout new\n' + 'checkout new\n' +
'commit\n' + 'commit\n' +
'commit\n' 'commit\n'
parser.parse(str) parser.parse(str)
var commits = parser.yy.getCommits() var commits = parser.yy.getCommits()
@@ -118,11 +112,10 @@ describe('when parsing a gitGraph', function () {
}) })
it('should handle commit with args', function () { it('should handle commit with args', function () {
var str = 'gitGraph:\n' + var str = 'gitGraph:\n' +
'commit "a commit"\n' 'commit "a commit"\n'
parser.parse(str) parser.parse(str)
var commits = parser.yy.getCommits() var commits = parser.yy.getCommits()
// console.log(commits);
expect(Object.keys(commits).length).toBe(1) expect(Object.keys(commits).length).toBe(1)
var key = Object.keys(commits)[0] var key = Object.keys(commits)[0]
@@ -132,12 +125,12 @@ describe('when parsing a gitGraph', function () {
it('it should reset a branch', function () { it('it should reset a branch', function () {
var str = 'gitGraph:\n' + var str = 'gitGraph:\n' +
'commit\n' + 'commit\n' +
'commit\n' + 'commit\n' +
'branch newbranch\n' + 'branch newbranch\n' +
'checkout newbranch\n' + 'checkout newbranch\n' +
'commit\n' + 'commit\n' +
'reset master\n' 'reset master\n'
parser.parse(str) parser.parse(str)
@@ -150,12 +143,12 @@ describe('when parsing a gitGraph', function () {
it('reset can take an argument', function () { it('reset can take an argument', function () {
var str = 'gitGraph:\n' + var str = 'gitGraph:\n' +
'commit\n' + 'commit\n' +
'commit\n' + 'commit\n' +
'branch newbranch\n' + 'branch newbranch\n' +
'checkout newbranch\n' + 'checkout newbranch\n' +
'commit\n' + 'commit\n' +
'reset master^\n' 'reset master^\n'
parser.parse(str) parser.parse(str)
@@ -168,18 +161,17 @@ describe('when parsing a gitGraph', function () {
it('it should handle fast forwardable merges', function () { it('it should handle fast forwardable merges', function () {
var str = 'gitGraph:\n' + var str = 'gitGraph:\n' +
'commit\n' + 'commit\n' +
'branch newbranch\n' + 'branch newbranch\n' +
'checkout newbranch\n' + 'checkout newbranch\n' +
'commit\n' + 'commit\n' +
'commit\n' + 'commit\n' +
'checkout master\n' + 'checkout master\n' +
'merge newbranch\n' 'merge newbranch\n'
parser.parse(str) parser.parse(str)
var commits = parser.yy.getCommits() var commits = parser.yy.getCommits()
// console.log(commits);
expect(Object.keys(commits).length).toBe(3) expect(Object.keys(commits).length).toBe(3)
expect(parser.yy.getCurrentBranch()).toBe('master') expect(parser.yy.getCurrentBranch()).toBe('master')
expect(parser.yy.getBranches()['newbranch']).toEqual(parser.yy.getBranches()['master']) expect(parser.yy.getBranches()['newbranch']).toEqual(parser.yy.getBranches()['master'])
@@ -188,17 +180,16 @@ describe('when parsing a gitGraph', function () {
it('it should handle cases when merge is a noop', function () { it('it should handle cases when merge is a noop', function () {
var str = 'gitGraph:\n' + var str = 'gitGraph:\n' +
'commit\n' + 'commit\n' +
'branch newbranch\n' + 'branch newbranch\n' +
'checkout newbranch\n' + 'checkout newbranch\n' +
'commit\n' + 'commit\n' +
'commit\n' + 'commit\n' +
'merge master\n' 'merge master\n'
parser.parse(str) parser.parse(str)
var commits = parser.yy.getCommits() var commits = parser.yy.getCommits()
// console.log(commits);
expect(Object.keys(commits).length).toBe(3) expect(Object.keys(commits).length).toBe(3)
expect(parser.yy.getCurrentBranch()).toBe('newbranch') expect(parser.yy.getCurrentBranch()).toBe('newbranch')
expect(parser.yy.getBranches()['newbranch']).not.toEqual(parser.yy.getBranches()['master']) expect(parser.yy.getBranches()['newbranch']).not.toEqual(parser.yy.getBranches()['master'])
@@ -207,19 +198,18 @@ describe('when parsing a gitGraph', function () {
it('it should handle merge with 2 parents', function () { it('it should handle merge with 2 parents', function () {
var str = 'gitGraph:\n' + var str = 'gitGraph:\n' +
'commit\n' + 'commit\n' +
'branch newbranch\n' + 'branch newbranch\n' +
'checkout newbranch\n' + 'checkout newbranch\n' +
'commit\n' + 'commit\n' +
'commit\n' + 'commit\n' +
'checkout master\n' + 'checkout master\n' +
'commit\n' + 'commit\n' +
'merge newbranch\n' 'merge newbranch\n'
parser.parse(str) parser.parse(str)
var commits = parser.yy.getCommits() var commits = parser.yy.getCommits()
// console.log(commits);
expect(Object.keys(commits).length).toBe(5) expect(Object.keys(commits).length).toBe(5)
expect(parser.yy.getCurrentBranch()).toBe('master') expect(parser.yy.getCurrentBranch()).toBe('master')
expect(parser.yy.getBranches()['newbranch']).not.toEqual(parser.yy.getBranches()['master']) expect(parser.yy.getBranches()['newbranch']).not.toEqual(parser.yy.getBranches()['master'])
@@ -228,22 +218,21 @@ describe('when parsing a gitGraph', function () {
it('it should handle ff merge when history walk has two parents (merge commit)', function () { it('it should handle ff merge when history walk has two parents (merge commit)', function () {
var str = 'gitGraph:\n' + var str = 'gitGraph:\n' +
'commit\n' + 'commit\n' +
'branch newbranch\n' + 'branch newbranch\n' +
'checkout newbranch\n' + 'checkout newbranch\n' +
'commit\n' + 'commit\n' +
'commit\n' + 'commit\n' +
'checkout master\n' + 'checkout master\n' +
'commit\n' + 'commit\n' +
'merge newbranch\n' + 'merge newbranch\n' +
'commit\n' + 'commit\n' +
'checkout newbranch\n' + 'checkout newbranch\n' +
'merge master\n' 'merge master\n'
parser.parse(str) parser.parse(str)
var commits = parser.yy.getCommits() var commits = parser.yy.getCommits()
// console.log(commits);
expect(Object.keys(commits).length).toBe(6) expect(Object.keys(commits).length).toBe(6)
expect(parser.yy.getCurrentBranch()).toBe('newbranch') expect(parser.yy.getCurrentBranch()).toBe('newbranch')
expect(parser.yy.getBranches()['newbranch']).toEqual(parser.yy.getBranches()['master']) expect(parser.yy.getBranches()['newbranch']).toEqual(parser.yy.getBranches()['master'])

View File

@@ -32,43 +32,43 @@ exports.setConf = function (c) {
function svgCreateDefs (svg) { function svgCreateDefs (svg) {
svg svg
.append('defs') .append('defs')
.append('g') .append('g')
.attr('id', 'def-commit') .attr('id', 'def-commit')
.append('circle') .append('circle')
.attr('r', config.nodeRadius) .attr('r', config.nodeRadius)
.attr('cx', 0) .attr('cx', 0)
.attr('cy', 0) .attr('cy', 0)
svg.select('#def-commit') svg.select('#def-commit')
.append('foreignObject') .append('foreignObject')
.attr('width', config.nodeLabel.width) .attr('width', config.nodeLabel.width)
.attr('height', config.nodeLabel.height) .attr('height', config.nodeLabel.height)
.attr('x', config.nodeLabel.x) .attr('x', config.nodeLabel.x)
.attr('y', config.nodeLabel.y) .attr('y', config.nodeLabel.y)
.attr('class', 'node-label') .attr('class', 'node-label')
.attr('requiredFeatures', 'http://www.w3.org/TR/SVG11/feature#Extensibility') .attr('requiredFeatures', 'http://www.w3.org/TR/SVG11/feature#Extensibility')
.append('xhtml:p') .append('xhtml:p')
.html('') .html('')
} }
function svgDrawLine (svg, points, colorIdx, interpolate) { function svgDrawLine (svg, points, colorIdx, interpolate) {
interpolate = interpolate || 'basis' interpolate = interpolate || 'basis'
var color = config.branchColors[colorIdx % config.branchColors.length] var color = config.branchColors[colorIdx % config.branchColors.length]
var lineGen = d3.svg.line() var lineGen = d3.svg.line()
.x(function (d) { .x(function (d) {
return Math.round(d.x) return Math.round(d.x)
}) })
.y(function (d) { .y(function (d) {
return Math.round(d.y) return Math.round(d.y)
}) })
.interpolate(interpolate) .interpolate(interpolate)
svg svg
.append('svg:path') .append('svg:path')
.attr('d', lineGen(points)) .attr('d', lineGen(points))
.style('stroke', color) .style('stroke', color)
.style('stroke-width', config.lineStrokeWidth) .style('stroke-width', config.lineStrokeWidth)
.style('fill', 'none') .style('fill', 'none')
} }
// Pass in the element and its pre-transform coords // Pass in the element and its pre-transform coords
function getElementCoords (element, coords) { function getElementCoords (element, coords) {
@@ -76,7 +76,6 @@ function getElementCoords (element, coords) {
var ctm = element.node().getCTM() var ctm = element.node().getCTM()
var xn = ctm.e + coords.x * ctm.a var xn = ctm.e + coords.x * ctm.a
var yn = ctm.f + coords.y * ctm.d var yn = ctm.f + coords.y * ctm.d
// log.debug(ctm, coords);
return { return {
left: xn, left: xn,
top: yn, top: yn,
@@ -89,20 +88,19 @@ function svgDrawLineForCommits (svg, fromId, toId, direction, color) {
log.debug('svgDrawLineForCommits: ', fromId, toId) log.debug('svgDrawLineForCommits: ', fromId, toId)
var fromBbox = getElementCoords(svg.select('#node-' + fromId + ' circle')) var fromBbox = getElementCoords(svg.select('#node-' + fromId + ' circle'))
var toBbox = getElementCoords(svg.select('#node-' + toId + ' circle')) var toBbox = getElementCoords(svg.select('#node-' + toId + ' circle'))
// log.debug('svgDrawLineForCommits: ', fromBbox, toBbox);
switch (direction) { switch (direction) {
case 'LR': case 'LR':
// (toBbox) // (toBbox)
// +-------- // +--------
// + (fromBbox) // + (fromBbox)
if (fromBbox.left - toBbox.left > config.nodeSpacing) { if (fromBbox.left - toBbox.left > config.nodeSpacing) {
var lineStart = { x: fromBbox.left - config.nodeSpacing, y: toBbox.top + toBbox.height / 2 } var lineStart = { x: fromBbox.left - config.nodeSpacing, y: toBbox.top + toBbox.height / 2 }
var lineEnd = { x: toBbox.left + toBbox.width, y: toBbox.top + toBbox.height / 2 } var lineEnd = { x: toBbox.left + toBbox.width, y: toBbox.top + toBbox.height / 2 }
svgDrawLine(svg, [lineStart, lineEnd], color, 'linear') svgDrawLine(svg, [lineStart, lineEnd], color, 'linear')
svgDrawLine(svg, [ svgDrawLine(svg, [
{x: fromBbox.left, y: fromBbox.top + fromBbox.height / 2}, { x: fromBbox.left, y: fromBbox.top + fromBbox.height / 2 },
{x: fromBbox.left - config.nodeSpacing / 2, y: fromBbox.top + fromBbox.height / 2}, { x: fromBbox.left - config.nodeSpacing / 2, y: fromBbox.top + fromBbox.height / 2 },
{x: fromBbox.left - config.nodeSpacing / 2, y: lineStart.y}, { x: fromBbox.left - config.nodeSpacing / 2, y: lineStart.y },
lineStart], color) lineStart], color)
} else { } else {
svgDrawLine(svg, [{ svgDrawLine(svg, [{
@@ -121,18 +119,18 @@ function svgDrawLineForCommits (svg, fromId, toId, direction, color) {
} }
break break
case 'BT': case 'BT':
// + (fromBbox) // + (fromBbox)
// | // |
// | // |
// + (toBbox) // + (toBbox)
if (toBbox.top - fromBbox.top > config.nodeSpacing) { if (toBbox.top - fromBbox.top > config.nodeSpacing) {
lineStart = { x: toBbox.left + toBbox.width / 2, y: fromBbox.top + fromBbox.height + config.nodeSpacing } lineStart = { x: toBbox.left + toBbox.width / 2, y: fromBbox.top + fromBbox.height + config.nodeSpacing }
lineEnd = { x: toBbox.left + toBbox.width / 2, y: toBbox.top } lineEnd = { x: toBbox.left + toBbox.width / 2, y: toBbox.top }
svgDrawLine(svg, [lineStart, lineEnd], color, 'linear') svgDrawLine(svg, [lineStart, lineEnd], color, 'linear')
svgDrawLine(svg, [ svgDrawLine(svg, [
{x: fromBbox.left + fromBbox.width / 2, y: fromBbox.top + fromBbox.height}, { x: fromBbox.left + fromBbox.width / 2, y: fromBbox.top + fromBbox.height },
{x: fromBbox.left + fromBbox.width / 2, y: fromBbox.top + fromBbox.height + config.nodeSpacing / 2}, { x: fromBbox.left + fromBbox.width / 2, y: fromBbox.top + fromBbox.height + config.nodeSpacing / 2 },
{x: toBbox.left + toBbox.width / 2, y: lineStart.y - config.nodeSpacing / 2}, { x: toBbox.left + toBbox.width / 2, y: lineStart.y - config.nodeSpacing / 2 },
lineStart], color) lineStart], color)
} else { } else {
svgDrawLine(svg, [{ svgDrawLine(svg, [{
@@ -168,44 +166,44 @@ function renderCommitHistory (svg, commitid, branches, direction) {
return return
} }
svg svg
.append(function () { .append(function () {
return cloneNode(svg, '#def-commit') return cloneNode(svg, '#def-commit')
}) })
.attr('class', 'commit') .attr('class', 'commit')
.attr('id', function () { .attr('id', function () {
return 'node-' + commit.id return 'node-' + commit.id
}) })
.attr('transform', function () { .attr('transform', function () {
switch (direction) { switch (direction) {
case 'LR': case 'LR':
return 'translate(' + (commit.seq * config.nodeSpacing + config.leftMargin) + ', ' + return 'translate(' + (commit.seq * config.nodeSpacing + config.leftMargin) + ', ' +
(branchNum * config.branchOffset) + ')' (branchNum * config.branchOffset) + ')'
case 'BT': case 'BT':
return 'translate(' + (branchNum * config.branchOffset + config.leftMargin) + ', ' + return 'translate(' + (branchNum * config.branchOffset + config.leftMargin) + ', ' +
((numCommits - commit.seq) * config.nodeSpacing) + ')' ((numCommits - commit.seq) * config.nodeSpacing) + ')'
} }
}) })
.attr('fill', config.nodeFillColor) .attr('fill', config.nodeFillColor)
.attr('stroke', config.nodeStrokeColor) .attr('stroke', config.nodeStrokeColor)
.attr('stroke-width', config.nodeStrokeWidth) .attr('stroke-width', config.nodeStrokeWidth)
var branch = _.find(branches, ['commit', commit]) var branch = _.find(branches, ['commit', commit])
if (branch) { if (branch) {
log.debug('found branch ', branch.name) log.debug('found branch ', branch.name)
svg.select('#node-' + commit.id + ' p') svg.select('#node-' + commit.id + ' p')
.append('xhtml:span') .append('xhtml:span')
.attr('class', 'branch-label') .attr('class', 'branch-label')
.text(branch.name + ', ') .text(branch.name + ', ')
} }
svg.select('#node-' + commit.id + ' p') svg.select('#node-' + commit.id + ' p')
.append('xhtml:span') .append('xhtml:span')
.attr('class', 'commit-id') .attr('class', 'commit-id')
.text(commit.id) .text(commit.id)
if (commit.message !== '' && direction === 'BT') { if (commit.message !== '' && direction === 'BT') {
svg.select('#node-' + commit.id + ' p') svg.select('#node-' + commit.id + ' p')
.append('xhtml:span') .append('xhtml:span')
.attr('class', 'commit-msg') .attr('class', 'commit-msg')
.text(', ' + commit.message) .text(', ' + commit.message)
} }
commitid = commit.parent commitid = commit.parent
} while (commitid && allCommitsDict[commitid]) } while (commitid && allCommitsDict[commitid])
@@ -244,7 +242,7 @@ exports.draw = function (txt, id, ver) {
parser.yy = db parser.yy = db
log.debug('in gitgraph renderer', txt, id, ver) log.debug('in gitgraph renderer', txt, id, ver)
// Parse the graph definition // Parse the graph definition
parser.parse(txt + '\n') parser.parse(txt + '\n')
config = _.extend(config, apiConfig, db.getOptions()) config = _.extend(config, apiConfig, db.getOptions())
@@ -269,10 +267,6 @@ exports.draw = function (txt, id, ver) {
if (direction === 'BT') return Object.keys(allCommitsDict).length * config.nodeSpacing if (direction === 'BT') return Object.keys(allCommitsDict).length * config.nodeSpacing
return (branches.length + 1) * config.branchOffset return (branches.length + 1) * config.branchOffset
}) })
// svg.attr('width', function() {
// if (direction === 'LR') return Object.keys(allCommitsDict).length * config.nodeSpacing + config.leftMargin;
// return (branches.length + 1) * config.branchOffset;
// });
} catch (e) { } catch (e) {
log.error('Error while rendering gitgraph') log.error('Error while rendering gitgraph')
log.error(e.message) log.error(e.message)

View File

@@ -9,26 +9,23 @@ var Logger = require('../../logger')
var log = Logger.Log var log = Logger.Log
exports.addActor = function (id, name, description) { exports.addActor = function (id, name, description) {
// Don't allow description nulling // Don't allow description nulling
var old = actors[id] var old = actors[id]
if (old && name === old.name && description == null) return if (old && name === old.name && description == null) return
// Don't allow null descriptions, either // Don't allow null descriptions, either
if (description == null) description = name if (description == null) description = name
actors[id] = {name: name, description: description} actors[id] = { name: name, description: description }
} }
exports.addMessage = function (idFrom, idTo, message, answer) { exports.addMessage = function (idFrom, idTo, message, answer) {
messages.push({from: idFrom, to: idTo, message: message, answer: answer}) messages.push({ from: idFrom, to: idTo, message: message, answer: answer })
} }
/**
*
*/
exports.addSignal = function (idFrom, idTo, message, messageType) { exports.addSignal = function (idFrom, idTo, message, messageType) {
log.debug('Adding message from=' + idFrom + ' to=' + idTo + ' message=' + message + ' type=' + messageType) log.debug('Adding message from=' + idFrom + ' to=' + idTo + ' message=' + message + ' type=' + messageType)
messages.push({from: idFrom, to: idTo, message: message, type: messageType}) messages.push({ from: idFrom, to: idTo, message: message, type: messageType })
} }
exports.getMessages = function () { exports.getMessages = function () {
@@ -87,13 +84,13 @@ exports.PLACEMENT = {
} }
exports.addNote = function (actor, placement, message) { exports.addNote = function (actor, placement, message) {
var note = {actor: actor, placement: placement, message: message} var note = { actor: actor, placement: placement, message: message }
// Coerce actor into a [to, from, ...] array // Coerce actor into a [to, from, ...] array
var actors = [].concat(actor, actor) var actors = [].concat(actor, actor)
notes.push(note) notes.push(note)
messages.push({from: actors[0], to: actors[1], message: message, type: exports.LINETYPE.NOTE, placement: placement}) messages.push({ from: actors[0], to: actors[1], message: message, type: exports.LINETYPE.NOTE, placement: placement })
} }
exports.setTitle = function (titleText) { exports.setTitle = function (titleText) {
@@ -110,7 +107,6 @@ exports.apply = function (param) {
exports.apply(item) exports.apply(item)
}) })
} else { } else {
// console.info(param);
switch (param.type) { switch (param.type) {
case 'addActor': case 'addActor':
exports.addActor(param.actor, param.actor, param.description) exports.addActor(param.actor, param.actor, param.description)
@@ -128,25 +124,19 @@ exports.apply = function (param) {
exports.addSignal(param.from, param.to, param.msg, param.signalType) exports.addSignal(param.from, param.to, param.msg, param.signalType)
break break
case 'loopStart': case 'loopStart':
// log.debug('Loop text: ',param.loopText);
exports.addSignal(undefined, undefined, param.loopText, param.signalType) exports.addSignal(undefined, undefined, param.loopText, param.signalType)
// yy.addSignal(undefined, undefined, $2, yy.LINETYPE.LOOP_START);
break break
case 'loopEnd': case 'loopEnd':
exports.addSignal(undefined, undefined, undefined, param.signalType) exports.addSignal(undefined, undefined, undefined, param.signalType)
break break
case 'optStart': case 'optStart':
// log.debug('Loop text: ',param.loopText);
exports.addSignal(undefined, undefined, param.optText, param.signalType) exports.addSignal(undefined, undefined, param.optText, param.signalType)
// yy.addSignal(undefined, undefined, $2, yy.LINETYPE.LOOP_START);
break break
case 'optEnd': case 'optEnd':
exports.addSignal(undefined, undefined, undefined, param.signalType) exports.addSignal(undefined, undefined, undefined, param.signalType)
break break
case 'altStart': case 'altStart':
// log.debug('Loop text: ',param.loopText);
exports.addSignal(undefined, undefined, param.altText, param.signalType) exports.addSignal(undefined, undefined, param.altText, param.signalType)
// yy.addSignal(undefined, undefined, $2, yy.LINETYPE.LOOP_START);
break break
case 'else': case 'else':
exports.addSignal(undefined, undefined, param.altText, param.signalType) exports.addSignal(undefined, undefined, param.altText, param.signalType)

View File

@@ -3,8 +3,6 @@ var proxyquire = require('proxyquire')
/** /**
* Created by knut on 14-11-18. * Created by knut on 14-11-18.
*/ */
// var proxyquire = require('proxyquire');
// var log = require('../../logger').create();
var sq = require('./parser/sequenceDiagram').parser var sq = require('./parser/sequenceDiagram').parser
var NewD3 var NewD3
@@ -17,13 +15,8 @@ var d3 = {
return new NewD3() return new NewD3()
} }
} }
// var sd = proxyquire('./sequenceRenderer', { './d3': d3 });
var sd = proxyquire('./sequenceRenderer', { '../../d3': d3 }) var sd = proxyquire('./sequenceRenderer', { '../../d3': d3 })
//
//
// var sd = require('./sequenceRenderer');
function addConf (conf, key, value) { function addConf (conf, key, value) {
if (value !== undefined) { if (value !== undefined) {
conf[key] = value conf[key] = value
@@ -36,17 +29,12 @@ describe('when parsing a sequenceDiagram', function () {
beforeEach(function () { beforeEach(function () {
sq.yy = require('./sequenceDb') sq.yy = require('./sequenceDb')
sq.yy.clear() sq.yy.clear()
// parseError = function(err, hash) {
// log.debug('Syntax error:' + err);
// log.debug(hash);
// };
// sq.yy.parseError = parseError;
}) })
it('it should handle a sequenceDiagram defintion', function () { it('it should handle a sequenceDiagram defintion', function () {
str = 'sequenceDiagram\n' + str = 'sequenceDiagram\n' +
'Alice->Bob:Hello Bob, how are you?\n' + 'Alice->Bob:Hello Bob, how are you?\n' +
'Note right of Bob: Bob thinks\n' + 'Note right of Bob: Bob thinks\n' +
'Bob-->Alice: I am good thanks!' 'Bob-->Alice: I am good thanks!'
sq.parse(str) sq.parse(str)
var actors = sq.yy.getActors() var actors = sq.yy.getActors()
@@ -61,10 +49,10 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle a sequenceDiagram definition with a title', function () { it('it should handle a sequenceDiagram definition with a title', function () {
str = 'sequenceDiagram\n' + str = 'sequenceDiagram\n' +
'title: Diagram Title\n' + 'title: Diagram Title\n' +
'Alice->Bob:Hello Bob, how are you?\n' + 'Alice->Bob:Hello Bob, how are you?\n' +
'Note right of Bob: Bob thinks\n' + 'Note right of Bob: Bob thinks\n' +
'Bob-->Alice: I am good thanks!' 'Bob-->Alice: I am good thanks!'
sq.parse(str) sq.parse(str)
var actors = sq.yy.getActors() var actors = sq.yy.getActors()
@@ -81,8 +69,8 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should space in actor names', function () { it('it should space in actor names', function () {
str = 'sequenceDiagram\n' + str = 'sequenceDiagram\n' +
'Alice->Bob:Hello Bob, how are - you?\n' + 'Alice->Bob:Hello Bob, how are - you?\n' +
'Bob-->Alice: I am good thanks!' 'Bob-->Alice: I am good thanks!'
sq.parse(str) sq.parse(str)
var actors = sq.yy.getActors() var actors = sq.yy.getActors()
@@ -97,10 +85,10 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should alias participants', function () { it('it should alias participants', function () {
str = 'sequenceDiagram\n' + str = 'sequenceDiagram\n' +
'participant A as Alice\n' + 'participant A as Alice\n' +
'participant B as Bob\n' + 'participant B as Bob\n' +
'A->B:Hello Bob, how are you?\n' + 'A->B:Hello Bob, how are you?\n' +
'B-->A: I am good thanks!' 'B-->A: I am good thanks!'
sq.parse(str) sq.parse(str)
@@ -116,7 +104,7 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle in async messages', function () { it('it should handle in async messages', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice-xBob:Hello Bob, how are you?' 'Alice-xBob:Hello Bob, how are you?'
sq.parse(str) sq.parse(str)
var actors = sq.yy.getActors() var actors = sq.yy.getActors()
@@ -130,7 +118,7 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle in async dotted messages', function () { it('it should handle in async dotted messages', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice--xBob:Hello Bob, how are you?' 'Alice--xBob:Hello Bob, how are you?'
sq.parse(str) sq.parse(str)
var actors = sq.yy.getActors() var actors = sq.yy.getActors()
@@ -144,7 +132,7 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle in arrow messages', function () { it('it should handle in arrow messages', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice->>Bob:Hello Bob, how are you?' 'Alice->>Bob:Hello Bob, how are you?'
sq.parse(str) sq.parse(str)
var actors = sq.yy.getActors() var actors = sq.yy.getActors()
@@ -158,7 +146,7 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle in arrow messages', function () { it('it should handle in arrow messages', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice-->>Bob:Hello Bob, how are you?' 'Alice-->>Bob:Hello Bob, how are you?'
sq.parse(str) sq.parse(str)
var actors = sq.yy.getActors() var actors = sq.yy.getActors()
@@ -172,10 +160,10 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle actor activation', function () { it('it should handle actor activation', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice-->>Bob:Hello Bob, how are you?\n' + 'Alice-->>Bob:Hello Bob, how are you?\n' +
'activate Bob\n' + 'activate Bob\n' +
'Bob-->>Alice:Hello Alice, I\'m fine and you?\n' + 'Bob-->>Alice:Hello Alice, I\'m fine and you?\n' +
'deactivate Bob' 'deactivate Bob'
sq.parse(str) sq.parse(str)
var actors = sq.yy.getActors() var actors = sq.yy.getActors()
@@ -194,8 +182,8 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle actor one line notation activation', function () { it('it should handle actor one line notation activation', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice-->>+Bob:Hello Bob, how are you?\n' + 'Alice-->>+Bob:Hello Bob, how are you?\n' +
'Bob-->>- Alice:Hello Alice, I\'m fine and you?' 'Bob-->>- Alice:Hello Alice, I\'m fine and you?'
sq.parse(str) sq.parse(str)
var actors = sq.yy.getActors() var actors = sq.yy.getActors()
@@ -218,10 +206,10 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle stacked activations', function () { it('it should handle stacked activations', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice-->>+Bob:Hello Bob, how are you?\n' + 'Alice-->>+Bob:Hello Bob, how are you?\n' +
'Bob-->>+Carol:Carol, let me introduce Alice?\n' + 'Bob-->>+Carol:Carol, let me introduce Alice?\n' +
'Bob-->>- Alice:Hello Alice, please meet Carol?\n' + 'Bob-->>- Alice:Hello Alice, please meet Carol?\n' +
'Carol->>- Bob:Oh Bob, I\'m so happy to be here!' 'Carol->>- Bob:Oh Bob, I\'m so happy to be here!'
sq.parse(str) sq.parse(str)
var actors = sq.yy.getActors() var actors = sq.yy.getActors()
@@ -250,10 +238,10 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle comments in a sequenceDiagram', function () { it('it should handle comments in a sequenceDiagram', function () {
str = 'sequenceDiagram\n' + str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n' + 'Alice->Bob: Hello Bob, how are you?\n' +
'%% Comment\n' + '%% Comment\n' +
'Note right of Bob: Bob thinks\n' + 'Note right of Bob: Bob thinks\n' +
'Bob-->Alice: I am good thanks!' 'Bob-->Alice: I am good thanks!'
sq.parse(str) sq.parse(str)
var actors = sq.yy.getActors() var actors = sq.yy.getActors()
@@ -268,10 +256,10 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle new lines in a sequenceDiagram', function () { it('it should handle new lines in a sequenceDiagram', function () {
str = 'sequenceDiagram\n' + str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n\n' + 'Alice->Bob: Hello Bob, how are you?\n\n' +
'%% Comment\n' + '%% Comment\n' +
'Note right of Bob: Bob thinks\n' + 'Note right of Bob: Bob thinks\n' +
'Bob-->Alice: I am good thanks!\n' 'Bob-->Alice: I am good thanks!\n'
sq.parse(str) sq.parse(str)
var actors = sq.yy.getActors() var actors = sq.yy.getActors()
@@ -286,9 +274,9 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle semicolons', function () { it('it should handle semicolons', function () {
str = 'sequenceDiagram;' + str = 'sequenceDiagram;' +
'Alice->Bob: Hello Bob, how are you?;' + 'Alice->Bob: Hello Bob, how are you?;' +
'Note right of Bob: Bob thinks;' + 'Note right of Bob: Bob thinks;' +
'Bob-->Alice: I am good thanks!;' 'Bob-->Alice: I am good thanks!;'
sq.parse(str) sq.parse(str)
var actors = sq.yy.getActors() var actors = sq.yy.getActors()
@@ -303,10 +291,10 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle one leading space in lines in a sequenceDiagram', function () { it('it should handle one leading space in lines in a sequenceDiagram', function () {
str = 'sequenceDiagram\n' + str = 'sequenceDiagram\n' +
' Alice->Bob: Hello Bob, how are you?\n\n' + ' Alice->Bob: Hello Bob, how are you?\n\n' +
'%% Comment\n' + '%% Comment\n' +
'Note right of Bob: Bob thinks\n' + 'Note right of Bob: Bob thinks\n' +
'Bob-->Alice: I am good thanks!' 'Bob-->Alice: I am good thanks!'
sq.parse(str) sq.parse(str)
var actors = sq.yy.getActors() var actors = sq.yy.getActors()
@@ -321,10 +309,10 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle several leading spaces in lines in a sequenceDiagram', function () { it('it should handle several leading spaces in lines in a sequenceDiagram', function () {
str = 'sequenceDiagram\n' + str = 'sequenceDiagram\n' +
' Alice->Bob: Hello Bob, how are you?\n\n' + ' Alice->Bob: Hello Bob, how are you?\n\n' +
'%% Comment\n' + '%% Comment\n' +
'Note right of Bob: Bob thinks\n' + 'Note right of Bob: Bob thinks\n' +
'Bob-->Alice: I am good thanks!' 'Bob-->Alice: I am good thanks!'
sq.parse(str) sq.parse(str)
var actors = sq.yy.getActors() var actors = sq.yy.getActors()
@@ -339,16 +327,16 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle several leading spaces in lines in a sequenceDiagram', function () { it('it should handle several leading spaces in lines in a sequenceDiagram', function () {
str = 'sequenceDiagram\n' + str = 'sequenceDiagram\n' +
'participant Alice\n' + 'participant Alice\n' +
'participant Bob\n' + 'participant Bob\n' +
'Alice->John: Hello John, how are you?\n' + 'Alice->John: Hello John, how are you?\n' +
' loop Healthcheck\n' + ' loop Healthcheck\n' +
'John->John: Fight against hypochondria\n' + 'John->John: Fight against hypochondria\n' +
' end\n' + ' end\n' +
'Note right of John: Rational thoughts<br/>prevail...\n' + 'Note right of John: Rational thoughts<br/>prevail...\n' +
' John-->Alice: Great!\n' + ' John-->Alice: Great!\n' +
' John->Bob: How about you?\n' + ' John->Bob: How about you?\n' +
'Bob-->John: Jolly good!' 'Bob-->John: Jolly good!'
sq.parse(str) sq.parse(str)
var actors = sq.yy.getActors() var actors = sq.yy.getActors()
@@ -363,8 +351,8 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle notes over a single actor', function () { it('it should handle notes over a single actor', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n' + 'Alice->Bob: Hello Bob, how are you?\n' +
'Note over Bob: Bob thinks\n' 'Note over Bob: Bob thinks\n'
sq.parse(str) sq.parse(str)
@@ -374,9 +362,9 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle notes over multiple actors', function () { it('it should handle notes over multiple actors', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n' + 'Alice->Bob: Hello Bob, how are you?\n' +
'Note over Alice,Bob: confusion\n' + 'Note over Alice,Bob: confusion\n' +
'Note over Bob,Alice: resolution\n' 'Note over Bob,Alice: resolution\n'
sq.parse(str) sq.parse(str)
@@ -388,12 +376,12 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle loop statements a sequenceDiagram', function () { it('it should handle loop statements a sequenceDiagram', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n\n' + 'Alice->Bob: Hello Bob, how are you?\n\n' +
'%% Comment\n' + '%% Comment\n' +
'Note right of Bob: Bob thinks\n' + 'Note right of Bob: Bob thinks\n' +
'loop Multiple happy responses\n\n' + 'loop Multiple happy responses\n\n' +
'Bob-->Alice: I am good thanks!\n' + 'Bob-->Alice: I am good thanks!\n' +
'end' 'end'
sq.parse(str) sq.parse(str)
var actors = sq.yy.getActors() var actors = sq.yy.getActors()
@@ -408,12 +396,12 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle opt statements a sequenceDiagram', function () { it('it should handle opt statements a sequenceDiagram', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n\n' + 'Alice->Bob: Hello Bob, how are you?\n\n' +
'%% Comment\n' + '%% Comment\n' +
'Note right of Bob: Bob thinks\n' + 'Note right of Bob: Bob thinks\n' +
'opt Perhaps a happy response\n\n' + 'opt Perhaps a happy response\n\n' +
'Bob-->Alice: I am good thanks!\n' + 'Bob-->Alice: I am good thanks!\n' +
'end' 'end'
sq.parse(str) sq.parse(str)
var actors = sq.yy.getActors() var actors = sq.yy.getActors()
@@ -428,14 +416,14 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle alt statements a sequenceDiagram', function () { it('it should handle alt statements a sequenceDiagram', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n\n' + 'Alice->Bob: Hello Bob, how are you?\n\n' +
'%% Comment\n' + '%% Comment\n' +
'Note right of Bob: Bob thinks\n' + 'Note right of Bob: Bob thinks\n' +
'alt isWell\n\n' + 'alt isWell\n\n' +
'Bob-->Alice: I am good thanks!\n' + 'Bob-->Alice: I am good thanks!\n' +
'else isSick\n' + 'else isSick\n' +
'Bob-->Alice: Feel sick...\n' + 'Bob-->Alice: Feel sick...\n' +
'end' 'end'
sq.parse(str) sq.parse(str)
var actors = sq.yy.getActors() var actors = sq.yy.getActors()
@@ -451,16 +439,16 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle par statements a sequenceDiagram', function () { it('it should handle par statements a sequenceDiagram', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'par Parallel one\n' + 'par Parallel one\n' +
'Alice->>Bob: Hello Bob, how are you?\n' + 'Alice->>Bob: Hello Bob, how are you?\n' +
'Bob-->>Alice: I am good thanks!\n' + 'Bob-->>Alice: I am good thanks!\n' +
'and Parallel two\n' + 'and Parallel two\n' +
'Alice->>Bob: Are you OK?\n' + 'Alice->>Bob: Are you OK?\n' +
'Bob-->>Alice: Fine!\n' + 'Bob-->>Alice: Fine!\n' +
'and Parallel three\n' + 'and Parallel three\n' +
'Alice->>Bob: What do you think about it?\n' + 'Alice->>Bob: What do you think about it?\n' +
'Bob-->>Alice: It\'s good!\n' + 'Bob-->>Alice: It\'s good!\n' +
'end' 'end'
sq.parse(str) sq.parse(str)
var actors = sq.yy.getActors() var actors = sq.yy.getActors()
@@ -477,7 +465,7 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle special characters in signals', function () { it('it should handle special characters in signals', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice->Bob: -:<>,;# comment' 'Alice->Bob: -:<>,;# comment'
sq.parse(str) sq.parse(str)
@@ -486,8 +474,8 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle special characters in notes', function () { it('it should handle special characters in notes', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n' + 'Alice->Bob: Hello Bob, how are you?\n' +
'Note right of Bob: -:<>,;# comment' 'Note right of Bob: -:<>,;# comment'
sq.parse(str) sq.parse(str)
@@ -496,10 +484,10 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle special characters in loop', function () { it('it should handle special characters in loop', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n' + 'Alice->Bob: Hello Bob, how are you?\n' +
'loop -:<>,;# comment\n' + 'loop -:<>,;# comment\n' +
'Bob-->Alice: I am good thanks!\n' + 'Bob-->Alice: I am good thanks!\n' +
'end' 'end'
sq.parse(str) sq.parse(str)
@@ -508,10 +496,10 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle special characters in opt', function () { it('it should handle special characters in opt', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n' + 'Alice->Bob: Hello Bob, how are you?\n' +
'opt -:<>,;# comment\n' + 'opt -:<>,;# comment\n' +
'Bob-->Alice: I am good thanks!\n' + 'Bob-->Alice: I am good thanks!\n' +
'end' 'end'
sq.parse(str) sq.parse(str)
@@ -520,12 +508,12 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle special characters in alt', function () { it('it should handle special characters in alt', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n' + 'Alice->Bob: Hello Bob, how are you?\n' +
'alt -:<>,;# comment\n' + 'alt -:<>,;# comment\n' +
'Bob-->Alice: I am good thanks!\n' + 'Bob-->Alice: I am good thanks!\n' +
'else ,<>:-#; comment\n' + 'else ,<>:-#; comment\n' +
'Bob-->Alice: I am good thanks!\n' + 'Bob-->Alice: I am good thanks!\n' +
'end' 'end'
sq.parse(str) sq.parse(str)
@@ -535,12 +523,12 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle special characters in par', function () { it('it should handle special characters in par', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n' + 'Alice->Bob: Hello Bob, how are you?\n' +
'par -:<>,;# comment\n' + 'par -:<>,;# comment\n' +
'Bob-->Alice: I am good thanks!\n' + 'Bob-->Alice: I am good thanks!\n' +
'and ,<>:-#; comment\n' + 'and ,<>:-#; comment\n' +
'Bob-->Alice: I am good thanks!\n' + 'Bob-->Alice: I am good thanks!\n' +
'end' 'end'
sq.parse(str) sq.parse(str)
@@ -550,10 +538,10 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle no-label loop', function () { it('it should handle no-label loop', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n' + 'Alice->Bob: Hello Bob, how are you?\n' +
'loop\n' + 'loop\n' +
'Bob-->Alice: I am good thanks!\n' + 'Bob-->Alice: I am good thanks!\n' +
'end' 'end'
sq.parse(str) sq.parse(str)
@@ -563,10 +551,10 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle no-label opt', function () { it('it should handle no-label opt', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n' + 'Alice->Bob: Hello Bob, how are you?\n' +
'opt # comment\n' + 'opt # comment\n' +
'Bob-->Alice: I am good thanks!\n' + 'Bob-->Alice: I am good thanks!\n' +
'end' 'end'
sq.parse(str) sq.parse(str)
@@ -576,12 +564,12 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle no-label alt', function () { it('it should handle no-label alt', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n' + 'Alice->Bob: Hello Bob, how are you?\n' +
'alt;' + 'alt;' +
'Bob-->Alice: I am good thanks!\n' + 'Bob-->Alice: I am good thanks!\n' +
'else # comment\n' + 'else # comment\n' +
'Bob-->Alice: I am good thanks!\n' + 'Bob-->Alice: I am good thanks!\n' +
'end' 'end'
sq.parse(str) sq.parse(str)
@@ -593,12 +581,12 @@ describe('when parsing a sequenceDiagram', function () {
}) })
it('it should handle no-label par', function () { it('it should handle no-label par', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n' + 'Alice->Bob: Hello Bob, how are you?\n' +
'par;' + 'par;' +
'Bob-->Alice: I am good thanks!\n' + 'Bob-->Alice: I am good thanks!\n' +
'and # comment\n' + 'and # comment\n' +
'Bob-->Alice: I am good thanks!\n' + 'Bob-->Alice: I am good thanks!\n' +
'end' 'end'
sq.parse(str) sq.parse(str)
@@ -615,18 +603,12 @@ describe('when checking the bounds in a sequenceDiagram', function () {
beforeEach(function () { beforeEach(function () {
sq.yy = require('./sequenceDb') sq.yy = require('./sequenceDb')
sq.yy.clear() sq.yy.clear()
// parseError = function(err, hash) {
// log.debug('Syntax error:' + err);
// log.debug(hash);
// };
// sq.yy.parseError = parseError;
conf = { conf = {
diagramMarginX: 50, diagramMarginX: 50,
diagramMarginY: 10, diagramMarginY: 10,
actorMargin: 50, actorMargin: 50,
width: 150, width: 150,
// Height of actor boxes // Height of actor boxes
height: 65, height: 65,
boxMargin: 10, boxMargin: 10,
messageMargin: 40, messageMargin: 40,
@@ -686,7 +668,7 @@ describe('when checking the bounds in a sequenceDiagram', function () {
expect(loop.stopx).toBe(150 + conf.boxMargin) expect(loop.stopx).toBe(150 + conf.boxMargin)
expect(loop.stopy).toBe(200 + conf.boxMargin) expect(loop.stopy).toBe(200 + conf.boxMargin)
// Check bounds of first loop // Check bounds of first loop
var bounds = sd.bounds.getBounds() var bounds = sd.bounds.getBounds()
expect(bounds.startx).toBe(25) expect(bounds.startx).toBe(25)
@@ -703,7 +685,7 @@ describe('when checking the bounds in a sequenceDiagram', function () {
sd.bounds.newLoop() sd.bounds.newLoop()
sd.bounds.insert(200, 200, 300, 300) sd.bounds.insert(200, 200, 300, 300)
// Check bounds of first loop // Check bounds of first loop
var loop = sd.bounds.endLoop() var loop = sd.bounds.endLoop()
expect(loop.startx).toBe(200 - conf.boxMargin) expect(loop.startx).toBe(200 - conf.boxMargin)
@@ -711,7 +693,7 @@ describe('when checking the bounds in a sequenceDiagram', function () {
expect(loop.stopx).toBe(300 + conf.boxMargin) expect(loop.stopx).toBe(300 + conf.boxMargin)
expect(loop.stopy).toBe(300 + conf.boxMargin) expect(loop.stopy).toBe(300 + conf.boxMargin)
// Check bounds of second loop // Check bounds of second loop
loop = sd.bounds.endLoop() loop = sd.bounds.endLoop()
expect(loop.startx).toBe(200 - 2 * conf.boxMargin) expect(loop.startx).toBe(200 - 2 * conf.boxMargin)
@@ -719,7 +701,7 @@ describe('when checking the bounds in a sequenceDiagram', function () {
expect(loop.stopx).toBe(300 + 2 * conf.boxMargin) expect(loop.stopx).toBe(300 + 2 * conf.boxMargin)
expect(loop.stopy).toBe(300 + 2 * conf.boxMargin) expect(loop.stopy).toBe(300 + 2 * conf.boxMargin)
// Check bounds of first loop // Check bounds of first loop
var bounds = sd.bounds.getBounds() var bounds = sd.bounds.getBounds()
expect(bounds.startx).toBe(100) expect(bounds.startx).toBe(100)
@@ -742,7 +724,7 @@ describe('when checking the bounds in a sequenceDiagram', function () {
expect(loop.stopx).toBe(300 + conf.boxMargin) expect(loop.stopx).toBe(300 + conf.boxMargin)
expect(loop.stopy).toBe(300 + conf.boxMargin) expect(loop.stopy).toBe(300 + conf.boxMargin)
// Check bounds after the loop // Check bounds after the loop
var bounds = sd.bounds.getBounds() var bounds = sd.bounds.getBounds()
expect(bounds.startx).toBe(loop.startx) expect(bounds.startx).toBe(loop.startx)
@@ -758,21 +740,8 @@ describe('when rendering a sequenceDiagram', function () {
sq.yy = require('./sequenceDb') sq.yy = require('./sequenceDb')
sq.yy.clear() sq.yy.clear()
// var MockBrowser = require('mock-browser').mocks.MockBrowser;
// var mock = new MockBrowser();
delete global.mermaid_config delete global.mermaid_config
// and in the run-code inside some object
// global.document = mock.getDocument();
// global.window = mock.getWindow();
// parseError = function(err, hash) {
// log.debug('Syntax error:' + err);
// log.debug(hash);
// };
// sq.yy.parseError = parseError;
NewD3 = function () { NewD3 = function () {
var o = { var o = {
append: function () { append: function () {
@@ -808,7 +777,7 @@ describe('when rendering a sequenceDiagram', function () {
diagramMarginY: 10, diagramMarginY: 10,
actorMargin: 50, actorMargin: 50,
width: 150, width: 150,
// Height of actor boxes // Height of actor boxes
height: 65, height: 65,
boxMargin: 10, boxMargin: 10,
messageMargin: 40, messageMargin: 40,
@@ -816,18 +785,13 @@ describe('when rendering a sequenceDiagram', function () {
noteMargin: 25 noteMargin: 25
} }
sd.setConf(conf) sd.setConf(conf)
// document.body.innerHTML = '<div id="tst"></div>';
// document.body.innerHTML = '<svg height="30" width="200"><text id="tst" x="0" y="15" fill="red">I love SVG!</text></svg>';
// document.body.innerHTML = '<svg height="30" width="200"><text x="0" y="15" fill="red"><tspan x="46" id="tst">Alice thinks</tspan></text></svg>';
// console.log('document.body');
// console.log(document.querySelector('#tst').getBBox());
}); });
['tspan', 'fo', 'old', undefined].forEach(function (textPlacement) { ['tspan', 'fo', 'old', undefined].forEach(function (textPlacement) {
it('it should handle one actor, when textPlacement is ' + textPlacement, function () { it('it should handle one actor, when textPlacement is ' + textPlacement, function () {
sd.setConf(addConf(conf, 'textPlacement', textPlacement)) sd.setConf(addConf(conf, 'textPlacement', textPlacement))
sd.bounds.init() sd.bounds.init()
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'participant Alice' 'participant Alice'
sq.parse(str) sq.parse(str)
sd.draw(str, 'tst') sd.draw(str, 'tst')
@@ -842,8 +806,8 @@ describe('when rendering a sequenceDiagram', function () {
it('it should handle one actor and a centered note', function () { it('it should handle one actor and a centered note', function () {
sd.bounds.init() sd.bounds.init()
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'participant Alice\n' + 'participant Alice\n' +
'Note over Alice: Alice thinks\n' 'Note over Alice: Alice thinks\n'
sq.parse(str) sq.parse(str)
sd.draw(str, 'tst') sd.draw(str, 'tst')
@@ -852,14 +816,14 @@ describe('when rendering a sequenceDiagram', function () {
expect(bounds.startx).toBe(0) expect(bounds.startx).toBe(0)
expect(bounds.starty).toBe(0) expect(bounds.starty).toBe(0)
expect(bounds.stopx).toBe(conf.width) expect(bounds.stopx).toBe(conf.width)
// 10 comes from mock of text height // 10 comes from mock of text height
expect(bounds.stopy).toBe(conf.height + conf.boxMargin + 2 * conf.noteMargin + 10) expect(bounds.stopy).toBe(conf.height + conf.boxMargin + 2 * conf.noteMargin + 10)
}) })
it('it should handle one actor and a note to the left', function () { it('it should handle one actor and a note to the left', function () {
sd.bounds.init() sd.bounds.init()
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'participant Alice\n' + 'participant Alice\n' +
'Note left of Alice: Alice thinks' 'Note left of Alice: Alice thinks'
sq.parse(str) sq.parse(str)
sd.draw(str, 'tst') sd.draw(str, 'tst')
@@ -868,14 +832,14 @@ describe('when rendering a sequenceDiagram', function () {
expect(bounds.startx).toBe(-(conf.width / 2) - (conf.actorMargin / 2)) expect(bounds.startx).toBe(-(conf.width / 2) - (conf.actorMargin / 2))
expect(bounds.starty).toBe(0) expect(bounds.starty).toBe(0)
expect(bounds.stopx).toBe(conf.width) expect(bounds.stopx).toBe(conf.width)
// 10 comes from mock of text height // 10 comes from mock of text height
expect(bounds.stopy).toBe(conf.height + conf.boxMargin + 2 * conf.noteMargin + 10) expect(bounds.stopy).toBe(conf.height + conf.boxMargin + 2 * conf.noteMargin + 10)
}) })
it('it should handle one actor and a note to the right', function () { it('it should handle one actor and a note to the right', function () {
sd.bounds.init() sd.bounds.init()
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'participant Alice\n' + 'participant Alice\n' +
'Note right of Alice: Alice thinks' 'Note right of Alice: Alice thinks'
sq.parse(str) sq.parse(str)
sd.draw(str, 'tst') sd.draw(str, 'tst')
@@ -884,13 +848,13 @@ describe('when rendering a sequenceDiagram', function () {
expect(bounds.startx).toBe(0) expect(bounds.startx).toBe(0)
expect(bounds.starty).toBe(0) expect(bounds.starty).toBe(0)
expect(bounds.stopx).toBe((conf.width / 2) + (conf.actorMargin / 2) + conf.width) expect(bounds.stopx).toBe((conf.width / 2) + (conf.actorMargin / 2) + conf.width)
// 10 comes from mock of text height // 10 comes from mock of text height
expect(bounds.stopy).toBe(conf.height + conf.boxMargin + 2 * conf.noteMargin + 10) expect(bounds.stopy).toBe(conf.height + conf.boxMargin + 2 * conf.noteMargin + 10)
}) })
it('it should handle two actors', function () { it('it should handle two actors', function () {
sd.bounds.init() sd.bounds.init()
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?' 'Alice->Bob: Hello Bob, how are you?'
sq.parse(str) sq.parse(str)
sd.draw(str, 'tst') sd.draw(str, 'tst')
@@ -904,9 +868,9 @@ describe('when rendering a sequenceDiagram', function () {
it('it should handle two actors and two centered shared notes', function () { it('it should handle two actors and two centered shared notes', function () {
sd.bounds.init() sd.bounds.init()
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n' + 'Alice->Bob: Hello Bob, how are you?\n' +
'Note over Alice,Bob: Looks\n' + 'Note over Alice,Bob: Looks\n' +
'Note over Bob,Alice: Looks back\n' 'Note over Bob,Alice: Looks back\n'
sq.parse(str) sq.parse(str)
sd.draw(str, 'tst') sd.draw(str, 'tst')
@@ -920,8 +884,8 @@ describe('when rendering a sequenceDiagram', function () {
it('it should draw two actors and two messages', function () { it('it should draw two actors and two messages', function () {
sd.bounds.init() sd.bounds.init()
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n' + 'Alice->Bob: Hello Bob, how are you?\n' +
'Bob->Alice: Fine!' 'Bob->Alice: Fine!'
sq.parse(str) sq.parse(str)
sd.draw(str, 'tst') sd.draw(str, 'tst')
@@ -935,9 +899,9 @@ describe('when rendering a sequenceDiagram', function () {
it('it should draw two actors notes to the right', function () { it('it should draw two actors notes to the right', function () {
sd.bounds.init() sd.bounds.init()
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n' + 'Alice->Bob: Hello Bob, how are you?\n' +
'Note right of Bob: Bob thinks\n' + 'Note right of Bob: Bob thinks\n' +
'Bob->Alice: Fine!' 'Bob->Alice: Fine!'
sq.parse(str) sq.parse(str)
sd.draw(str, 'tst') sd.draw(str, 'tst')
@@ -954,9 +918,9 @@ describe('when rendering a sequenceDiagram', function () {
it('it should draw two actors notes to the left', function () { it('it should draw two actors notes to the left', function () {
sd.bounds.init() sd.bounds.init()
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n' + 'Alice->Bob: Hello Bob, how are you?\n' +
'Note left of Alice: Bob thinks\n' + 'Note left of Alice: Bob thinks\n' +
'Bob->Alice: Fine!' 'Bob->Alice: Fine!'
sq.parse(str) sq.parse(str)
sd.draw(str, 'tst') sd.draw(str, 'tst')
@@ -971,10 +935,10 @@ describe('when rendering a sequenceDiagram', function () {
it('it should draw two loops', function () { it('it should draw two loops', function () {
sd.bounds.init() sd.bounds.init()
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n' + 'Alice->Bob: Hello Bob, how are you?\n' +
'loop Cheers\n' + 'loop Cheers\n' +
'Bob->Alice: Fine!\n' + 'Bob->Alice: Fine!\n' +
'end' 'end'
sq.parse(str) sq.parse(str)
sd.draw(str, 'tst') sd.draw(str, 'tst')
@@ -992,11 +956,6 @@ describe('when rendering a sequenceDiagram with actor mirror activated', functio
beforeEach(function () { beforeEach(function () {
sq.yy = require('./sequenceDb') sq.yy = require('./sequenceDb')
sq.yy.clear() sq.yy.clear()
// parseError = function(err, hash) {
// log.debug('Syntax error:' + err);
// log.debug(hash);
// };
// sq.yy.parseError = parseError;
NewD3 = function () { NewD3 = function () {
var o = { var o = {
@@ -1033,15 +992,15 @@ describe('when rendering a sequenceDiagram with actor mirror activated', functio
diagramMarginY: 10, diagramMarginY: 10,
actorMargin: 50, actorMargin: 50,
width: 150, width: 150,
// Height of actor boxes // Height of actor boxes
height: 65, height: 65,
boxMargin: 10, boxMargin: 10,
messageMargin: 40, messageMargin: 40,
boxTextMargin: 15, boxTextMargin: 15,
noteMargin: 25, noteMargin: 25,
mirrorActors: true, mirrorActors: true,
// Depending on css styling this might need adjustment // Depending on css styling this might need adjustment
// Prolongs the edge of the diagram downwards // Prolongs the edge of the diagram downwards
bottomMarginAdj: 1 bottomMarginAdj: 1
} }
sd.setConf(conf) sd.setConf(conf)
@@ -1051,7 +1010,7 @@ describe('when rendering a sequenceDiagram with actor mirror activated', functio
sd.setConf(addConf(conf, 'textPlacement', textPlacement)) sd.setConf(addConf(conf, 'textPlacement', textPlacement))
sd.bounds.init() sd.bounds.init()
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'participant Alice' 'participant Alice'
sq.parse(str) sq.parse(str)
sd.draw(str, 'tst') sd.draw(str, 'tst')

View File

@@ -13,28 +13,28 @@ var conf = {
diagramMarginX: 50, diagramMarginX: 50,
diagramMarginY: 30, diagramMarginY: 30,
// Margin between actors // Margin between actors
actorMargin: 50, actorMargin: 50,
// Width of actor boxes // Width of actor boxes
width: 150, width: 150,
// Height of actor boxes // Height of actor boxes
height: 65, height: 65,
// Margin around loop boxes // Margin around loop boxes
boxMargin: 10, boxMargin: 10,
boxTextMargin: 5, boxTextMargin: 5,
noteMargin: 10, noteMargin: 10,
// Space between messages // Space between messages
messageMargin: 35, messageMargin: 35,
// mirror actors under diagram // mirror actors under diagram
mirrorActors: false, mirrorActors: false,
// Depending on css styling this might need adjustment // Depending on css styling this might need adjustment
// Prolongs the edge of the diagram downwards // Prolongs the edge of the diagram downwards
bottomMarginAdj: 1, bottomMarginAdj: 1,
// width of activation box // width of activation box
activationWidth: 10, activationWidth: 10,
// text placement as: tspan | fo | old only text as before // text placement as: tspan | fo | old only text as before
textPlacement: 'tspan' textPlacement: 'tspan'
} }
@@ -73,7 +73,7 @@ exports.bounds = {
function updateFn (type) { function updateFn (type) {
return function updateItemBounds (item) { return function updateItemBounds (item) {
cnt++ cnt++
// The loop sequenceItems is a stack so the biggest margins in the beginning of the sequenceItems // The loop sequenceItems is a stack so the biggest margins in the beginning of the sequenceItems
var n = _self.sequenceItems.length - cnt + 1 var n = _self.sequenceItems.length - cnt + 1
_self.updateVal(item, 'starty', starty - n * conf.boxMargin, Math.min) _self.updateVal(item, 'starty', starty - n * conf.boxMargin, Math.min)
@@ -114,7 +114,8 @@ exports.bounds = {
var actorRect = sq.yy.getActors()[message.from.actor] var actorRect = sq.yy.getActors()[message.from.actor]
var stackedSize = actorActivations(message.from.actor).length var stackedSize = actorActivations(message.from.actor).length
var x = actorRect.x + conf.width / 2 + (stackedSize - 1) * conf.activationWidth / 2 var x = actorRect.x + conf.width / 2 + (stackedSize - 1) * conf.activationWidth / 2
this.activations.push({startx: x, this.activations.push({
startx: x,
starty: this.verticalPos + 2, starty: this.verticalPos + 2,
stopx: x + conf.activationWidth, stopx: x + conf.activationWidth,
stopy: undefined, stopy: undefined,
@@ -123,15 +124,15 @@ exports.bounds = {
}) })
}, },
endActivation: function (message) { endActivation: function (message) {
// find most recent activation for given actor // find most recent activation for given actor
var lastActorActivationIdx = this.activations var lastActorActivationIdx = this.activations
.map(function (activation) { return activation.actor }) .map(function (activation) { return activation.actor })
.lastIndexOf(message.from.actor) .lastIndexOf(message.from.actor)
var activation = this.activations.splice(lastActorActivationIdx, 1)[0] var activation = this.activations.splice(lastActorActivationIdx, 1)[0]
return activation return activation
}, },
newLoop: function (title) { newLoop: function (title) {
this.sequenceItems.push({startx: undefined, starty: this.verticalPos, stopx: undefined, stopy: undefined, title: title}) this.sequenceItems.push({ startx: undefined, starty: this.verticalPos, stopx: undefined, stopy: undefined, title: title })
}, },
endLoop: function () { endLoop: function () {
var loop = this.sequenceItems.pop() var loop = this.sequenceItems.pop()
@@ -214,28 +215,26 @@ var drawMessage = function (elem, startx, stopx, verticalPos, msg) {
var txtCenter = startx + (stopx - startx) / 2 var txtCenter = startx + (stopx - startx) / 2
var textElem = g.append('text') // text label for the x axis var textElem = g.append('text') // text label for the x axis
.attr('x', txtCenter) .attr('x', txtCenter)
.attr('y', verticalPos - 7) .attr('y', verticalPos - 7)
.style('text-anchor', 'middle') .style('text-anchor', 'middle')
.attr('class', 'messageText') .attr('class', 'messageText')
.text(msg.message) .text(msg.message)
var textWidth var textWidth
if (typeof textElem[0][0].getBBox !== 'undefined') { if (typeof textElem[0][0].getBBox !== 'undefined') {
textWidth = textElem[0][0].getBBox().width textWidth = textElem[0][0].getBBox().width
} else { } else {
// textWidth = getBBox(textElem).width; //.getComputedTextLength()
textWidth = textElem[0][0].getBoundingClientRect() textWidth = textElem[0][0].getBoundingClientRect()
// textWidth = textElem[0][0].getComputedTextLength();
} }
var line var line
if (startx === stopx) { if (startx === stopx) {
line = g.append('path') line = g.append('path')
.attr('d', 'M ' + startx + ',' + verticalPos + ' C ' + (startx + 60) + ',' + (verticalPos - 10) + ' ' + (startx + 60) + ',' + .attr('d', 'M ' + startx + ',' + verticalPos + ' C ' + (startx + 60) + ',' + (verticalPos - 10) + ' ' + (startx + 60) + ',' +
(verticalPos + 30) + ' ' + startx + ',' + (verticalPos + 20)) (verticalPos + 30) + ' ' + startx + ',' + (verticalPos + 20))
exports.bounds.bumpVerticalPos(30) exports.bounds.bumpVerticalPos(30)
var dx = Math.max(textWidth / 2, 100) var dx = Math.max(textWidth / 2, 100)
@@ -248,8 +247,8 @@ var drawMessage = function (elem, startx, stopx, verticalPos, msg) {
line.attr('y2', verticalPos) line.attr('y2', verticalPos)
exports.bounds.insert(startx, exports.bounds.getVerticalPos() - 10, stopx, exports.bounds.getVerticalPos()) exports.bounds.insert(startx, exports.bounds.getVerticalPos() - 10, stopx, exports.bounds.getVerticalPos())
} }
// Make an SVG Container // Make an SVG Container
// Draw the line // Draw the line
if (msg.type === sq.yy.LINETYPE.DOTTED || msg.type === sq.yy.LINETYPE.DOTTED_CROSS || msg.type === sq.yy.LINETYPE.DOTTED_OPEN) { if (msg.type === sq.yy.LINETYPE.DOTTED || msg.type === sq.yy.LINETYPE.DOTTED_CROSS || msg.type === sq.yy.LINETYPE.DOTTED_OPEN) {
line.style('stroke-dasharray', ('3, 3')) line.style('stroke-dasharray', ('3, 3'))
line.attr('class', 'messageLine1') line.attr('class', 'messageLine1')
@@ -278,23 +277,22 @@ var drawMessage = function (elem, startx, stopx, verticalPos, msg) {
module.exports.drawActors = function (diagram, actors, actorKeys, verticalPos) { module.exports.drawActors = function (diagram, actors, actorKeys, verticalPos) {
var i var i
// Draw the actors // Draw the actors
for (i = 0; i < actorKeys.length; i++) { for (i = 0; i < actorKeys.length; i++) {
var key = actorKeys[i] var key = actorKeys[i]
// Add some rendering data to the object // Add some rendering data to the object
actors[key].x = i * conf.actorMargin + i * conf.width actors[key].x = i * conf.actorMargin + i * conf.width
actors[key].y = verticalPos actors[key].y = verticalPos
actors[key].width = conf.diagramMarginX actors[key].width = conf.diagramMarginX
actors[key].height = conf.diagramMarginY actors[key].height = conf.diagramMarginY
// Draw the box with the attached line // Draw the box with the attached line
svgDraw.drawActor(diagram, actors[key].x, verticalPos, actors[key].description, conf) svgDraw.drawActor(diagram, actors[key].x, verticalPos, actors[key].description, conf)
exports.bounds.insert(actors[key].x, verticalPos, actors[key].x + conf.width, conf.height) exports.bounds.insert(actors[key].x, verticalPos, actors[key].x + conf.width, conf.height)
} }
// Add a margin between the actor boxes and the first arrow // Add a margin between the actor boxes and the first arrow
// exports.bounds.bumpVerticalPos(conf.height+conf.messageMargin);
exports.bounds.bumpVerticalPos(conf.height) exports.bounds.bumpVerticalPos(conf.height)
} }
@@ -313,7 +311,7 @@ var actorActivations = function (actor) {
} }
var actorFlowVerticaBounds = function (actor) { var actorFlowVerticaBounds = function (actor) {
// handle multiple stacked activations for same actor // handle multiple stacked activations for same actor
var actors = sq.yy.getActors() var actors = sq.yy.getActors()
var activations = actorActivations(actor) var activations = actorActivations(actor)
@@ -338,14 +336,14 @@ module.exports.draw = function (text, id) {
var stopx var stopx
var forceWidth var forceWidth
// Fetch data from the parsing // Fetch data from the parsing
var actors = sq.yy.getActors() var actors = sq.yy.getActors()
var actorKeys = sq.yy.getActorKeys() var actorKeys = sq.yy.getActorKeys()
var messages = sq.yy.getMessages() var messages = sq.yy.getMessages()
var title = sq.yy.getTitle() var title = sq.yy.getTitle()
module.exports.drawActors(diagram, actors, actorKeys, 0) module.exports.drawActors(diagram, actors, actorKeys, 0)
// The arrow head definition is attached to the svg once // The arrow head definition is attached to the svg once
svgDraw.insertArrowHead(diagram) svgDraw.insertArrowHead(diagram)
svgDraw.insertArrowCrossHead(diagram) svgDraw.insertArrowCrossHead(diagram)
@@ -362,7 +360,7 @@ module.exports.draw = function (text, id) {
// var lastMsg // var lastMsg
// Draw the messages/signals // Draw the messages/signals
messages.forEach(function (msg) { messages.forEach(function (msg) {
var loopData var loopData
@@ -378,13 +376,13 @@ module.exports.draw = function (text, id) {
} else if (msg.placement === sq.yy.PLACEMENT.LEFTOF) { } else if (msg.placement === sq.yy.PLACEMENT.LEFTOF) {
drawNote(diagram, startx - (conf.width + conf.actorMargin) / 2, exports.bounds.getVerticalPos(), msg) drawNote(diagram, startx - (conf.width + conf.actorMargin) / 2, exports.bounds.getVerticalPos(), msg)
} else if (msg.to === msg.from) { } else if (msg.to === msg.from) {
// Single-actor over // Single-actor over
drawNote(diagram, startx, exports.bounds.getVerticalPos(), msg) drawNote(diagram, startx, exports.bounds.getVerticalPos(), msg)
} else { } else {
// Multi-actor over // Multi-actor over
forceWidth = Math.abs(startx - stopx) + conf.actorMargin forceWidth = Math.abs(startx - stopx) + conf.actorMargin
drawNote(diagram, (startx + stopx + conf.width - forceWidth) / 2, exports.bounds.getVerticalPos(), msg, drawNote(diagram, (startx + stopx + conf.width - forceWidth) / 2, exports.bounds.getVerticalPos(), msg,
forceWidth) forceWidth)
} }
break break
case sq.yy.LINETYPE.ACTIVE_START: case sq.yy.LINETYPE.ACTIVE_START:
@@ -468,14 +466,14 @@ module.exports.draw = function (text, id) {
}) })
if (conf.mirrorActors) { if (conf.mirrorActors) {
// Draw actors below diagram // Draw actors below diagram
exports.bounds.bumpVerticalPos(conf.boxMargin * 2) exports.bounds.bumpVerticalPos(conf.boxMargin * 2)
module.exports.drawActors(diagram, actors, actorKeys, exports.bounds.getVerticalPos()) module.exports.drawActors(diagram, actors, actorKeys, exports.bounds.getVerticalPos())
} }
var box = exports.bounds.getBounds() var box = exports.bounds.getBounds()
// Adjust line height of actor lines now that the height of the diagram is known // Adjust line height of actor lines now that the height of the diagram is known
log.debug('For line height fix Querying: #' + id + ' .actor-line') log.debug('For line height fix Querying: #' + id + ' .actor-line')
var actorLines = d3.selectAll('#' + id + ' .actor-line') var actorLines = d3.selectAll('#' + id + ' .actor-line')
actorLines.attr('y2', box.stopy) actorLines.attr('y2', box.stopy)
@@ -490,9 +488,9 @@ module.exports.draw = function (text, id) {
if (title) { if (title) {
diagram.append('text') diagram.append('text')
.text(title) .text(title)
.attr('x', ((box.stopx - box.startx) / 2) - (2 * conf.diagramMarginX)) .attr('x', ((box.stopx - box.startx) / 2) - (2 * conf.diagramMarginX))
.attr('y', -25) .attr('y', -25)
} }
if (conf.useMaxWidth) { if (conf.useMaxWidth) {

View File

@@ -1,7 +1,6 @@
/** /**
* Created by knut on 14-12-20. * Created by knut on 14-12-20.
*/ */
// var log = require('../../logger').create();
exports.drawRect = function (elem, rectData) { exports.drawRect = function (elem, rectData) {
var rectElem = elem.append('rect') var rectElem = elem.append('rect')
rectElem.attr('x', rectData.x) rectElem.attr('x', rectData.x)
@@ -21,7 +20,7 @@ exports.drawRect = function (elem, rectData) {
} }
exports.drawText = function (elem, textData, width) { exports.drawText = function (elem, textData, width) {
// Remove and ignore br:s // Remove and ignore br:s
var nText = textData.text.replace(/<br\/?>/ig, ' ') var nText = textData.text.replace(/<br\/?>/ig, ' ')
var textElem = elem.append('text') var textElem = elem.append('text')
@@ -32,17 +31,9 @@ exports.drawText = function (elem, textData, width) {
if (typeof textData.class !== 'undefined') { if (typeof textData.class !== 'undefined') {
textElem.attr('class', textData.class) textElem.attr('class', textData.class)
} }
/* textData.text.split(/<br\/?>/ig).forEach(function(rowText){
var span = textElem.append('tspan');
span.attr('x', textData.x +textData.textMargin);
span.attr('dy', textData.dy);
span.text(rowText);
}); */
var span = textElem.append('tspan') var span = textElem.append('tspan')
// span.attr('x', textData.x);
span.attr('x', textData.x + textData.textMargin * 2) span.attr('x', textData.x + textData.textMargin * 2)
// span.attr('dy', textData.dy);
span.attr('fill', textData.fill) span.attr('fill', textData.fill)
span.text(nText) span.text(nText)
if (typeof textElem.textwrap !== 'undefined') { if (typeof textElem.textwrap !== 'undefined') {
@@ -60,10 +51,10 @@ exports.drawText = function (elem, textData, width) {
exports.drawLabel = function (elem, txtObject) { exports.drawLabel = function (elem, txtObject) {
function genPoints (x, y, width, height, cut) { function genPoints (x, y, width, height, cut) {
return x + ',' + y + ' ' + return x + ',' + y + ' ' +
(x + width) + ',' + y + ' ' + (x + width) + ',' + y + ' ' +
(x + width) + ',' + (y + height - cut) + ' ' + (x + width) + ',' + (y + height - cut) + ' ' +
(x + width - cut * 1.2) + ',' + (y + height) + ' ' + (x + width - cut * 1.2) + ',' + (y + height) + ' ' +
(x) + ',' + (y + height) (x) + ',' + (y + height)
} }
var polygon = elem.append('polygon') var polygon = elem.append('polygon')
polygon.attr('points', genPoints(txtObject.x, txtObject.y, 50, 20, 7)) polygon.attr('points', genPoints(txtObject.x, txtObject.y, 50, 20, 7))
@@ -73,8 +64,6 @@ exports.drawLabel = function (elem, txtObject) {
txtObject.x = txtObject.x + 0.5 * txtObject.labelMargin txtObject.x = txtObject.x + 0.5 * txtObject.labelMargin
txtObject.fill = 'white' txtObject.fill = 'white'
exports.drawText(elem, txtObject) exports.drawText(elem, txtObject)
// return textElem;
} }
var actorCnt = -1 var actorCnt = -1
/** /**
@@ -89,14 +78,14 @@ exports.drawActor = function (elem, left, verticalPos, description, conf) {
if (verticalPos === 0) { if (verticalPos === 0) {
actorCnt++ actorCnt++
g.append('line') g.append('line')
.attr('id', 'actor' + actorCnt) .attr('id', 'actor' + actorCnt)
.attr('x1', center) .attr('x1', center)
.attr('y1', 5) .attr('y1', 5)
.attr('x2', center) .attr('x2', center)
.attr('y2', 2000) .attr('y2', 2000)
.attr('class', 'actor-line') .attr('class', 'actor-line')
.attr('stroke-width', '0.5px') .attr('stroke-width', '0.5px')
.attr('stroke', '#999') .attr('stroke', '#999')
} }
var rect = exports.getNoteRect() var rect = exports.getNoteRect()
@@ -111,7 +100,7 @@ exports.drawActor = function (elem, left, verticalPos, description, conf) {
exports.drawRect(g, rect) exports.drawRect(g, rect)
_drawTextCandidateFunc(conf)(description, g, _drawTextCandidateFunc(conf)(description, g,
rect.x, rect.y, rect.width, rect.height, {'class': 'actor'}) rect.x, rect.y, rect.width, rect.height, { 'class': 'actor' })
} }
exports.anchorElement = function (elem) { exports.anchorElement = function (elem) {
@@ -144,13 +133,13 @@ exports.drawLoop = function (elem, bounds, labelText, conf) {
var g = elem.append('g') var g = elem.append('g')
var drawLoopLine = function (startx, starty, stopx, stopy) { var drawLoopLine = function (startx, starty, stopx, stopy) {
return g.append('line') return g.append('line')
.attr('x1', startx) .attr('x1', startx)
.attr('y1', starty) .attr('y1', starty)
.attr('x2', stopx) .attr('x2', stopx)
.attr('y2', stopy) .attr('y2', stopy)
.attr('stroke-width', 2) .attr('stroke-width', 2)
.attr('stroke', '#526e52') .attr('stroke', '#526e52')
.attr('class', 'loopLine') .attr('class', 'loopLine')
} }
drawLoopLine(bounds.startx, bounds.starty, bounds.stopx, bounds.starty) drawLoopLine(bounds.startx, bounds.starty, bounds.stopx, bounds.starty)
drawLoopLine(bounds.stopx, bounds.starty, bounds.stopx, bounds.stopy) drawLoopLine(bounds.stopx, bounds.starty, bounds.stopx, bounds.stopy)
@@ -197,14 +186,14 @@ exports.drawLoop = function (elem, bounds, labelText, conf) {
*/ */
exports.insertArrowHead = function (elem) { exports.insertArrowHead = function (elem) {
elem.append('defs').append('marker') elem.append('defs').append('marker')
.attr('id', 'arrowhead') .attr('id', 'arrowhead')
.attr('refX', 5) .attr('refX', 5)
.attr('refY', 2) .attr('refY', 2)
.attr('markerWidth', 6) .attr('markerWidth', 6)
.attr('markerHeight', 4) .attr('markerHeight', 4)
.attr('orient', 'auto') .attr('orient', 'auto')
.append('path') .append('path')
.attr('d', 'M 0,0 V 4 L6,2 Z') // this is actual shape for arrowhead .attr('d', 'M 0,0 V 4 L6,2 Z') // this is actual shape for arrowhead
} }
/** /**
* Setup arrow head and define the marker. The result is appended to the svg. * Setup arrow head and define the marker. The result is appended to the svg.
@@ -212,29 +201,29 @@ exports.insertArrowHead = function (elem) {
exports.insertArrowCrossHead = function (elem) { exports.insertArrowCrossHead = function (elem) {
var defs = elem.append('defs') var defs = elem.append('defs')
var marker = defs.append('marker') var marker = defs.append('marker')
.attr('id', 'crosshead') .attr('id', 'crosshead')
.attr('markerWidth', 15) .attr('markerWidth', 15)
.attr('markerHeight', 8) .attr('markerHeight', 8)
.attr('orient', 'auto') .attr('orient', 'auto')
.attr('refX', 16) .attr('refX', 16)
.attr('refY', 4) .attr('refY', 4)
// The arrow // The arrow
marker.append('path') marker.append('path')
.attr('fill', 'black') .attr('fill', 'black')
.attr('stroke', '#000000') .attr('stroke', '#000000')
.style('stroke-dasharray', ('0, 0')) .style('stroke-dasharray', ('0, 0'))
.attr('stroke-width', '1px') .attr('stroke-width', '1px')
.attr('d', 'M 9,2 V 6 L16,4 Z') .attr('d', 'M 9,2 V 6 L16,4 Z')
// The cross // The cross
marker.append('path') marker.append('path')
.attr('fill', 'none') .attr('fill', 'none')
.attr('stroke', '#000000') .attr('stroke', '#000000')
.style('stroke-dasharray', ('0, 0')) .style('stroke-dasharray', ('0, 0'))
.attr('stroke-width', '1px') .attr('stroke-width', '1px')
.attr('d', 'M 0,1 L 6,7 M 6,1 L 0,7') .attr('d', 'M 0,1 L 6,7 M 6,1 L 0,7')
// this is actual shape for arrowhead // this is actual shape for arrowhead
} }
exports.getTextObj = function () { exports.getTextObj = function () {
@@ -271,32 +260,32 @@ exports.getNoteRect = function () {
var _drawTextCandidateFunc = (function () { var _drawTextCandidateFunc = (function () {
function byText (content, g, x, y, width, height, textAttrs) { function byText (content, g, x, y, width, height, textAttrs) {
var text = g.append('text') var text = g.append('text')
.attr('x', x + width / 2).attr('y', y + height / 2 + 5) .attr('x', x + width / 2).attr('y', y + height / 2 + 5)
.style('text-anchor', 'middle') .style('text-anchor', 'middle')
.text(content) .text(content)
_setTextAttrs(text, textAttrs) _setTextAttrs(text, textAttrs)
} }
function byTspan (content, g, x, y, width, height, textAttrs) { function byTspan (content, g, x, y, width, height, textAttrs) {
var text = g.append('text') var text = g.append('text')
.attr('x', x + width / 2).attr('y', y) .attr('x', x + width / 2).attr('y', y)
.style('text-anchor', 'middle') .style('text-anchor', 'middle')
text.append('tspan') text.append('tspan')
.attr('x', x + width / 2).attr('dy', '0') .attr('x', x + width / 2).attr('dy', '0')
.text(content) .text(content)
if (typeof (text.textwrap) !== 'undefined') { if (typeof (text.textwrap) !== 'undefined') {
text.textwrap({ // d3textwrap text.textwrap({ // d3textwrap
x: x + width / 2, y: y, width: width, height: height x: x + width / 2, y: y, width: width, height: height
}, 0) }, 0)
// vertical aligment after d3textwrap expans tspan to multiple tspans // vertical aligment after d3textwrap expans tspan to multiple tspans
var tspans = text.selectAll('tspan') var tspans = text.selectAll('tspan')
if (tspans.length > 0 && tspans[0].length > 0) { if (tspans.length > 0 && tspans[0].length > 0) {
tspans = tspans[0] tspans = tspans[0]
// set y of <text> to the mid y of the first line // set y of <text> to the mid y of the first line
text.attr('y', y + (height / 2.0 - text[0][0].getBBox().height * (1 - 1.0 / tspans.length) / 2.0)) text.attr('y', y + (height / 2.0 - text[0][0].getBBox().height * (1 - 1.0 / tspans.length) / 2.0))
.attr('dominant-baseline', 'central') .attr('dominant-baseline', 'central')
.attr('alignment-baseline', 'central') .attr('alignment-baseline', 'central')
} }
} }
_setTextAttrs(text, textAttrs) _setTextAttrs(text, textAttrs)
@@ -305,15 +294,15 @@ var _drawTextCandidateFunc = (function () {
function byFo (content, g, x, y, width, height, textAttrs) { function byFo (content, g, x, y, width, height, textAttrs) {
var s = g.append('switch') var s = g.append('switch')
var f = s.append('foreignObject') var f = s.append('foreignObject')
.attr('x', x).attr('y', y) .attr('x', x).attr('y', y)
.attr('width', width).attr('height', height) .attr('width', width).attr('height', height)
var text = f.append('div').style('display', 'table') var text = f.append('div').style('display', 'table')
.style('height', '100%').style('width', '100%') .style('height', '100%').style('width', '100%')
text.append('div').style('display', 'table-cell') text.append('div').style('display', 'table-cell')
.style('text-align', 'center').style('vertical-align', 'middle') .style('text-align', 'center').style('vertical-align', 'middle')
.text(content) .text(content)
byTspan(content, s, x, y, width, height, textAttrs) byTspan(content, s, x, y, width, height, textAttrs)
_setTextAttrs(text, textAttrs) _setTextAttrs(text, textAttrs)
@@ -329,6 +318,6 @@ var _drawTextCandidateFunc = (function () {
return function (conf) { return function (conf) {
return conf.textPlacement === 'fo' ? byFo : ( return conf.textPlacement === 'fo' ? byFo : (
conf.textPlacement === 'old' ? byText : byTspan) conf.textPlacement === 'old' ? byText : byTspan)
} }
})() })()