mirror of
				https://github.com/mermaid-js/mermaid.git
				synced 2025-11-04 12:54:08 +01:00 
			
		
		
		
	Auto fix standard style voilations
This commit is contained in:
		@@ -1,15 +1,15 @@
 | 
			
		||||
 | 
			
		||||
var Logger = require('../../logger');
 | 
			
		||||
var log = Logger.Log;
 | 
			
		||||
var relations = [];
 | 
			
		||||
var Logger = require('../../logger')
 | 
			
		||||
var log = Logger.Log
 | 
			
		||||
var relations = []
 | 
			
		||||
 | 
			
		||||
var classes;
 | 
			
		||||
var idCache;
 | 
			
		||||
var classes
 | 
			
		||||
var idCache
 | 
			
		||||
classes = {
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Functions to be run after graph rendering
 | 
			
		||||
var funs = [];
 | 
			
		||||
var funs = []
 | 
			
		||||
/**
 | 
			
		||||
 * Function called by parser when a node definition has been found.
 | 
			
		||||
 * @param id
 | 
			
		||||
@@ -18,69 +18,66 @@ var funs = [];
 | 
			
		||||
 * @param style
 | 
			
		||||
 */
 | 
			
		||||
exports.addClass = function (id) {
 | 
			
		||||
    if(typeof classes[id] === 'undefined'){
 | 
			
		||||
        classes[id] = {
 | 
			
		||||
            id:id,
 | 
			
		||||
            methods:[],
 | 
			
		||||
            members:[]
 | 
			
		||||
        };
 | 
			
		||||
  if (typeof classes[id] === 'undefined') {
 | 
			
		||||
    classes[id] = {
 | 
			
		||||
      id: id,
 | 
			
		||||
      methods: [],
 | 
			
		||||
      members: []
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.clear = function () {
 | 
			
		||||
    relations = [];
 | 
			
		||||
    classes = {};
 | 
			
		||||
};
 | 
			
		||||
  relations = []
 | 
			
		||||
  classes = {}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports.getClass = function (id) {
 | 
			
		||||
    return classes[id];
 | 
			
		||||
};
 | 
			
		||||
  return classes[id]
 | 
			
		||||
}
 | 
			
		||||
module.exports.getClasses = function () {
 | 
			
		||||
    return classes;
 | 
			
		||||
};
 | 
			
		||||
  return classes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports.getRelations = function () {
 | 
			
		||||
    return relations;
 | 
			
		||||
};
 | 
			
		||||
  return relations
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.addRelation = function (relation) {
 | 
			
		||||
    log.warn('Adding relation: ' + JSON.stringify(relation));
 | 
			
		||||
    exports.addClass(relation.id1);
 | 
			
		||||
    exports.addClass(relation.id2);
 | 
			
		||||
  log.warn('Adding relation: ' + JSON.stringify(relation))
 | 
			
		||||
  exports.addClass(relation.id1)
 | 
			
		||||
  exports.addClass(relation.id2)
 | 
			
		||||
 | 
			
		||||
    relations.push(relation);
 | 
			
		||||
};
 | 
			
		||||
  relations.push(relation)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.addMembers = function (className, MembersArr) {
 | 
			
		||||
    var theClass = classes[className];
 | 
			
		||||
    if(typeof MembersArr === 'string'){
 | 
			
		||||
        if(MembersArr.substr(-1) === ')'){
 | 
			
		||||
            theClass.methods.push(MembersArr);
 | 
			
		||||
        }
 | 
			
		||||
        else{
 | 
			
		||||
            theClass.members.push(MembersArr);
 | 
			
		||||
        }
 | 
			
		||||
  var theClass = classes[className]
 | 
			
		||||
  if (typeof MembersArr === 'string') {
 | 
			
		||||
    if (MembersArr.substr(-1) === ')') {
 | 
			
		||||
      theClass.methods.push(MembersArr)
 | 
			
		||||
    } else {
 | 
			
		||||
      theClass.members.push(MembersArr)
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.cleanupLabel = function (label) {
 | 
			
		||||
 | 
			
		||||
    if(label.substring(0,1) === ':'){
 | 
			
		||||
        return label.substr(2).trim();
 | 
			
		||||
    }
 | 
			
		||||
    else{
 | 
			
		||||
        return label.trim();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
  if (label.substring(0, 1) === ':') {
 | 
			
		||||
    return label.substr(2).trim()
 | 
			
		||||
  } else {
 | 
			
		||||
    return label.trim()
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.lineType = {
 | 
			
		||||
    LINE:0,
 | 
			
		||||
    DOTTED_LINE:1
 | 
			
		||||
};
 | 
			
		||||
  LINE: 0,
 | 
			
		||||
  DOTTED_LINE: 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.relationType = {
 | 
			
		||||
    AGGREGATION:0,
 | 
			
		||||
    EXTENSION:1,
 | 
			
		||||
    COMPOSITION:2,
 | 
			
		||||
    DEPENDENCY:3
 | 
			
		||||
};
 | 
			
		||||
  AGGREGATION: 0,
 | 
			
		||||
  EXTENSION: 1,
 | 
			
		||||
  COMPOSITION: 2,
 | 
			
		||||
  DEPENDENCY: 3
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,213 +2,212 @@
 | 
			
		||||
 * Created by knut on 14-11-18.
 | 
			
		||||
 */
 | 
			
		||||
describe('class diagram, ', function () {
 | 
			
		||||
    describe('when parsing an info graph it', function () {
 | 
			
		||||
        var cd, cDDb;
 | 
			
		||||
        beforeEach(function () {
 | 
			
		||||
            cd = require('./parser/classDiagram').parser;
 | 
			
		||||
            cDDb = require('./classDb');
 | 
			
		||||
            cd.yy = cDDb;
 | 
			
		||||
        });
 | 
			
		||||
  describe('when parsing an info graph it', function () {
 | 
			
		||||
    var cd, cDDb
 | 
			
		||||
    beforeEach(function () {
 | 
			
		||||
      cd = require('./parser/classDiagram').parser
 | 
			
		||||
      cDDb = require('./classDb')
 | 
			
		||||
      cd.yy = cDDb
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
        it('should handle relation definitions', function () {
 | 
			
		||||
            var str = 'classDiagram\n'+
 | 
			
		||||
'Class01 <|-- Class02\n'+
 | 
			
		||||
'Class03 *-- Class04\n'+
 | 
			
		||||
'Class05 o-- Class06\n'+
 | 
			
		||||
'Class07 .. Class08\n'+
 | 
			
		||||
'Class09 -- Class1';
 | 
			
		||||
    it('should handle relation definitions', function () {
 | 
			
		||||
      var str = 'classDiagram\n' +
 | 
			
		||||
'Class01 <|-- Class02\n' +
 | 
			
		||||
'Class03 *-- Class04\n' +
 | 
			
		||||
'Class05 o-- Class06\n' +
 | 
			
		||||
'Class07 .. Class08\n' +
 | 
			
		||||
'Class09 -- Class1'
 | 
			
		||||
 | 
			
		||||
            cd.parse(str);
 | 
			
		||||
        });
 | 
			
		||||
        it('should handle relation definition of different types and directions', function () {
 | 
			
		||||
            var str = 'classDiagram\n'+
 | 
			
		||||
'Class11 <|.. Class12\n'+
 | 
			
		||||
'Class13 --> Class14\n'+
 | 
			
		||||
'Class15 ..> Class16\n'+
 | 
			
		||||
'Class17 ..|> Class18\n'+
 | 
			
		||||
'Class19 <--* Class20';
 | 
			
		||||
      cd.parse(str)
 | 
			
		||||
    })
 | 
			
		||||
    it('should handle relation definition of different types and directions', function () {
 | 
			
		||||
      var str = 'classDiagram\n' +
 | 
			
		||||
'Class11 <|.. Class12\n' +
 | 
			
		||||
'Class13 --> Class14\n' +
 | 
			
		||||
'Class15 ..> Class16\n' +
 | 
			
		||||
'Class17 ..|> Class18\n' +
 | 
			
		||||
'Class19 <--* Class20'
 | 
			
		||||
 | 
			
		||||
            cd.parse(str);
 | 
			
		||||
        });
 | 
			
		||||
      cd.parse(str)
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
        it('should handle cardinality and labels', function () {
 | 
			
		||||
            var str = 'classDiagram\n'+
 | 
			
		||||
'Class01 "1" *-- "many" Class02 : contains\n'+
 | 
			
		||||
'Class03 o-- Class04 : aggregation\n'+
 | 
			
		||||
'Class05 --> "1" Class06';
 | 
			
		||||
    it('should handle cardinality and labels', function () {
 | 
			
		||||
      var str = 'classDiagram\n' +
 | 
			
		||||
'Class01 "1" *-- "many" Class02 : contains\n' +
 | 
			
		||||
'Class03 o-- Class04 : aggregation\n' +
 | 
			
		||||
'Class05 --> "1" Class06'
 | 
			
		||||
 | 
			
		||||
            cd.parse(str);
 | 
			
		||||
        });
 | 
			
		||||
        it('should handle class definitions', function () {
 | 
			
		||||
            var str = 'classDiagram\n'+
 | 
			
		||||
'class Car\n'+
 | 
			
		||||
'Driver -- Car : drives >\n'+
 | 
			
		||||
'Car *-- Wheel : have 4 >\n'+
 | 
			
		||||
'Car -- Person : < owns';
 | 
			
		||||
      cd.parse(str)
 | 
			
		||||
    })
 | 
			
		||||
    it('should handle class definitions', function () {
 | 
			
		||||
      var str = 'classDiagram\n' +
 | 
			
		||||
'class Car\n' +
 | 
			
		||||
'Driver -- Car : drives >\n' +
 | 
			
		||||
'Car *-- Wheel : have 4 >\n' +
 | 
			
		||||
'Car -- Person : < owns'
 | 
			
		||||
 | 
			
		||||
            cd.parse(str);
 | 
			
		||||
        });
 | 
			
		||||
      cd.parse(str)
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
        it('should handle method statements', function () {
 | 
			
		||||
            var str = 'classDiagram\n'+
 | 
			
		||||
'Object <|-- ArrayList\n'+
 | 
			
		||||
'Object : equals()\n'+
 | 
			
		||||
'ArrayList : Object[] elementData\n'+
 | 
			
		||||
'ArrayList : size()';
 | 
			
		||||
    it('should handle method statements', function () {
 | 
			
		||||
      var str = 'classDiagram\n' +
 | 
			
		||||
'Object <|-- ArrayList\n' +
 | 
			
		||||
'Object : equals()\n' +
 | 
			
		||||
'ArrayList : Object[] elementData\n' +
 | 
			
		||||
'ArrayList : size()'
 | 
			
		||||
 | 
			
		||||
            cd.parse(str);
 | 
			
		||||
        });
 | 
			
		||||
        it('should handle parsing of method statements  grouped by brackets', function () {
 | 
			
		||||
            var str = 'classDiagram\n'+
 | 
			
		||||
'class Dummy {\n'+
 | 
			
		||||
'String data\n'+
 | 
			
		||||
'  void methods()\n'+
 | 
			
		||||
'}\n'+
 | 
			
		||||
'\n'+
 | 
			
		||||
'class Flight {\n'+
 | 
			
		||||
'   flightNumber : Integer\n'+
 | 
			
		||||
'   departureTime : Date\n'+
 | 
			
		||||
'}';
 | 
			
		||||
      cd.parse(str)
 | 
			
		||||
    })
 | 
			
		||||
    it('should handle parsing of method statements  grouped by brackets', function () {
 | 
			
		||||
      var str = 'classDiagram\n' +
 | 
			
		||||
'class Dummy {\n' +
 | 
			
		||||
'String data\n' +
 | 
			
		||||
'  void methods()\n' +
 | 
			
		||||
'}\n' +
 | 
			
		||||
'\n' +
 | 
			
		||||
'class Flight {\n' +
 | 
			
		||||
'   flightNumber : Integer\n' +
 | 
			
		||||
'   departureTime : Date\n' +
 | 
			
		||||
'}'
 | 
			
		||||
 | 
			
		||||
            cd.parse(str);
 | 
			
		||||
        });
 | 
			
		||||
      cd.parse(str)
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
        it('should handle parsing of separators', function () {
 | 
			
		||||
            var str = 'classDiagram\n'+
 | 
			
		||||
                'class Foo1 {\n'+
 | 
			
		||||
                '  You can use\n'+
 | 
			
		||||
                '  several lines\n'+
 | 
			
		||||
                '..\n'+
 | 
			
		||||
                'as you want\n'+
 | 
			
		||||
                'and group\n'+
 | 
			
		||||
                '==\n'+
 | 
			
		||||
                'things together.\n'+
 | 
			
		||||
                '__\n'+
 | 
			
		||||
                'You can have as many groups\n'+
 | 
			
		||||
                'as you want\n'+
 | 
			
		||||
                '--\n'+
 | 
			
		||||
                'End of class\n'+
 | 
			
		||||
                '}\n'+
 | 
			
		||||
                '\n'+
 | 
			
		||||
                'class User {\n'+
 | 
			
		||||
                '.. Simple Getter ..\n'+
 | 
			
		||||
                '+ getName()\n'+
 | 
			
		||||
                '+ getAddress()\n'+
 | 
			
		||||
                '.. Some setter ..\n'+
 | 
			
		||||
                '+ setName()\n'+
 | 
			
		||||
                '__ private data __\n'+
 | 
			
		||||
                'int age\n'+
 | 
			
		||||
                '-- encrypted --\n'+
 | 
			
		||||
                'String password\n'+
 | 
			
		||||
                '}';
 | 
			
		||||
    it('should handle parsing of separators', function () {
 | 
			
		||||
      var str = 'classDiagram\n' +
 | 
			
		||||
                'class Foo1 {\n' +
 | 
			
		||||
                '  You can use\n' +
 | 
			
		||||
                '  several lines\n' +
 | 
			
		||||
                '..\n' +
 | 
			
		||||
                'as you want\n' +
 | 
			
		||||
                'and group\n' +
 | 
			
		||||
                '==\n' +
 | 
			
		||||
                'things together.\n' +
 | 
			
		||||
                '__\n' +
 | 
			
		||||
                'You can have as many groups\n' +
 | 
			
		||||
                'as you want\n' +
 | 
			
		||||
                '--\n' +
 | 
			
		||||
                'End of class\n' +
 | 
			
		||||
                '}\n' +
 | 
			
		||||
                '\n' +
 | 
			
		||||
                'class User {\n' +
 | 
			
		||||
                '.. Simple Getter ..\n' +
 | 
			
		||||
                '+ getName()\n' +
 | 
			
		||||
                '+ getAddress()\n' +
 | 
			
		||||
                '.. Some setter ..\n' +
 | 
			
		||||
                '+ setName()\n' +
 | 
			
		||||
                '__ private data __\n' +
 | 
			
		||||
                'int age\n' +
 | 
			
		||||
                '-- encrypted --\n' +
 | 
			
		||||
                'String password\n' +
 | 
			
		||||
                '}'
 | 
			
		||||
 | 
			
		||||
            cd.parse(str);
 | 
			
		||||
        });
 | 
			
		||||
      cd.parse(str)
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    });
 | 
			
		||||
  describe('when fetching data from an classDiagram graph it', function () {
 | 
			
		||||
    var cd, cDDb
 | 
			
		||||
    beforeEach(function () {
 | 
			
		||||
      cd = require('./parser/classDiagram').parser
 | 
			
		||||
      cDDb = require('./classDb')
 | 
			
		||||
      cd.yy = cDDb
 | 
			
		||||
      cd.yy.clear()
 | 
			
		||||
    })
 | 
			
		||||
    it('should handle relation definitions EXTENSION', function () {
 | 
			
		||||
      var str = 'classDiagram\n' +
 | 
			
		||||
                        'Class01 <|-- Class02'
 | 
			
		||||
 | 
			
		||||
    describe('when fetching data from an classDiagram graph it', function () {
 | 
			
		||||
        var cd, cDDb;
 | 
			
		||||
        beforeEach(function () {
 | 
			
		||||
            cd = require('./parser/classDiagram').parser;
 | 
			
		||||
            cDDb = require('./classDb');
 | 
			
		||||
            cd.yy = cDDb;
 | 
			
		||||
            cd.yy.clear();
 | 
			
		||||
        });
 | 
			
		||||
        it('should handle relation definitions EXTENSION', function () {
 | 
			
		||||
            var str =   'classDiagram\n'+
 | 
			
		||||
                        'Class01 <|-- Class02';
 | 
			
		||||
      cd.parse(str)
 | 
			
		||||
 | 
			
		||||
            cd.parse(str);
 | 
			
		||||
      var relations = cd.yy.getRelations()
 | 
			
		||||
 | 
			
		||||
            var relations = cd.yy.getRelations();
 | 
			
		||||
      expect(cd.yy.getClass('Class01').id).toBe('Class01')
 | 
			
		||||
      expect(cd.yy.getClass('Class02').id).toBe('Class02')
 | 
			
		||||
      expect(relations[0].relation.type1).toBe(cDDb.relationType.EXTENSION)
 | 
			
		||||
      expect(relations[0].relation.type2).toBe('none')
 | 
			
		||||
      expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE)
 | 
			
		||||
    })
 | 
			
		||||
    it('should handle relation definitions AGGREGATION and dotted line', function () {
 | 
			
		||||
      var str = 'classDiagram\n' +
 | 
			
		||||
                        'Class01 o.. Class02'
 | 
			
		||||
 | 
			
		||||
            expect(cd.yy.getClass('Class01').id).toBe('Class01');
 | 
			
		||||
            expect(cd.yy.getClass('Class02').id).toBe('Class02');
 | 
			
		||||
            expect(relations[0].relation.type1).toBe(cDDb.relationType.EXTENSION);
 | 
			
		||||
            expect(relations[0].relation.type2).toBe('none');
 | 
			
		||||
            expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE);
 | 
			
		||||
        });
 | 
			
		||||
        it('should handle relation definitions AGGREGATION and dotted line', function () {
 | 
			
		||||
            var str =   'classDiagram\n'+
 | 
			
		||||
                        'Class01 o.. Class02';
 | 
			
		||||
      cd.parse(str)
 | 
			
		||||
 | 
			
		||||
            cd.parse(str);
 | 
			
		||||
      var relations = cd.yy.getRelations()
 | 
			
		||||
 | 
			
		||||
            var relations = cd.yy.getRelations();
 | 
			
		||||
      expect(cd.yy.getClass('Class01').id).toBe('Class01')
 | 
			
		||||
      expect(cd.yy.getClass('Class02').id).toBe('Class02')
 | 
			
		||||
      expect(relations[0].relation.type1).toBe(cDDb.relationType.AGGREGATION)
 | 
			
		||||
      expect(relations[0].relation.type2).toBe('none')
 | 
			
		||||
      expect(relations[0].relation.lineType).toBe(cDDb.lineType.DOTTED_LINE)
 | 
			
		||||
    })
 | 
			
		||||
    it('should handle relation definitions COMPOSITION on both sides', function () {
 | 
			
		||||
      var str = 'classDiagram\n' +
 | 
			
		||||
                       'Class01 *--* Class02'
 | 
			
		||||
 | 
			
		||||
            expect(cd.yy.getClass('Class01').id).toBe('Class01');
 | 
			
		||||
            expect(cd.yy.getClass('Class02').id).toBe('Class02');
 | 
			
		||||
            expect(relations[0].relation.type1).toBe(cDDb.relationType.AGGREGATION);
 | 
			
		||||
            expect(relations[0].relation.type2).toBe('none');
 | 
			
		||||
            expect(relations[0].relation.lineType).toBe(cDDb.lineType.DOTTED_LINE);
 | 
			
		||||
        });
 | 
			
		||||
        it('should handle relation definitions COMPOSITION on both sides', function () {
 | 
			
		||||
            var str =  'classDiagram\n'+
 | 
			
		||||
                       'Class01 *--* Class02';
 | 
			
		||||
      cd.parse(str)
 | 
			
		||||
 | 
			
		||||
            cd.parse(str);
 | 
			
		||||
      var relations = cd.yy.getRelations()
 | 
			
		||||
 | 
			
		||||
            var relations = cd.yy.getRelations();
 | 
			
		||||
      expect(cd.yy.getClass('Class01').id).toBe('Class01')
 | 
			
		||||
      expect(cd.yy.getClass('Class02').id).toBe('Class02')
 | 
			
		||||
      expect(relations[0].relation.type1).toBe(cDDb.relationType.COMPOSITION)
 | 
			
		||||
      expect(relations[0].relation.type2).toBe(cDDb.relationType.COMPOSITION)
 | 
			
		||||
      expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE)
 | 
			
		||||
    })
 | 
			
		||||
    it('should handle relation definitions no types', function () {
 | 
			
		||||
      var str = 'classDiagram\n' +
 | 
			
		||||
                        'Class01 -- Class02'
 | 
			
		||||
 | 
			
		||||
            expect(cd.yy.getClass('Class01').id).toBe('Class01');
 | 
			
		||||
            expect(cd.yy.getClass('Class02').id).toBe('Class02');
 | 
			
		||||
            expect(relations[0].relation.type1).toBe(cDDb.relationType.COMPOSITION);
 | 
			
		||||
            expect(relations[0].relation.type2).toBe(cDDb.relationType.COMPOSITION);
 | 
			
		||||
            expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE);
 | 
			
		||||
        });
 | 
			
		||||
        it('should handle relation definitions no types', function () {
 | 
			
		||||
            var str =   'classDiagram\n'+
 | 
			
		||||
                        'Class01 -- Class02';
 | 
			
		||||
      cd.parse(str)
 | 
			
		||||
 | 
			
		||||
            cd.parse(str);
 | 
			
		||||
      var relations = cd.yy.getRelations()
 | 
			
		||||
 | 
			
		||||
            var relations = cd.yy.getRelations();
 | 
			
		||||
      expect(cd.yy.getClass('Class01').id).toBe('Class01')
 | 
			
		||||
      expect(cd.yy.getClass('Class02').id).toBe('Class02')
 | 
			
		||||
      expect(relations[0].relation.type1).toBe('none')
 | 
			
		||||
      expect(relations[0].relation.type2).toBe('none')
 | 
			
		||||
      expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE)
 | 
			
		||||
    })
 | 
			
		||||
    it('should handle relation definitions with type only on right side', function () {
 | 
			
		||||
      var str = 'classDiagram\n' +
 | 
			
		||||
                       'Class01 --|> Class02'
 | 
			
		||||
 | 
			
		||||
            expect(cd.yy.getClass('Class01').id).toBe('Class01');
 | 
			
		||||
            expect(cd.yy.getClass('Class02').id).toBe('Class02');
 | 
			
		||||
            expect(relations[0].relation.type1).toBe('none');
 | 
			
		||||
            expect(relations[0].relation.type2).toBe('none');
 | 
			
		||||
            expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE);
 | 
			
		||||
        });
 | 
			
		||||
        it('should handle relation definitions with type only on right side', function () {
 | 
			
		||||
            var str =  'classDiagram\n'+
 | 
			
		||||
                       'Class01 --|> Class02';
 | 
			
		||||
      cd.parse(str)
 | 
			
		||||
 | 
			
		||||
            cd.parse(str);
 | 
			
		||||
      var relations = cd.yy.getRelations()
 | 
			
		||||
 | 
			
		||||
            var relations = cd.yy.getRelations();
 | 
			
		||||
      expect(cd.yy.getClass('Class01').id).toBe('Class01')
 | 
			
		||||
      expect(cd.yy.getClass('Class02').id).toBe('Class02')
 | 
			
		||||
      expect(relations[0].relation.type1).toBe('none')
 | 
			
		||||
      expect(relations[0].relation.type2).toBe(cDDb.relationType.EXTENSION)
 | 
			
		||||
      expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE)
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
            expect(cd.yy.getClass('Class01').id).toBe('Class01');
 | 
			
		||||
            expect(cd.yy.getClass('Class02').id).toBe('Class02');
 | 
			
		||||
            expect(relations[0].relation.type1).toBe('none');
 | 
			
		||||
            expect(relations[0].relation.type2).toBe(cDDb.relationType.EXTENSION);
 | 
			
		||||
            expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE);
 | 
			
		||||
        });
 | 
			
		||||
    it('should handle multiple classes and relation definitions', function () {
 | 
			
		||||
      var str = 'classDiagram\n' +
 | 
			
		||||
                        'Class01 <|-- Class02\n' +
 | 
			
		||||
                        'Class03 *-- Class04\n' +
 | 
			
		||||
                        'Class05 o-- Class06\n' +
 | 
			
		||||
                        'Class07 .. Class08\n' +
 | 
			
		||||
                        'Class09 -- Class10'
 | 
			
		||||
 | 
			
		||||
        it('should handle multiple classes and relation definitions', function () {
 | 
			
		||||
            var str =   'classDiagram\n'+
 | 
			
		||||
                        'Class01 <|-- Class02\n'+
 | 
			
		||||
                        'Class03 *-- Class04\n'+
 | 
			
		||||
                        'Class05 o-- Class06\n'+
 | 
			
		||||
                        'Class07 .. Class08\n'+
 | 
			
		||||
                        'Class09 -- Class10';
 | 
			
		||||
      cd.parse(str)
 | 
			
		||||
 | 
			
		||||
            cd.parse(str);
 | 
			
		||||
      var relations = cd.yy.getRelations()
 | 
			
		||||
 | 
			
		||||
            var relations = cd.yy.getRelations();
 | 
			
		||||
      expect(cd.yy.getClass('Class01').id).toBe('Class01')
 | 
			
		||||
      expect(cd.yy.getClass('Class10').id).toBe('Class10')
 | 
			
		||||
 | 
			
		||||
            expect(cd.yy.getClass('Class01').id).toBe('Class01');
 | 
			
		||||
            expect(cd.yy.getClass('Class10').id).toBe('Class10');
 | 
			
		||||
      expect(relations.length).toBe(5)
 | 
			
		||||
 | 
			
		||||
            expect(relations.length).toBe(5);
 | 
			
		||||
 | 
			
		||||
            expect(relations[0].relation.type1).toBe(cDDb.relationType.EXTENSION);
 | 
			
		||||
            expect(relations[0].relation.type2).toBe('none');
 | 
			
		||||
            expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE);
 | 
			
		||||
            expect(relations[3].relation.type1).toBe('none');
 | 
			
		||||
            expect(relations[3].relation.type2).toBe('none');
 | 
			
		||||
            expect(relations[3].relation.lineType).toBe(cDDb.lineType.DOTTED_LINE);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
      expect(relations[0].relation.type1).toBe(cDDb.relationType.EXTENSION)
 | 
			
		||||
      expect(relations[0].relation.type2).toBe('none')
 | 
			
		||||
      expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE)
 | 
			
		||||
      expect(relations[3].relation.type1).toBe('none')
 | 
			
		||||
      expect(relations[3].relation.type2).toBe('none')
 | 
			
		||||
      expect(relations[3].relation.lineType).toBe(cDDb.lineType.DOTTED_LINE)
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
 
 | 
			
		||||
@@ -2,43 +2,43 @@
 | 
			
		||||
 * Created by knut on 14-11-23.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
var cd = require('./parser/classDiagram').parser;
 | 
			
		||||
var cDDb = require('./classDb');
 | 
			
		||||
cd.yy = cDDb;
 | 
			
		||||
var d3 = require('../../d3');
 | 
			
		||||
var Logger = require('../../logger');
 | 
			
		||||
var log = Logger.Log;
 | 
			
		||||
var dagre = require('dagre');
 | 
			
		||||
var cd = require('./parser/classDiagram').parser
 | 
			
		||||
var cDDb = require('./classDb')
 | 
			
		||||
cd.yy = cDDb
 | 
			
		||||
var d3 = require('../../d3')
 | 
			
		||||
var Logger = require('../../logger')
 | 
			
		||||
var log = Logger.Log
 | 
			
		||||
var dagre = require('dagre')
 | 
			
		||||
 | 
			
		||||
var idCache;
 | 
			
		||||
idCache = {};
 | 
			
		||||
var idCache
 | 
			
		||||
idCache = {}
 | 
			
		||||
 | 
			
		||||
var classCnt = 0;
 | 
			
		||||
var classCnt = 0
 | 
			
		||||
var conf = {
 | 
			
		||||
    dividerMargin: 10,
 | 
			
		||||
    padding: 5,
 | 
			
		||||
    textHeight: 14
 | 
			
		||||
};
 | 
			
		||||
  dividerMargin: 10,
 | 
			
		||||
  padding: 5,
 | 
			
		||||
  textHeight: 14
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Todo optimize
 | 
			
		||||
var getGraphId = function (label) {
 | 
			
		||||
    var keys = Object.keys(idCache);
 | 
			
		||||
  var keys = Object.keys(idCache)
 | 
			
		||||
 | 
			
		||||
    var i;
 | 
			
		||||
    for(i=0;i<keys.length;i++){
 | 
			
		||||
      if(idCache[keys[i]].label === label){
 | 
			
		||||
          return keys[i];
 | 
			
		||||
      }
 | 
			
		||||
  var i
 | 
			
		||||
  for (i = 0; i < keys.length; i++) {
 | 
			
		||||
    if (idCache[keys[i]].label === label) {
 | 
			
		||||
      return keys[i]
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    return undefined;
 | 
			
		||||
  return undefined
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Setup arrow head and define the marker. The result is appended to the svg.
 | 
			
		||||
 */
 | 
			
		||||
var insertMarkers = function (elem) {
 | 
			
		||||
    elem.append('defs').append('marker')
 | 
			
		||||
  elem.append('defs').append('marker')
 | 
			
		||||
        .attr('id', 'extensionStart')
 | 
			
		||||
        .attr('class', 'extension')
 | 
			
		||||
        .attr('refX', 0)
 | 
			
		||||
@@ -47,9 +47,9 @@ var insertMarkers = function (elem) {
 | 
			
		||||
        .attr('markerHeight', 240)
 | 
			
		||||
        .attr('orient', 'auto')
 | 
			
		||||
        .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('refX', 19)
 | 
			
		||||
        .attr('refY', 7)
 | 
			
		||||
@@ -57,9 +57,9 @@ var insertMarkers = function (elem) {
 | 
			
		||||
        .attr('markerHeight', 28)
 | 
			
		||||
        .attr('orient', 'auto')
 | 
			
		||||
        .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('class', 'extension')
 | 
			
		||||
        .attr('refX', 0)
 | 
			
		||||
@@ -68,9 +68,9 @@ var insertMarkers = function (elem) {
 | 
			
		||||
        .attr('markerHeight', 240)
 | 
			
		||||
        .attr('orient', 'auto')
 | 
			
		||||
        .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('refX', 19)
 | 
			
		||||
        .attr('refY', 7)
 | 
			
		||||
@@ -78,10 +78,9 @@ var insertMarkers = function (elem) {
 | 
			
		||||
        .attr('markerHeight', 28)
 | 
			
		||||
        .attr('orient', 'auto')
 | 
			
		||||
        .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('class', 'extension')
 | 
			
		||||
        .attr('refX', 0)
 | 
			
		||||
@@ -90,9 +89,9 @@ var insertMarkers = function (elem) {
 | 
			
		||||
        .attr('markerHeight', 240)
 | 
			
		||||
        .attr('orient', 'auto')
 | 
			
		||||
        .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('refX', 19)
 | 
			
		||||
        .attr('refY', 7)
 | 
			
		||||
@@ -100,9 +99,9 @@ var insertMarkers = function (elem) {
 | 
			
		||||
        .attr('markerHeight', 28)
 | 
			
		||||
        .attr('orient', 'auto')
 | 
			
		||||
        .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('class', 'extension')
 | 
			
		||||
        .attr('refX', 0)
 | 
			
		||||
@@ -111,9 +110,9 @@ var insertMarkers = function (elem) {
 | 
			
		||||
        .attr('markerHeight', 240)
 | 
			
		||||
        .attr('orient', 'auto')
 | 
			
		||||
        .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('refX', 19)
 | 
			
		||||
        .attr('refY', 7)
 | 
			
		||||
@@ -121,302 +120,293 @@ var insertMarkers = function (elem) {
 | 
			
		||||
        .attr('markerHeight', 28)
 | 
			
		||||
        .attr('orient', 'auto')
 | 
			
		||||
        .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
 | 
			
		||||
var drawEdge = function (elem, path, relation) {
 | 
			
		||||
    var getRelationType = function (type) {
 | 
			
		||||
        switch (type) {
 | 
			
		||||
            case cDDb.relationType.AGGREGATION:
 | 
			
		||||
                return 'aggregation';
 | 
			
		||||
            case cDDb.relationType.EXTENSION:
 | 
			
		||||
                return 'extension';
 | 
			
		||||
            case cDDb.relationType.COMPOSITION:
 | 
			
		||||
                return 'composition';
 | 
			
		||||
            case cDDb.relationType.DEPENDENCY:
 | 
			
		||||
                return 'dependency';
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
  var getRelationType = function (type) {
 | 
			
		||||
    switch (type) {
 | 
			
		||||
      case cDDb.relationType.AGGREGATION:
 | 
			
		||||
        return 'aggregation'
 | 
			
		||||
      case cDDb.relationType.EXTENSION:
 | 
			
		||||
        return 'extension'
 | 
			
		||||
      case cDDb.relationType.COMPOSITION:
 | 
			
		||||
        return 'composition'
 | 
			
		||||
      case cDDb.relationType.DEPENDENCY:
 | 
			
		||||
        return 'dependency'
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    // The data for our line
 | 
			
		||||
  var lineData = path.points
 | 
			
		||||
 | 
			
		||||
    //The data for our line
 | 
			
		||||
    var lineData = path.points;
 | 
			
		||||
 | 
			
		||||
    //This is the accessor function we talked about above
 | 
			
		||||
    var lineFunction = d3.svg.line()
 | 
			
		||||
    // This is the accessor function we talked about above
 | 
			
		||||
  var lineFunction = d3.svg.line()
 | 
			
		||||
        .x(function (d) {
 | 
			
		||||
            return d.x;
 | 
			
		||||
          return d.x
 | 
			
		||||
        })
 | 
			
		||||
        .y(function (d) {
 | 
			
		||||
            return d.y;
 | 
			
		||||
          return d.y
 | 
			
		||||
        })
 | 
			
		||||
        //.interpolate('cardinal');
 | 
			
		||||
        .interpolate('basis');
 | 
			
		||||
        // .interpolate('cardinal');
 | 
			
		||||
        .interpolate('basis')
 | 
			
		||||
 | 
			
		||||
    var svgPath = elem.append('path')
 | 
			
		||||
  var svgPath = elem.append('path')
 | 
			
		||||
        .attr('d', lineFunction(lineData))
 | 
			
		||||
        .attr('id', 'edge' + edgeCount)
 | 
			
		||||
        .attr('class', 'relation');
 | 
			
		||||
    var url =  '';
 | 
			
		||||
    if(conf.arrowMarkerAbsolute){
 | 
			
		||||
        url =  window.location.protocol+'//'+window.location.host+window.location.pathname +window.location.search;
 | 
			
		||||
        url = url.replace(/\(/g,'\\(');
 | 
			
		||||
        url = url.replace(/\)/g,'\\)');
 | 
			
		||||
    }
 | 
			
		||||
        .attr('class', 'relation')
 | 
			
		||||
  var url = ''
 | 
			
		||||
  if (conf.arrowMarkerAbsolute) {
 | 
			
		||||
    url = window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.search
 | 
			
		||||
    url = url.replace(/\(/g, '\\(')
 | 
			
		||||
    url = url.replace(/\)/g, '\\)')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    //console.log(relation.relation.type1);
 | 
			
		||||
    if (relation.relation.type1 !== 'none') {
 | 
			
		||||
        svgPath.attr('marker-start', 'url(' + url + '#' + getRelationType(relation.relation.type1) + 'Start' + ')');
 | 
			
		||||
    }
 | 
			
		||||
    if (relation.relation.type2 !== 'none') {
 | 
			
		||||
        svgPath.attr('marker-end', 'url(' + url + '#' + getRelationType(relation.relation.type2) + 'End' + ')');
 | 
			
		||||
    }
 | 
			
		||||
    // console.log(relation.relation.type1);
 | 
			
		||||
  if (relation.relation.type1 !== 'none') {
 | 
			
		||||
    svgPath.attr('marker-start', 'url(' + url + '#' + getRelationType(relation.relation.type1) + 'Start' + ')')
 | 
			
		||||
  }
 | 
			
		||||
  if (relation.relation.type2 !== 'none') {
 | 
			
		||||
    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 l = path.points.length;
 | 
			
		||||
    if ((l % 2) !== 0) {
 | 
			
		||||
        var p1 = path.points[Math.floor(l / 2)];
 | 
			
		||||
        var p2 = path.points[Math.ceil(l / 2)];
 | 
			
		||||
        x = (p1.x + p2.x) / 2;
 | 
			
		||||
        y = (p1.y + p2.y) / 2;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        var p = path.points[Math.floor(l / 2)];
 | 
			
		||||
        x = p.x;
 | 
			
		||||
        y = p.y;
 | 
			
		||||
    }
 | 
			
		||||
    // 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 l = path.points.length
 | 
			
		||||
  if ((l % 2) !== 0) {
 | 
			
		||||
    var p1 = path.points[Math.floor(l / 2)]
 | 
			
		||||
    var p2 = path.points[Math.ceil(l / 2)]
 | 
			
		||||
    x = (p1.x + p2.x) / 2
 | 
			
		||||
    y = (p1.y + p2.y) / 2
 | 
			
		||||
  } else {
 | 
			
		||||
    var p = path.points[Math.floor(l / 2)]
 | 
			
		||||
    x = p.x
 | 
			
		||||
    y = p.y
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    if (typeof relation.title !== 'undefined') {
 | 
			
		||||
        var g = elem.append('g').
 | 
			
		||||
            attr('class','classLabel');
 | 
			
		||||
        var label = g.append('text')
 | 
			
		||||
  if (typeof relation.title !== 'undefined') {
 | 
			
		||||
    var g = elem.append('g')
 | 
			
		||||
            .attr('class', 'classLabel')
 | 
			
		||||
    var label = g.append('text')
 | 
			
		||||
            .attr('class', 'label')
 | 
			
		||||
            .attr('x', x)
 | 
			
		||||
            .attr('y', y)
 | 
			
		||||
            .attr('fill', 'red')
 | 
			
		||||
            .attr('text-anchor', 'middle')
 | 
			
		||||
            .text(relation.title);
 | 
			
		||||
            .text(relation.title)
 | 
			
		||||
 | 
			
		||||
        window.label = label;
 | 
			
		||||
        var bounds = label.node().getBBox();
 | 
			
		||||
    window.label = label
 | 
			
		||||
    var bounds = label.node().getBBox()
 | 
			
		||||
 | 
			
		||||
        g.insert('rect', ':first-child')
 | 
			
		||||
    g.insert('rect', ':first-child')
 | 
			
		||||
            .attr('class', 'box')
 | 
			
		||||
            .attr('x', bounds.x-conf.padding/2)
 | 
			
		||||
            .attr('y', bounds.y-conf.padding/2)
 | 
			
		||||
            .attr('width', bounds.width + 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%')
 | 
			
		||||
            .attr('x', bounds.x - conf.padding / 2)
 | 
			
		||||
            .attr('y', bounds.y - conf.padding / 2)
 | 
			
		||||
            .attr('width', bounds.width + 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++
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var drawClass = function (elem, classDef) {
 | 
			
		||||
    log.info('Rendering class ' + classDef);
 | 
			
		||||
  log.info('Rendering class ' + classDef)
 | 
			
		||||
 | 
			
		||||
    var addTspan = function (textEl, txt, isFirst) {
 | 
			
		||||
        var tSpan = textEl.append('tspan')
 | 
			
		||||
  var addTspan = function (textEl, txt, isFirst) {
 | 
			
		||||
    var tSpan = textEl.append('tspan')
 | 
			
		||||
            .attr('x', conf.padding)
 | 
			
		||||
            .text(txt);
 | 
			
		||||
        if (!isFirst) {
 | 
			
		||||
            tSpan.attr('dy', conf.textHeight);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
            .text(txt)
 | 
			
		||||
    if (!isFirst) {
 | 
			
		||||
      tSpan.attr('dy', conf.textHeight)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    var id = 'classId' + classCnt;
 | 
			
		||||
    var classInfo = {
 | 
			
		||||
        id: id,
 | 
			
		||||
        label: classDef.id,
 | 
			
		||||
        width: 0,
 | 
			
		||||
        height: 0
 | 
			
		||||
    };
 | 
			
		||||
  var id = 'classId' + classCnt
 | 
			
		||||
  var classInfo = {
 | 
			
		||||
    id: id,
 | 
			
		||||
    label: classDef.id,
 | 
			
		||||
    width: 0,
 | 
			
		||||
    height: 0
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    var g = elem.append('g')
 | 
			
		||||
  var g = elem.append('g')
 | 
			
		||||
        .attr('id', id)
 | 
			
		||||
        .attr('class', 'classGroup');
 | 
			
		||||
    var title = g.append('text')
 | 
			
		||||
        .attr('class', 'classGroup')
 | 
			
		||||
  var title = g.append('text')
 | 
			
		||||
        .attr('x', 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('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('y', titleHeight + (conf.dividerMargin) + conf.textHeight)
 | 
			
		||||
        .attr('fill', 'white')
 | 
			
		||||
        .attr('class', 'classText');
 | 
			
		||||
        .attr('class', 'classText')
 | 
			
		||||
 | 
			
		||||
    var isFirst = true;
 | 
			
		||||
  var isFirst = true
 | 
			
		||||
 | 
			
		||||
    classDef.members.forEach(function(member){
 | 
			
		||||
            addTspan(members, member, isFirst);
 | 
			
		||||
            isFirst = false;
 | 
			
		||||
    });
 | 
			
		||||
    //for (var member of classDef.members) {
 | 
			
		||||
  classDef.members.forEach(function (member) {
 | 
			
		||||
    addTspan(members, member, isFirst)
 | 
			
		||||
    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('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('y', titleHeight + 2 * conf.dividerMargin + membersBox.height + conf.textHeight)
 | 
			
		||||
        .attr('fill', 'white')
 | 
			
		||||
        .attr('class', 'classText');
 | 
			
		||||
        .attr('class', 'classText')
 | 
			
		||||
 | 
			
		||||
    isFirst = true;
 | 
			
		||||
  isFirst = true
 | 
			
		||||
 | 
			
		||||
    classDef.methods.forEach(function(method){
 | 
			
		||||
            addTspan(methods, method, isFirst);
 | 
			
		||||
            isFirst = false;
 | 
			
		||||
    });
 | 
			
		||||
    //for (var method of classDef.methods) {
 | 
			
		||||
  classDef.methods.forEach(function (method) {
 | 
			
		||||
    addTspan(methods, method, isFirst)
 | 
			
		||||
    isFirst = false
 | 
			
		||||
  })
 | 
			
		||||
    // for (var method of classDef.methods) {
 | 
			
		||||
    //    addTspan(methods, method, isFirst);
 | 
			
		||||
    //    isFirst = false;
 | 
			
		||||
    //}
 | 
			
		||||
    // }
 | 
			
		||||
 | 
			
		||||
    var classBox = g.node().getBBox();
 | 
			
		||||
    g.insert('rect', ':first-child')
 | 
			
		||||
  var classBox = g.node().getBBox()
 | 
			
		||||
  g.insert('rect', ':first-child')
 | 
			
		||||
        .attr('x', 0)
 | 
			
		||||
        .attr('y', 0)
 | 
			
		||||
        .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)
 | 
			
		||||
  methodsLine.attr('x2', classBox.width + 2 * conf.padding)
 | 
			
		||||
 | 
			
		||||
    membersLine.attr('x2', classBox.width + 2 * conf.padding);
 | 
			
		||||
    methodsLine.attr('x2', classBox.width + 2 * conf.padding);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    classInfo.width = classBox.width + 2 * conf.padding;
 | 
			
		||||
    classInfo.height = classBox.height + conf.padding + 0.5 * conf.dividerMargin;
 | 
			
		||||
 | 
			
		||||
    idCache[id] = classInfo;
 | 
			
		||||
    classCnt++;
 | 
			
		||||
    return classInfo;
 | 
			
		||||
};
 | 
			
		||||
  classInfo.width = classBox.width + 2 * conf.padding
 | 
			
		||||
  classInfo.height = classBox.height + conf.padding + 0.5 * conf.dividerMargin
 | 
			
		||||
 | 
			
		||||
  idCache[id] = classInfo
 | 
			
		||||
  classCnt++
 | 
			
		||||
  return classInfo
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports.setConf = function (cnf) {
 | 
			
		||||
    var keys = Object.keys(cnf);
 | 
			
		||||
  var keys = Object.keys(cnf)
 | 
			
		||||
 | 
			
		||||
    keys.forEach(function (key) {
 | 
			
		||||
        conf[key] = cnf[key];
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
  keys.forEach(function (key) {
 | 
			
		||||
    conf[key] = cnf[key]
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
/**
 | 
			
		||||
 * Draws a flowchart in the tag with id: id based on the graph definition in text.
 | 
			
		||||
 * @param text
 | 
			
		||||
 * @param id
 | 
			
		||||
 */
 | 
			
		||||
module.exports.draw = function (text, id) {
 | 
			
		||||
    cd.yy.clear();
 | 
			
		||||
    cd.parse(text);
 | 
			
		||||
  cd.yy.clear()
 | 
			
		||||
  cd.parse(text)
 | 
			
		||||
 | 
			
		||||
    log.info('Rendering diagram ' + text);
 | 
			
		||||
  log.info('Rendering diagram ' + text)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //// Fetch the default direction, use TD if none was found
 | 
			
		||||
    var diagram = d3.select('#' + id);
 | 
			
		||||
    insertMarkers(diagram);
 | 
			
		||||
    //var svg = diagram.append('svg');
 | 
			
		||||
    /// / Fetch the default direction, use TD if none was found
 | 
			
		||||
  var diagram = d3.select('#' + id)
 | 
			
		||||
  insertMarkers(diagram)
 | 
			
		||||
    // var svg = diagram.append('svg');
 | 
			
		||||
 | 
			
		||||
    // Layout graph, Create a new directed graph
 | 
			
		||||
    var g = new dagre.graphlib.Graph({
 | 
			
		||||
        multigraph: true
 | 
			
		||||
    });
 | 
			
		||||
  var g = new dagre.graphlib.Graph({
 | 
			
		||||
    multigraph: true
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    // Set an object for the graph label
 | 
			
		||||
    g.setGraph({
 | 
			
		||||
        isMultiGraph: true
 | 
			
		||||
    });
 | 
			
		||||
  g.setGraph({
 | 
			
		||||
    isMultiGraph: true
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    // Default to assigning a new object as a label for each new edge.
 | 
			
		||||
    g.setDefaultEdgeLabel(function () {
 | 
			
		||||
        return {};
 | 
			
		||||
    });
 | 
			
		||||
  g.setDefaultEdgeLabel(function () {
 | 
			
		||||
    return {}
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    var classes = cDDb.getClasses();
 | 
			
		||||
    var keys = Object.keys(classes);
 | 
			
		||||
    var i;
 | 
			
		||||
    for (i=0;i<keys.length;i++) {
 | 
			
		||||
        var classDef = classes[keys[i]];
 | 
			
		||||
        var node = drawClass(diagram, classDef);
 | 
			
		||||
  var classes = cDDb.getClasses()
 | 
			
		||||
  var keys = Object.keys(classes)
 | 
			
		||||
  var i
 | 
			
		||||
  for (i = 0; i < keys.length; i++) {
 | 
			
		||||
    var classDef = classes[keys[i]]
 | 
			
		||||
    var node = drawClass(diagram, classDef)
 | 
			
		||||
        // 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
 | 
			
		||||
        // our nodes.
 | 
			
		||||
        g.setNode(node.id, node);
 | 
			
		||||
        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 });
 | 
			
		||||
    }
 | 
			
		||||
    g.setNode(node.id, node)
 | 
			
		||||
    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 i = 0;
 | 
			
		||||
    relations.forEach(function(relation){
 | 
			
		||||
            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});
 | 
			
		||||
    });
 | 
			
		||||
    //for (var relation of relations) {
 | 
			
		||||
  var relations = cDDb.getRelations()
 | 
			
		||||
  var i = 0
 | 
			
		||||
  relations.forEach(function (relation) {
 | 
			
		||||
    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})
 | 
			
		||||
  })
 | 
			
		||||
    // 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);
 | 
			
		||||
    g.nodes().forEach(function (v) {
 | 
			
		||||
        if(typeof v !== 'undefined'){
 | 
			
		||||
            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 +' 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) {
 | 
			
		||||
        log.debug('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(g.edge(e)));
 | 
			
		||||
        drawEdge(diagram, g.edge(e), g.edge(e).relation);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // }
 | 
			
		||||
  dagre.layout(g)
 | 
			
		||||
  g.nodes().forEach(function (v) {
 | 
			
		||||
    if (typeof v !== 'undefined') {
 | 
			
		||||
      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 +' 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) {
 | 
			
		||||
    log.debug('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(g.edge(e)))
 | 
			
		||||
    drawEdge(diagram, g.edge(e), g.edge(e).relation)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    diagram.attr('height', '100%');
 | 
			
		||||
    diagram.attr('width', '100%');
 | 
			
		||||
    diagram.attr('viewBox', '0 0 ' + (g.graph().width + 20) + ' ' + (g.graph().height + 20));
 | 
			
		||||
  diagram.attr('height', '100%')
 | 
			
		||||
  diagram.attr('width', '100%')
 | 
			
		||||
  diagram.attr('viewBox', '0 0 ' + (g.graph().width + 20) + ' ' + (g.graph().height + 20))
 | 
			
		||||
    //
 | 
			
		||||
    //
 | 
			
		||||
    //
 | 
			
		||||
    //
 | 
			
		||||
    //if(conf.useMaxWidth) {
 | 
			
		||||
    // if(conf.useMaxWidth) {
 | 
			
		||||
    //    diagram.attr('height', '100%');
 | 
			
		||||
    //    diagram.attr('width', '100%');
 | 
			
		||||
    //    diagram.attr('style', 'max-width:' + (width) + 'px;');
 | 
			
		||||
    //}else{
 | 
			
		||||
    // }else{
 | 
			
		||||
    //    diagram.attr('height',height);
 | 
			
		||||
    //    diagram.attr('width', width );
 | 
			
		||||
    //}
 | 
			
		||||
    //diagram.attr('viewBox', (box.startx-conf.diagramMarginX) + ' -' +conf.diagramMarginY + ' ' + width + ' ' + height);
 | 
			
		||||
};
 | 
			
		||||
    // }
 | 
			
		||||
    // diagram.attr('viewBox', (box.startx-conf.diagramMarginX) + ' -' +conf.diagramMarginY + ' ' + width + ' ' + height);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,38 +1,37 @@
 | 
			
		||||
//var proxyquire = require('proxyquire');
 | 
			
		||||
//var newD3;
 | 
			
		||||
///**
 | 
			
		||||
// var proxyquire = require('proxyquire');
 | 
			
		||||
// var newD3;
 | 
			
		||||
/// **
 | 
			
		||||
// * Created by knut on 14-11-18.
 | 
			
		||||
// */
 | 
			
		||||
//
 | 
			
		||||
//var d3 = {
 | 
			
		||||
// 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;
 | 
			
		||||
// 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('when rendering a classDiagram',function() {
 | 
			
		||||
        var conf;
 | 
			
		||||
        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;
 | 
			
		||||
  describe('when rendering a classDiagram', function () {
 | 
			
		||||
    var conf
 | 
			
		||||
    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() {
 | 
			
		||||
            // newD3 = function() {
 | 
			
		||||
            //    var o = {
 | 
			
		||||
            //        append: function () {
 | 
			
		||||
            //            return newD3();
 | 
			
		||||
@@ -60,9 +59,9 @@ describe('class diagram, ', function () {
 | 
			
		||||
            //    };
 | 
			
		||||
            //
 | 
			
		||||
            //    return o;
 | 
			
		||||
            //};
 | 
			
		||||
            // };
 | 
			
		||||
            //
 | 
			
		||||
            //conf = {
 | 
			
		||||
            // conf = {
 | 
			
		||||
            //    diagramMarginX:50,
 | 
			
		||||
            //    diagramMarginY:10,
 | 
			
		||||
            //    actorMargin:50,
 | 
			
		||||
@@ -77,37 +76,36 @@ describe('class diagram, ', function () {
 | 
			
		||||
            //    // Depending on css styling this might need adjustment
 | 
			
		||||
            //    // Prolongs the edge of the diagram downwards
 | 
			
		||||
            //    bottomMarginAdj:1
 | 
			
		||||
            //};
 | 
			
		||||
            //classRenderer.setConf(conf);
 | 
			
		||||
            // };
 | 
			
		||||
            // classRenderer.setConf(conf);
 | 
			
		||||
 | 
			
		||||
                // ... add whatever browser globals your tests might need ...
 | 
			
		||||
            //}
 | 
			
		||||
            Object.defineProperties(window.HTMLElement.prototype, {
 | 
			
		||||
                getBBox :{
 | 
			
		||||
                    get : function() {return {x:10,y:10,width:100,height:100}; }
 | 
			
		||||
                },
 | 
			
		||||
                offsetLeft: {
 | 
			
		||||
                    get: function() { return parseFloat(window.getComputedStyle(this).marginLeft) || 0; }
 | 
			
		||||
                },
 | 
			
		||||
                offsetTop: {
 | 
			
		||||
                    get: function() { return parseFloat(window.getComputedStyle(this).marginTop) || 0; }
 | 
			
		||||
                },
 | 
			
		||||
                offsetHeight: {
 | 
			
		||||
                    get: function() { return parseFloat(window.getComputedStyle(this).height) || 0; }
 | 
			
		||||
                },
 | 
			
		||||
                offsetWidth: {
 | 
			
		||||
                    get: function() { return parseFloat(window.getComputedStyle(this).width) || 0; }
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
        it('it should handle one actor', function () {
 | 
			
		||||
            var str = 'classDiagram\n'+
 | 
			
		||||
            'Class01 --|> Class02';
 | 
			
		||||
            // }
 | 
			
		||||
      Object.defineProperties(window.HTMLElement.prototype, {
 | 
			
		||||
        getBBox: {
 | 
			
		||||
          get: function () { return {x: 10, y: 10, width: 100, height: 100} }
 | 
			
		||||
        },
 | 
			
		||||
        offsetLeft: {
 | 
			
		||||
          get: function () { return parseFloat(window.getComputedStyle(this).marginLeft) || 0 }
 | 
			
		||||
        },
 | 
			
		||||
        offsetTop: {
 | 
			
		||||
          get: function () { return parseFloat(window.getComputedStyle(this).marginTop) || 0 }
 | 
			
		||||
        },
 | 
			
		||||
        offsetHeight: {
 | 
			
		||||
          get: function () { return parseFloat(window.getComputedStyle(this).height) || 0 }
 | 
			
		||||
        },
 | 
			
		||||
        offsetWidth: {
 | 
			
		||||
          get: function () { return parseFloat(window.getComputedStyle(this).width) || 0 }
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('it should handle one actor', function () {
 | 
			
		||||
      var str = 'classDiagram\n' +
 | 
			
		||||
            'Class01 --|> Class02'
 | 
			
		||||
 | 
			
		||||
            //classRenderer.draw(str,'tst');
 | 
			
		||||
            // classRenderer.draw(str,'tst');
 | 
			
		||||
 | 
			
		||||
            //console.log(document.body.innerHTML);
 | 
			
		||||
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
            // console.log(document.body.innerHTML);
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,21 +1,21 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Created by knut on 14-11-18.
 | 
			
		||||
 */
 | 
			
		||||
describe('when parsing an info graph it',function() {
 | 
			
		||||
    var ex;
 | 
			
		||||
    beforeEach(function () {
 | 
			
		||||
        ex = require('./parser/example').parser;
 | 
			
		||||
        ex.yy = require('./exampleDb');
 | 
			
		||||
    });
 | 
			
		||||
describe('when parsing an info graph it', function () {
 | 
			
		||||
  var ex
 | 
			
		||||
  beforeEach(function () {
 | 
			
		||||
    ex = require('./parser/example').parser
 | 
			
		||||
    ex.yy = require('./exampleDb')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    it('should handle an info definition', function () {
 | 
			
		||||
        var str = 'info\nsay: hello';
 | 
			
		||||
  it('should handle an info definition', function () {
 | 
			
		||||
    var str = 'info\nsay: hello'
 | 
			
		||||
 | 
			
		||||
        ex.parse(str);
 | 
			
		||||
    });
 | 
			
		||||
    it('should handle an showMessage statement definition', function () {
 | 
			
		||||
        var str = 'info\nshowInfo';
 | 
			
		||||
    ex.parse(str)
 | 
			
		||||
  })
 | 
			
		||||
  it('should handle an showMessage statement definition', function () {
 | 
			
		||||
    var str = 'info\nshowInfo'
 | 
			
		||||
 | 
			
		||||
        ex.parse(str);
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
    ex.parse(str)
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
 
 | 
			
		||||
@@ -1,29 +1,29 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Created by knut on 15-01-14.
 | 
			
		||||
 */
 | 
			
		||||
var Logger = require('../../logger');
 | 
			
		||||
var log = Logger.Log;
 | 
			
		||||
var Logger = require('../../logger')
 | 
			
		||||
var log = Logger.Log
 | 
			
		||||
 | 
			
		||||
var message = '';
 | 
			
		||||
var info = false;
 | 
			
		||||
var message = ''
 | 
			
		||||
var info = false
 | 
			
		||||
 | 
			
		||||
exports.setMessage = function(txt){
 | 
			
		||||
    log.debug('Setting message to: '+txt);
 | 
			
		||||
    message = txt;
 | 
			
		||||
};
 | 
			
		||||
exports.setMessage = function (txt) {
 | 
			
		||||
  log.debug('Setting message to: ' + txt)
 | 
			
		||||
  message = txt
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.getMessage = function(){
 | 
			
		||||
    return message;
 | 
			
		||||
};
 | 
			
		||||
exports.getMessage = function () {
 | 
			
		||||
  return message
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.setInfo = function(inf){
 | 
			
		||||
    info = inf;
 | 
			
		||||
};
 | 
			
		||||
exports.setInfo = function (inf) {
 | 
			
		||||
  info = inf
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.getInfo = function(){
 | 
			
		||||
    return info;
 | 
			
		||||
};
 | 
			
		||||
exports.getInfo = function () {
 | 
			
		||||
  return info
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.parseError = function(err,hash){
 | 
			
		||||
    global.mermaidAPI.parseError(err,hash);
 | 
			
		||||
};
 | 
			
		||||
exports.parseError = function (err, hash) {
 | 
			
		||||
  global.mermaidAPI.parseError(err, hash)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,12 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Created by knut on 14-12-11.
 | 
			
		||||
 */
 | 
			
		||||
var db = require('./exampleDb');
 | 
			
		||||
var exampleParser = require('./parser/example.js');
 | 
			
		||||
var d3 = require('../../d3');
 | 
			
		||||
var db = require('./exampleDb')
 | 
			
		||||
var exampleParser = require('./parser/example.js')
 | 
			
		||||
var d3 = require('../../d3')
 | 
			
		||||
 | 
			
		||||
var Logger = require('../../logger');
 | 
			
		||||
var log = Logger.Log;
 | 
			
		||||
var Logger = require('../../logger')
 | 
			
		||||
var log = Logger.Log
 | 
			
		||||
// var log = new Logger.Log();
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -15,33 +15,33 @@ var log = Logger.Log;
 | 
			
		||||
 * @param id
 | 
			
		||||
 */
 | 
			
		||||
exports.draw = function (txt, id, ver) {
 | 
			
		||||
    var parser;
 | 
			
		||||
    parser = exampleParser.parser;
 | 
			
		||||
    parser.yy = db;
 | 
			
		||||
    log.debug('Renering example diagram');
 | 
			
		||||
  var parser
 | 
			
		||||
  parser = exampleParser.parser
 | 
			
		||||
  parser.yy = db
 | 
			
		||||
  log.debug('Renering example diagram')
 | 
			
		||||
    // Parse the graph definition
 | 
			
		||||
    parser.parse(txt);
 | 
			
		||||
  parser.parse(txt)
 | 
			
		||||
 | 
			
		||||
    // 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('y', 40)
 | 
			
		||||
        .attr('class','version')
 | 
			
		||||
        .attr('font-size','32px')
 | 
			
		||||
        .attr('class', 'version')
 | 
			
		||||
        .attr('font-size', '32px')
 | 
			
		||||
        .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;*/
 | 
			
		||||
    var width  = box.stopx-box.startx+2*conf.diagramMarginX; */
 | 
			
		||||
 | 
			
		||||
    svg.attr('height',100);
 | 
			
		||||
    svg.attr('width', 400 );
 | 
			
		||||
    //svg.attr('viewBox', '0 0 300 150');
 | 
			
		||||
};
 | 
			
		||||
  svg.attr('height', 100)
 | 
			
		||||
  svg.attr('width', 400)
 | 
			
		||||
    // svg.attr('viewBox', '0 0 300 150');
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -50,7 +50,6 @@
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  token location info (@$, _$, etc.): {
 | 
			
		||||
    first_line: n,
 | 
			
		||||
    last_line: n,
 | 
			
		||||
@@ -59,7 +58,6 @@
 | 
			
		||||
    range: [start_number, end_number]       (where the numbers are indexes into the input string, regular zero-based)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  the parseError function receives a 'hash' object with these members for lexer and parser errors: {
 | 
			
		||||
    text:        (matched text)
 | 
			
		||||
    token:       (the produced terminal token, if any)
 | 
			
		||||
@@ -71,560 +69,558 @@
 | 
			
		||||
    recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
 | 
			
		||||
  }
 | 
			
		||||
*/
 | 
			
		||||
var parser = (function(){
 | 
			
		||||
var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[6,9,10,12];
 | 
			
		||||
var parser = {trace: function trace() { },
 | 
			
		||||
yy: {},
 | 
			
		||||
symbols_: {"error":2,"start":3,"info":4,"document":5,"EOF":6,"line":7,"statement":8,"NL":9,"showInfo":10,"message":11,"say":12,"TXT":13,"$accept":0,"$end":1},
 | 
			
		||||
terminals_: {2:"error",4:"info",6:"EOF",9:"NL",10:"showInfo",12:"say",13:"TXT"},
 | 
			
		||||
productions_: [0,[3,3],[5,0],[5,2],[7,1],[7,1],[8,1],[8,1],[11,2]],
 | 
			
		||||
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
 | 
			
		||||
var parser = (function () {
 | 
			
		||||
  var o = function (k, v, o, l) { for (o = o || {}, l = k.length; l--; o[k[l]] = v);return o }, $V0 = [6, 9, 10, 12]
 | 
			
		||||
  var parser = {trace: function trace () { },
 | 
			
		||||
    yy: {},
 | 
			
		||||
    symbols_: {'error': 2, 'start': 3, 'info': 4, 'document': 5, 'EOF': 6, 'line': 7, 'statement': 8, 'NL': 9, 'showInfo': 10, 'message': 11, 'say': 12, 'TXT': 13, '$accept': 0, '$end': 1},
 | 
			
		||||
    terminals_: {2: 'error', 4: 'info', 6: 'EOF', 9: 'NL', 10: 'showInfo', 12: 'say', 13: 'TXT'},
 | 
			
		||||
    productions_: [0, [3, 3], [5, 0], [5, 2], [7, 1], [7, 1], [8, 1], [8, 1], [11, 2]],
 | 
			
		||||
    performAction: function anonymous (yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
 | 
			
		||||
/* this == yyval */
 | 
			
		||||
 | 
			
		||||
var $0 = $$.length - 1;
 | 
			
		||||
switch (yystate) {
 | 
			
		||||
case 1:
 | 
			
		||||
 return yy; 
 | 
			
		||||
break;
 | 
			
		||||
case 4:
 | 
			
		||||
 
 | 
			
		||||
break;
 | 
			
		||||
case 6:
 | 
			
		||||
 yy.setInfo(true);  
 | 
			
		||||
break;
 | 
			
		||||
case 7:
 | 
			
		||||
 yy.setMessage($$[$0]);  
 | 
			
		||||
break;
 | 
			
		||||
case 8:
 | 
			
		||||
 this.$ = $$[$0-1].substring(1).trim().replace(/\\n/gm, "\n"); 
 | 
			
		||||
break;
 | 
			
		||||
}
 | 
			
		||||
},
 | 
			
		||||
table: [{3:1,4:[1,2]},{1:[3]},o($V0,[2,2],{5:3}),{6:[1,4],7:5,8:6,9:[1,7],10:[1,8],11:9,12:[1,10]},{1:[2,1]},o($V0,[2,3]),o($V0,[2,4]),o($V0,[2,5]),o($V0,[2,6]),o($V0,[2,7]),{13:[1,11]},o($V0,[2,8])],
 | 
			
		||||
defaultActions: {4:[2,1]},
 | 
			
		||||
parseError: function parseError(str, hash) {
 | 
			
		||||
    if (hash.recoverable) {
 | 
			
		||||
        this.trace(str);
 | 
			
		||||
    } else {
 | 
			
		||||
        function _parseError (msg, hash) {
 | 
			
		||||
            this.message = msg;
 | 
			
		||||
            this.hash = hash;
 | 
			
		||||
        }
 | 
			
		||||
        _parseError.prototype = Error;
 | 
			
		||||
      var $0 = $$.length - 1
 | 
			
		||||
      switch (yystate) {
 | 
			
		||||
        case 1:
 | 
			
		||||
          return yy
 | 
			
		||||
          break
 | 
			
		||||
        case 4:
 | 
			
		||||
 | 
			
		||||
        throw new _parseError(str, hash);
 | 
			
		||||
    }
 | 
			
		||||
},
 | 
			
		||||
parse: function parse(input) {
 | 
			
		||||
    var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
 | 
			
		||||
    var args = lstack.slice.call(arguments, 1);
 | 
			
		||||
    var lexer = Object.create(this.lexer);
 | 
			
		||||
    var sharedState = { yy: {} };
 | 
			
		||||
    for (var k in this.yy) {
 | 
			
		||||
          break
 | 
			
		||||
        case 6:
 | 
			
		||||
          yy.setInfo(true)
 | 
			
		||||
          break
 | 
			
		||||
        case 7:
 | 
			
		||||
          yy.setMessage($$[$0])
 | 
			
		||||
          break
 | 
			
		||||
        case 8:
 | 
			
		||||
          this.$ = $$[$0 - 1].substring(1).trim().replace(/\\n/gm, '\n')
 | 
			
		||||
          break
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    table: [{3: 1, 4: [1, 2]}, {1: [3]}, o($V0, [2, 2], {5: 3}), {6: [1, 4], 7: 5, 8: 6, 9: [1, 7], 10: [1, 8], 11: 9, 12: [1, 10]}, {1: [2, 1]}, o($V0, [2, 3]), o($V0, [2, 4]), o($V0, [2, 5]), o($V0, [2, 6]), o($V0, [2, 7]), {13: [1, 11]}, o($V0, [2, 8])],
 | 
			
		||||
    defaultActions: {4: [2, 1]},
 | 
			
		||||
    parseError: function parseError (str, hash) {
 | 
			
		||||
      if (hash.recoverable) {
 | 
			
		||||
        this.trace(str)
 | 
			
		||||
      } else {
 | 
			
		||||
        function _parseError (msg, hash) {
 | 
			
		||||
          this.message = msg
 | 
			
		||||
          this.hash = hash
 | 
			
		||||
        }
 | 
			
		||||
        _parseError.prototype = Error
 | 
			
		||||
 | 
			
		||||
        throw new _parseError(str, hash)
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    parse: function parse (input) {
 | 
			
		||||
      var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1
 | 
			
		||||
      var args = lstack.slice.call(arguments, 1)
 | 
			
		||||
      var lexer = Object.create(this.lexer)
 | 
			
		||||
      var sharedState = { yy: {} }
 | 
			
		||||
      for (var k in this.yy) {
 | 
			
		||||
        if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
 | 
			
		||||
            sharedState.yy[k] = this.yy[k];
 | 
			
		||||
          sharedState.yy[k] = this.yy[k]
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    lexer.setInput(input, sharedState.yy);
 | 
			
		||||
    sharedState.yy.lexer = lexer;
 | 
			
		||||
    sharedState.yy.parser = this;
 | 
			
		||||
    if (typeof lexer.yylloc == 'undefined') {
 | 
			
		||||
        lexer.yylloc = {};
 | 
			
		||||
    }
 | 
			
		||||
    var yyloc = lexer.yylloc;
 | 
			
		||||
    lstack.push(yyloc);
 | 
			
		||||
    var ranges = lexer.options && lexer.options.ranges;
 | 
			
		||||
    if (typeof sharedState.yy.parseError === 'function') {
 | 
			
		||||
        this.parseError = sharedState.yy.parseError;
 | 
			
		||||
    } else {
 | 
			
		||||
        this.parseError = Object.getPrototypeOf(this).parseError;
 | 
			
		||||
    }
 | 
			
		||||
    function popStack(n) {
 | 
			
		||||
        stack.length = stack.length - 2 * n;
 | 
			
		||||
        vstack.length = vstack.length - n;
 | 
			
		||||
        lstack.length = lstack.length - n;
 | 
			
		||||
    }
 | 
			
		||||
    _token_stack:
 | 
			
		||||
      }
 | 
			
		||||
      lexer.setInput(input, sharedState.yy)
 | 
			
		||||
      sharedState.yy.lexer = lexer
 | 
			
		||||
      sharedState.yy.parser = this
 | 
			
		||||
      if (typeof lexer.yylloc === 'undefined') {
 | 
			
		||||
        lexer.yylloc = {}
 | 
			
		||||
      }
 | 
			
		||||
      var yyloc = lexer.yylloc
 | 
			
		||||
      lstack.push(yyloc)
 | 
			
		||||
      var ranges = lexer.options && lexer.options.ranges
 | 
			
		||||
      if (typeof sharedState.yy.parseError === 'function') {
 | 
			
		||||
        this.parseError = sharedState.yy.parseError
 | 
			
		||||
      } else {
 | 
			
		||||
        this.parseError = Object.getPrototypeOf(this).parseError
 | 
			
		||||
      }
 | 
			
		||||
      function popStack (n) {
 | 
			
		||||
        stack.length = stack.length - 2 * n
 | 
			
		||||
        vstack.length = vstack.length - n
 | 
			
		||||
        lstack.length = lstack.length - n
 | 
			
		||||
      }
 | 
			
		||||
      _token_stack:
 | 
			
		||||
        var lex = function () {
 | 
			
		||||
            var token;
 | 
			
		||||
            token = lexer.lex() || EOF;
 | 
			
		||||
            if (typeof token !== 'number') {
 | 
			
		||||
                token = self.symbols_[token] || token;
 | 
			
		||||
            }
 | 
			
		||||
            return token;
 | 
			
		||||
        };
 | 
			
		||||
    var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
 | 
			
		||||
    while (true) {
 | 
			
		||||
        state = stack[stack.length - 1];
 | 
			
		||||
        if (this.defaultActions[state]) {
 | 
			
		||||
            action = this.defaultActions[state];
 | 
			
		||||
        } else {
 | 
			
		||||
            if (symbol === null || typeof symbol == 'undefined') {
 | 
			
		||||
                symbol = lex();
 | 
			
		||||
            }
 | 
			
		||||
            action = table[state] && table[state][symbol];
 | 
			
		||||
          var token
 | 
			
		||||
          token = lexer.lex() || EOF
 | 
			
		||||
          if (typeof token !== 'number') {
 | 
			
		||||
            token = self.symbols_[token] || token
 | 
			
		||||
          }
 | 
			
		||||
          return token
 | 
			
		||||
        }
 | 
			
		||||
                    if (typeof action === 'undefined' || !action.length || !action[0]) {
 | 
			
		||||
                var errStr = '';
 | 
			
		||||
                expected = [];
 | 
			
		||||
                for (p in table[state]) {
 | 
			
		||||
                    if (this.terminals_[p] && p > TERROR) {
 | 
			
		||||
                        expected.push('\'' + this.terminals_[p] + '\'');
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                if (lexer.showPosition) {
 | 
			
		||||
                    errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
 | 
			
		||||
                } else {
 | 
			
		||||
                    errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
 | 
			
		||||
                }
 | 
			
		||||
                this.parseError(errStr, {
 | 
			
		||||
                    text: lexer.match,
 | 
			
		||||
                    token: this.terminals_[symbol] || symbol,
 | 
			
		||||
                    line: lexer.yylineno,
 | 
			
		||||
                    loc: yyloc,
 | 
			
		||||
                    expected: expected
 | 
			
		||||
                });
 | 
			
		||||
      var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected
 | 
			
		||||
      while (true) {
 | 
			
		||||
        state = stack[stack.length - 1]
 | 
			
		||||
        if (this.defaultActions[state]) {
 | 
			
		||||
          action = this.defaultActions[state]
 | 
			
		||||
        } else {
 | 
			
		||||
          if (symbol === null || typeof symbol === 'undefined') {
 | 
			
		||||
            symbol = lex()
 | 
			
		||||
          }
 | 
			
		||||
          action = table[state] && table[state][symbol]
 | 
			
		||||
        }
 | 
			
		||||
        if (typeof action === 'undefined' || !action.length || !action[0]) {
 | 
			
		||||
          var errStr = ''
 | 
			
		||||
          expected = []
 | 
			
		||||
          for (p in table[state]) {
 | 
			
		||||
            if (this.terminals_[p] && p > TERROR) {
 | 
			
		||||
              expected.push('\'' + this.terminals_[p] + '\'')
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          if (lexer.showPosition) {
 | 
			
		||||
            errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\''
 | 
			
		||||
          } else {
 | 
			
		||||
            errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'')
 | 
			
		||||
          }
 | 
			
		||||
          this.parseError(errStr, {
 | 
			
		||||
            text: lexer.match,
 | 
			
		||||
            token: this.terminals_[symbol] || symbol,
 | 
			
		||||
            line: lexer.yylineno,
 | 
			
		||||
            loc: yyloc,
 | 
			
		||||
            expected: expected
 | 
			
		||||
          })
 | 
			
		||||
        }
 | 
			
		||||
        if (action[0] instanceof Array && action.length > 1) {
 | 
			
		||||
            throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
 | 
			
		||||
          throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol)
 | 
			
		||||
        }
 | 
			
		||||
        switch (action[0]) {
 | 
			
		||||
        case 1:
 | 
			
		||||
            stack.push(symbol);
 | 
			
		||||
            vstack.push(lexer.yytext);
 | 
			
		||||
            lstack.push(lexer.yylloc);
 | 
			
		||||
            stack.push(action[1]);
 | 
			
		||||
            symbol = null;
 | 
			
		||||
          case 1:
 | 
			
		||||
            stack.push(symbol)
 | 
			
		||||
            vstack.push(lexer.yytext)
 | 
			
		||||
            lstack.push(lexer.yylloc)
 | 
			
		||||
            stack.push(action[1])
 | 
			
		||||
            symbol = null
 | 
			
		||||
            if (!preErrorSymbol) {
 | 
			
		||||
                yyleng = lexer.yyleng;
 | 
			
		||||
                yytext = lexer.yytext;
 | 
			
		||||
                yylineno = lexer.yylineno;
 | 
			
		||||
                yyloc = lexer.yylloc;
 | 
			
		||||
                if (recovering > 0) {
 | 
			
		||||
                    recovering--;
 | 
			
		||||
                }
 | 
			
		||||
              yyleng = lexer.yyleng
 | 
			
		||||
              yytext = lexer.yytext
 | 
			
		||||
              yylineno = lexer.yylineno
 | 
			
		||||
              yyloc = lexer.yylloc
 | 
			
		||||
              if (recovering > 0) {
 | 
			
		||||
                recovering--
 | 
			
		||||
              }
 | 
			
		||||
            } else {
 | 
			
		||||
                symbol = preErrorSymbol;
 | 
			
		||||
                preErrorSymbol = null;
 | 
			
		||||
              symbol = preErrorSymbol
 | 
			
		||||
              preErrorSymbol = null
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case 2:
 | 
			
		||||
            len = this.productions_[action[1]][1];
 | 
			
		||||
            yyval.$ = vstack[vstack.length - len];
 | 
			
		||||
            break
 | 
			
		||||
          case 2:
 | 
			
		||||
            len = this.productions_[action[1]][1]
 | 
			
		||||
            yyval.$ = vstack[vstack.length - len]
 | 
			
		||||
            yyval._$ = {
 | 
			
		||||
                first_line: lstack[lstack.length - (len || 1)].first_line,
 | 
			
		||||
                last_line: lstack[lstack.length - 1].last_line,
 | 
			
		||||
                first_column: lstack[lstack.length - (len || 1)].first_column,
 | 
			
		||||
                last_column: lstack[lstack.length - 1].last_column
 | 
			
		||||
            };
 | 
			
		||||
              first_line: lstack[lstack.length - (len || 1)].first_line,
 | 
			
		||||
              last_line: lstack[lstack.length - 1].last_line,
 | 
			
		||||
              first_column: lstack[lstack.length - (len || 1)].first_column,
 | 
			
		||||
              last_column: lstack[lstack.length - 1].last_column
 | 
			
		||||
            }
 | 
			
		||||
            if (ranges) {
 | 
			
		||||
                yyval._$.range = [
 | 
			
		||||
                    lstack[lstack.length - (len || 1)].range[0],
 | 
			
		||||
                    lstack[lstack.length - 1].range[1]
 | 
			
		||||
                ];
 | 
			
		||||
              yyval._$.range = [
 | 
			
		||||
                lstack[lstack.length - (len || 1)].range[0],
 | 
			
		||||
                lstack[lstack.length - 1].range[1]
 | 
			
		||||
              ]
 | 
			
		||||
            }
 | 
			
		||||
            r = this.performAction.apply(yyval, [
 | 
			
		||||
                yytext,
 | 
			
		||||
                yyleng,
 | 
			
		||||
                yylineno,
 | 
			
		||||
                sharedState.yy,
 | 
			
		||||
                action[1],
 | 
			
		||||
                vstack,
 | 
			
		||||
                lstack
 | 
			
		||||
            ].concat(args));
 | 
			
		||||
              yytext,
 | 
			
		||||
              yyleng,
 | 
			
		||||
              yylineno,
 | 
			
		||||
              sharedState.yy,
 | 
			
		||||
              action[1],
 | 
			
		||||
              vstack,
 | 
			
		||||
              lstack
 | 
			
		||||
            ].concat(args))
 | 
			
		||||
            if (typeof r !== 'undefined') {
 | 
			
		||||
                return r;
 | 
			
		||||
              return r
 | 
			
		||||
            }
 | 
			
		||||
            if (len) {
 | 
			
		||||
                stack = stack.slice(0, -1 * len * 2);
 | 
			
		||||
                vstack = vstack.slice(0, -1 * len);
 | 
			
		||||
                lstack = lstack.slice(0, -1 * len);
 | 
			
		||||
              stack = stack.slice(0, -1 * len * 2)
 | 
			
		||||
              vstack = vstack.slice(0, -1 * len)
 | 
			
		||||
              lstack = lstack.slice(0, -1 * len)
 | 
			
		||||
            }
 | 
			
		||||
            stack.push(this.productions_[action[1]][0]);
 | 
			
		||||
            vstack.push(yyval.$);
 | 
			
		||||
            lstack.push(yyval._$);
 | 
			
		||||
            newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
 | 
			
		||||
            stack.push(newState);
 | 
			
		||||
            break;
 | 
			
		||||
        case 3:
 | 
			
		||||
            return true;
 | 
			
		||||
            stack.push(this.productions_[action[1]][0])
 | 
			
		||||
            vstack.push(yyval.$)
 | 
			
		||||
            lstack.push(yyval._$)
 | 
			
		||||
            newState = table[stack[stack.length - 2]][stack[stack.length - 1]]
 | 
			
		||||
            stack.push(newState)
 | 
			
		||||
            break
 | 
			
		||||
          case 3:
 | 
			
		||||
            return true
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}};
 | 
			
		||||
      }
 | 
			
		||||
      return true
 | 
			
		||||
    }}
 | 
			
		||||
/* generated by jison-lex 0.3.4 */
 | 
			
		||||
var lexer = (function(){
 | 
			
		||||
var lexer = ({
 | 
			
		||||
  var lexer = (function () {
 | 
			
		||||
    var lexer = ({
 | 
			
		||||
 | 
			
		||||
EOF:1,
 | 
			
		||||
      EOF: 1,
 | 
			
		||||
 | 
			
		||||
parseError:function parseError(str, hash) {
 | 
			
		||||
      parseError: function parseError (str, hash) {
 | 
			
		||||
        if (this.yy.parser) {
 | 
			
		||||
            this.yy.parser.parseError(str, hash);
 | 
			
		||||
          this.yy.parser.parseError(str, hash)
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new Error(str);
 | 
			
		||||
          throw new Error(str)
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
// resets the lexer, sets new input
 | 
			
		||||
setInput:function (input, yy) {
 | 
			
		||||
        this.yy = yy || this.yy || {};
 | 
			
		||||
        this._input = input;
 | 
			
		||||
        this._more = this._backtrack = this.done = false;
 | 
			
		||||
        this.yylineno = this.yyleng = 0;
 | 
			
		||||
        this.yytext = this.matched = this.match = '';
 | 
			
		||||
        this.conditionStack = ['INITIAL'];
 | 
			
		||||
      setInput: function (input, yy) {
 | 
			
		||||
        this.yy = yy || this.yy || {}
 | 
			
		||||
        this._input = input
 | 
			
		||||
        this._more = this._backtrack = this.done = false
 | 
			
		||||
        this.yylineno = this.yyleng = 0
 | 
			
		||||
        this.yytext = this.matched = this.match = ''
 | 
			
		||||
        this.conditionStack = ['INITIAL']
 | 
			
		||||
        this.yylloc = {
 | 
			
		||||
            first_line: 1,
 | 
			
		||||
            first_column: 0,
 | 
			
		||||
            last_line: 1,
 | 
			
		||||
            last_column: 0
 | 
			
		||||
        };
 | 
			
		||||
        if (this.options.ranges) {
 | 
			
		||||
            this.yylloc.range = [0,0];
 | 
			
		||||
          first_line: 1,
 | 
			
		||||
          first_column: 0,
 | 
			
		||||
          last_line: 1,
 | 
			
		||||
          last_column: 0
 | 
			
		||||
        }
 | 
			
		||||
        this.offset = 0;
 | 
			
		||||
        return this;
 | 
			
		||||
    },
 | 
			
		||||
        if (this.options.ranges) {
 | 
			
		||||
          this.yylloc.range = [0, 0]
 | 
			
		||||
        }
 | 
			
		||||
        this.offset = 0
 | 
			
		||||
        return this
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
// consumes and returns one char from the input
 | 
			
		||||
input:function () {
 | 
			
		||||
        var ch = this._input[0];
 | 
			
		||||
        this.yytext += ch;
 | 
			
		||||
        this.yyleng++;
 | 
			
		||||
        this.offset++;
 | 
			
		||||
        this.match += ch;
 | 
			
		||||
        this.matched += ch;
 | 
			
		||||
        var lines = ch.match(/(?:\r\n?|\n).*/g);
 | 
			
		||||
      input: function () {
 | 
			
		||||
        var ch = this._input[0]
 | 
			
		||||
        this.yytext += ch
 | 
			
		||||
        this.yyleng++
 | 
			
		||||
        this.offset++
 | 
			
		||||
        this.match += ch
 | 
			
		||||
        this.matched += ch
 | 
			
		||||
        var lines = ch.match(/(?:\r\n?|\n).*/g)
 | 
			
		||||
        if (lines) {
 | 
			
		||||
            this.yylineno++;
 | 
			
		||||
            this.yylloc.last_line++;
 | 
			
		||||
          this.yylineno++
 | 
			
		||||
          this.yylloc.last_line++
 | 
			
		||||
        } else {
 | 
			
		||||
            this.yylloc.last_column++;
 | 
			
		||||
          this.yylloc.last_column++
 | 
			
		||||
        }
 | 
			
		||||
        if (this.options.ranges) {
 | 
			
		||||
            this.yylloc.range[1]++;
 | 
			
		||||
          this.yylloc.range[1]++
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._input = this._input.slice(1);
 | 
			
		||||
        return ch;
 | 
			
		||||
    },
 | 
			
		||||
        this._input = this._input.slice(1)
 | 
			
		||||
        return ch
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
// unshifts one char (or a string) into the input
 | 
			
		||||
unput:function (ch) {
 | 
			
		||||
        var len = ch.length;
 | 
			
		||||
        var lines = ch.split(/(?:\r\n?|\n)/g);
 | 
			
		||||
      unput: function (ch) {
 | 
			
		||||
        var len = ch.length
 | 
			
		||||
        var lines = ch.split(/(?:\r\n?|\n)/g)
 | 
			
		||||
 | 
			
		||||
        this._input = ch + this._input;
 | 
			
		||||
        this.yytext = this.yytext.substr(0, this.yytext.length - len);
 | 
			
		||||
        //this.yyleng -= len;
 | 
			
		||||
        this.offset -= len;
 | 
			
		||||
        var oldLines = this.match.split(/(?:\r\n?|\n)/g);
 | 
			
		||||
        this.match = this.match.substr(0, this.match.length - 1);
 | 
			
		||||
        this.matched = this.matched.substr(0, this.matched.length - 1);
 | 
			
		||||
        this._input = ch + this._input
 | 
			
		||||
        this.yytext = this.yytext.substr(0, this.yytext.length - len)
 | 
			
		||||
        // this.yyleng -= len;
 | 
			
		||||
        this.offset -= len
 | 
			
		||||
        var oldLines = this.match.split(/(?:\r\n?|\n)/g)
 | 
			
		||||
        this.match = this.match.substr(0, this.match.length - 1)
 | 
			
		||||
        this.matched = this.matched.substr(0, this.matched.length - 1)
 | 
			
		||||
 | 
			
		||||
        if (lines.length - 1) {
 | 
			
		||||
            this.yylineno -= lines.length - 1;
 | 
			
		||||
          this.yylineno -= lines.length - 1
 | 
			
		||||
        }
 | 
			
		||||
        var r = this.yylloc.range;
 | 
			
		||||
        var r = this.yylloc.range
 | 
			
		||||
 | 
			
		||||
        this.yylloc = {
 | 
			
		||||
            first_line: this.yylloc.first_line,
 | 
			
		||||
            last_line: this.yylineno + 1,
 | 
			
		||||
            first_column: this.yylloc.first_column,
 | 
			
		||||
            last_column: lines ?
 | 
			
		||||
                (lines.length === oldLines.length ? this.yylloc.first_column : 0)
 | 
			
		||||
                 + oldLines[oldLines.length - lines.length].length - lines[0].length :
 | 
			
		||||
              this.yylloc.first_column - len
 | 
			
		||||
        };
 | 
			
		||||
          first_line: this.yylloc.first_line,
 | 
			
		||||
          last_line: this.yylineno + 1,
 | 
			
		||||
          first_column: this.yylloc.first_column,
 | 
			
		||||
          last_column: lines
 | 
			
		||||
                ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) +
 | 
			
		||||
                 oldLines[oldLines.length - lines.length].length - lines[0].length
 | 
			
		||||
              : this.yylloc.first_column - len
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.options.ranges) {
 | 
			
		||||
            this.yylloc.range = [r[0], r[0] + this.yyleng - len];
 | 
			
		||||
          this.yylloc.range = [r[0], r[0] + this.yyleng - len]
 | 
			
		||||
        }
 | 
			
		||||
        this.yyleng = this.yytext.length;
 | 
			
		||||
        return this;
 | 
			
		||||
    },
 | 
			
		||||
        this.yyleng = this.yytext.length
 | 
			
		||||
        return this
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
// When called from action, caches matched text and appends it on next action
 | 
			
		||||
more:function () {
 | 
			
		||||
        this._more = true;
 | 
			
		||||
        return this;
 | 
			
		||||
    },
 | 
			
		||||
      more: function () {
 | 
			
		||||
        this._more = true
 | 
			
		||||
        return this
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
 | 
			
		||||
reject:function () {
 | 
			
		||||
      reject: function () {
 | 
			
		||||
        if (this.options.backtrack_lexer) {
 | 
			
		||||
            this._backtrack = true;
 | 
			
		||||
          this._backtrack = true
 | 
			
		||||
        } else {
 | 
			
		||||
            return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
 | 
			
		||||
                text: "",
 | 
			
		||||
                token: null,
 | 
			
		||||
                line: this.yylineno
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
          return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
 | 
			
		||||
            text: '',
 | 
			
		||||
            token: null,
 | 
			
		||||
            line: this.yylineno
 | 
			
		||||
          })
 | 
			
		||||
        }
 | 
			
		||||
        return this;
 | 
			
		||||
    },
 | 
			
		||||
        return this
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
// retain first n characters of the match
 | 
			
		||||
less:function (n) {
 | 
			
		||||
        this.unput(this.match.slice(n));
 | 
			
		||||
    },
 | 
			
		||||
      less: function (n) {
 | 
			
		||||
        this.unput(this.match.slice(n))
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
// displays already matched input, i.e. for error messages
 | 
			
		||||
pastInput:function () {
 | 
			
		||||
        var past = this.matched.substr(0, this.matched.length - this.match.length);
 | 
			
		||||
        return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
 | 
			
		||||
    },
 | 
			
		||||
      pastInput: function () {
 | 
			
		||||
        var past = this.matched.substr(0, this.matched.length - this.match.length)
 | 
			
		||||
        return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, '')
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
// displays upcoming input, i.e. for error messages
 | 
			
		||||
upcomingInput:function () {
 | 
			
		||||
        var next = this.match;
 | 
			
		||||
      upcomingInput: function () {
 | 
			
		||||
        var next = this.match
 | 
			
		||||
        if (next.length < 20) {
 | 
			
		||||
            next += this._input.substr(0, 20-next.length);
 | 
			
		||||
          next += this._input.substr(0, 20 - next.length)
 | 
			
		||||
        }
 | 
			
		||||
        return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
 | 
			
		||||
    },
 | 
			
		||||
        return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, '')
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
// displays the character position where the lexing error occurred, i.e. for error messages
 | 
			
		||||
showPosition:function () {
 | 
			
		||||
        var pre = this.pastInput();
 | 
			
		||||
        var c = new Array(pre.length + 1).join("-");
 | 
			
		||||
        return pre + this.upcomingInput() + "\n" + c + "^";
 | 
			
		||||
    },
 | 
			
		||||
      showPosition: function () {
 | 
			
		||||
        var pre = this.pastInput()
 | 
			
		||||
        var c = new Array(pre.length + 1).join('-')
 | 
			
		||||
        return pre + this.upcomingInput() + '\n' + c + '^'
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
// test the lexed token: return FALSE when not a match, otherwise return token
 | 
			
		||||
test_match:function (match, indexed_rule) {
 | 
			
		||||
      test_match: function (match, indexed_rule) {
 | 
			
		||||
        var token,
 | 
			
		||||
            lines,
 | 
			
		||||
            backup;
 | 
			
		||||
          lines,
 | 
			
		||||
          backup
 | 
			
		||||
 | 
			
		||||
        if (this.options.backtrack_lexer) {
 | 
			
		||||
            // save context
 | 
			
		||||
            backup = {
 | 
			
		||||
                yylineno: this.yylineno,
 | 
			
		||||
                yylloc: {
 | 
			
		||||
                    first_line: this.yylloc.first_line,
 | 
			
		||||
                    last_line: this.last_line,
 | 
			
		||||
                    first_column: this.yylloc.first_column,
 | 
			
		||||
                    last_column: this.yylloc.last_column
 | 
			
		||||
                },
 | 
			
		||||
                yytext: this.yytext,
 | 
			
		||||
                match: this.match,
 | 
			
		||||
                matches: this.matches,
 | 
			
		||||
                matched: this.matched,
 | 
			
		||||
                yyleng: this.yyleng,
 | 
			
		||||
                offset: this.offset,
 | 
			
		||||
                _more: this._more,
 | 
			
		||||
                _input: this._input,
 | 
			
		||||
                yy: this.yy,
 | 
			
		||||
                conditionStack: this.conditionStack.slice(0),
 | 
			
		||||
                done: this.done
 | 
			
		||||
            };
 | 
			
		||||
            if (this.options.ranges) {
 | 
			
		||||
                backup.yylloc.range = this.yylloc.range.slice(0);
 | 
			
		||||
            }
 | 
			
		||||
          backup = {
 | 
			
		||||
            yylineno: this.yylineno,
 | 
			
		||||
            yylloc: {
 | 
			
		||||
              first_line: this.yylloc.first_line,
 | 
			
		||||
              last_line: this.last_line,
 | 
			
		||||
              first_column: this.yylloc.first_column,
 | 
			
		||||
              last_column: this.yylloc.last_column
 | 
			
		||||
            },
 | 
			
		||||
            yytext: this.yytext,
 | 
			
		||||
            match: this.match,
 | 
			
		||||
            matches: this.matches,
 | 
			
		||||
            matched: this.matched,
 | 
			
		||||
            yyleng: this.yyleng,
 | 
			
		||||
            offset: this.offset,
 | 
			
		||||
            _more: this._more,
 | 
			
		||||
            _input: this._input,
 | 
			
		||||
            yy: this.yy,
 | 
			
		||||
            conditionStack: this.conditionStack.slice(0),
 | 
			
		||||
            done: this.done
 | 
			
		||||
          }
 | 
			
		||||
          if (this.options.ranges) {
 | 
			
		||||
            backup.yylloc.range = this.yylloc.range.slice(0)
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        lines = match[0].match(/(?:\r\n?|\n).*/g);
 | 
			
		||||
        lines = match[0].match(/(?:\r\n?|\n).*/g)
 | 
			
		||||
        if (lines) {
 | 
			
		||||
            this.yylineno += lines.length;
 | 
			
		||||
          this.yylineno += lines.length
 | 
			
		||||
        }
 | 
			
		||||
        this.yylloc = {
 | 
			
		||||
            first_line: this.yylloc.last_line,
 | 
			
		||||
            last_line: this.yylineno + 1,
 | 
			
		||||
            first_column: this.yylloc.last_column,
 | 
			
		||||
            last_column: lines ?
 | 
			
		||||
                         lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length :
 | 
			
		||||
                         this.yylloc.last_column + match[0].length
 | 
			
		||||
        };
 | 
			
		||||
        this.yytext += match[0];
 | 
			
		||||
        this.match += match[0];
 | 
			
		||||
        this.matches = match;
 | 
			
		||||
        this.yyleng = this.yytext.length;
 | 
			
		||||
        if (this.options.ranges) {
 | 
			
		||||
            this.yylloc.range = [this.offset, this.offset += this.yyleng];
 | 
			
		||||
          first_line: this.yylloc.last_line,
 | 
			
		||||
          last_line: this.yylineno + 1,
 | 
			
		||||
          first_column: this.yylloc.last_column,
 | 
			
		||||
          last_column: lines
 | 
			
		||||
                         ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length
 | 
			
		||||
                         : this.yylloc.last_column + match[0].length
 | 
			
		||||
        }
 | 
			
		||||
        this._more = false;
 | 
			
		||||
        this._backtrack = false;
 | 
			
		||||
        this._input = this._input.slice(match[0].length);
 | 
			
		||||
        this.matched += match[0];
 | 
			
		||||
        token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
 | 
			
		||||
        this.yytext += match[0]
 | 
			
		||||
        this.match += match[0]
 | 
			
		||||
        this.matches = match
 | 
			
		||||
        this.yyleng = this.yytext.length
 | 
			
		||||
        if (this.options.ranges) {
 | 
			
		||||
          this.yylloc.range = [this.offset, this.offset += this.yyleng]
 | 
			
		||||
        }
 | 
			
		||||
        this._more = false
 | 
			
		||||
        this._backtrack = false
 | 
			
		||||
        this._input = this._input.slice(match[0].length)
 | 
			
		||||
        this.matched += match[0]
 | 
			
		||||
        token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1])
 | 
			
		||||
        if (this.done && this._input) {
 | 
			
		||||
            this.done = false;
 | 
			
		||||
          this.done = false
 | 
			
		||||
        }
 | 
			
		||||
        if (token) {
 | 
			
		||||
            return token;
 | 
			
		||||
          return token
 | 
			
		||||
        } else if (this._backtrack) {
 | 
			
		||||
            // recover context
 | 
			
		||||
            for (var k in backup) {
 | 
			
		||||
                this[k] = backup[k];
 | 
			
		||||
            }
 | 
			
		||||
            return false; // rule action called reject() implying the next rule should be tested instead.
 | 
			
		||||
          for (var k in backup) {
 | 
			
		||||
            this[k] = backup[k]
 | 
			
		||||
          }
 | 
			
		||||
          return false // rule action called reject() implying the next rule should be tested instead.
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
        return false
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
// return next match in input
 | 
			
		||||
next:function () {
 | 
			
		||||
      next: function () {
 | 
			
		||||
        if (this.done) {
 | 
			
		||||
            return this.EOF;
 | 
			
		||||
          return this.EOF
 | 
			
		||||
        }
 | 
			
		||||
        if (!this._input) {
 | 
			
		||||
            this.done = true;
 | 
			
		||||
          this.done = true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var token,
 | 
			
		||||
            match,
 | 
			
		||||
            tempMatch,
 | 
			
		||||
            index;
 | 
			
		||||
          match,
 | 
			
		||||
          tempMatch,
 | 
			
		||||
          index
 | 
			
		||||
        if (!this._more) {
 | 
			
		||||
            this.yytext = '';
 | 
			
		||||
            this.match = '';
 | 
			
		||||
          this.yytext = ''
 | 
			
		||||
          this.match = ''
 | 
			
		||||
        }
 | 
			
		||||
        var rules = this._currentRules();
 | 
			
		||||
        var rules = this._currentRules()
 | 
			
		||||
        for (var i = 0; i < rules.length; i++) {
 | 
			
		||||
            tempMatch = this._input.match(this.rules[rules[i]]);
 | 
			
		||||
            if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
 | 
			
		||||
                match = tempMatch;
 | 
			
		||||
                index = i;
 | 
			
		||||
                if (this.options.backtrack_lexer) {
 | 
			
		||||
                    token = this.test_match(tempMatch, rules[i]);
 | 
			
		||||
                    if (token !== false) {
 | 
			
		||||
                        return token;
 | 
			
		||||
                    } else if (this._backtrack) {
 | 
			
		||||
                        match = false;
 | 
			
		||||
                        continue; // rule action called reject() implying a rule MISmatch.
 | 
			
		||||
                    } else {
 | 
			
		||||
          tempMatch = this._input.match(this.rules[rules[i]])
 | 
			
		||||
          if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
 | 
			
		||||
            match = tempMatch
 | 
			
		||||
            index = i
 | 
			
		||||
            if (this.options.backtrack_lexer) {
 | 
			
		||||
              token = this.test_match(tempMatch, rules[i])
 | 
			
		||||
              if (token !== false) {
 | 
			
		||||
                return token
 | 
			
		||||
              } else if (this._backtrack) {
 | 
			
		||||
                match = false
 | 
			
		||||
                continue // rule action called reject() implying a rule MISmatch.
 | 
			
		||||
              } else {
 | 
			
		||||
                        // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
 | 
			
		||||
                        return false;
 | 
			
		||||
                    }
 | 
			
		||||
                } else if (!this.options.flex) {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                return false
 | 
			
		||||
              }
 | 
			
		||||
            } else if (!this.options.flex) {
 | 
			
		||||
              break
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        if (match) {
 | 
			
		||||
            token = this.test_match(match, rules[index]);
 | 
			
		||||
            if (token !== false) {
 | 
			
		||||
                return token;
 | 
			
		||||
            }
 | 
			
		||||
          token = this.test_match(match, rules[index])
 | 
			
		||||
          if (token !== false) {
 | 
			
		||||
            return token
 | 
			
		||||
          }
 | 
			
		||||
            // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
 | 
			
		||||
            return false;
 | 
			
		||||
          return false
 | 
			
		||||
        }
 | 
			
		||||
        if (this._input === "") {
 | 
			
		||||
            return this.EOF;
 | 
			
		||||
        if (this._input === '') {
 | 
			
		||||
          return this.EOF
 | 
			
		||||
        } else {
 | 
			
		||||
            return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
 | 
			
		||||
                text: "",
 | 
			
		||||
                token: null,
 | 
			
		||||
                line: this.yylineno
 | 
			
		||||
            });
 | 
			
		||||
          return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
 | 
			
		||||
            text: '',
 | 
			
		||||
            token: null,
 | 
			
		||||
            line: this.yylineno
 | 
			
		||||
          })
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
// return next match that has a token
 | 
			
		||||
lex:function lex() {
 | 
			
		||||
        var r = this.next();
 | 
			
		||||
      lex: function lex () {
 | 
			
		||||
        var r = this.next()
 | 
			
		||||
        if (r) {
 | 
			
		||||
            return r;
 | 
			
		||||
          return r
 | 
			
		||||
        } else {
 | 
			
		||||
            return this.lex();
 | 
			
		||||
          return this.lex()
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
 | 
			
		||||
begin:function begin(condition) {
 | 
			
		||||
        this.conditionStack.push(condition);
 | 
			
		||||
    },
 | 
			
		||||
      begin: function begin (condition) {
 | 
			
		||||
        this.conditionStack.push(condition)
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
// pop the previously active lexer condition state off the condition stack
 | 
			
		||||
popState:function popState() {
 | 
			
		||||
        var n = this.conditionStack.length - 1;
 | 
			
		||||
      popState: function popState () {
 | 
			
		||||
        var n = this.conditionStack.length - 1
 | 
			
		||||
        if (n > 0) {
 | 
			
		||||
            return this.conditionStack.pop();
 | 
			
		||||
          return this.conditionStack.pop()
 | 
			
		||||
        } else {
 | 
			
		||||
            return this.conditionStack[0];
 | 
			
		||||
          return this.conditionStack[0]
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
// produce the lexer rule set which is active for the currently active lexer condition state
 | 
			
		||||
_currentRules:function _currentRules() {
 | 
			
		||||
      _currentRules: function _currentRules () {
 | 
			
		||||
        if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
 | 
			
		||||
            return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
 | 
			
		||||
          return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules
 | 
			
		||||
        } else {
 | 
			
		||||
            return this.conditions["INITIAL"].rules;
 | 
			
		||||
          return this.conditions['INITIAL'].rules
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
 | 
			
		||||
topState:function topState(n) {
 | 
			
		||||
        n = this.conditionStack.length - 1 - Math.abs(n || 0);
 | 
			
		||||
      topState: function topState (n) {
 | 
			
		||||
        n = this.conditionStack.length - 1 - Math.abs(n || 0)
 | 
			
		||||
        if (n >= 0) {
 | 
			
		||||
            return this.conditionStack[n];
 | 
			
		||||
          return this.conditionStack[n]
 | 
			
		||||
        } else {
 | 
			
		||||
            return "INITIAL";
 | 
			
		||||
          return 'INITIAL'
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
// alias for begin(condition)
 | 
			
		||||
pushState:function pushState(condition) {
 | 
			
		||||
        this.begin(condition);
 | 
			
		||||
    },
 | 
			
		||||
      pushState: function pushState (condition) {
 | 
			
		||||
        this.begin(condition)
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
// return the number of states currently on the stack
 | 
			
		||||
stateStackSize:function stateStackSize() {
 | 
			
		||||
        return this.conditionStack.length;
 | 
			
		||||
    },
 | 
			
		||||
options: {"case-insensitive":true},
 | 
			
		||||
performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
 | 
			
		||||
      stateStackSize: function stateStackSize () {
 | 
			
		||||
        return this.conditionStack.length
 | 
			
		||||
      },
 | 
			
		||||
      options: {'case-insensitive': true},
 | 
			
		||||
      performAction: function anonymous (yy, yy_, $avoiding_name_collisions, YY_START) {
 | 
			
		||||
	// Pre-lexer code can go here
 | 
			
		||||
 | 
			
		||||
var YYSTATE=YY_START;
 | 
			
		||||
switch($avoiding_name_collisions) {
 | 
			
		||||
case 0:return 9;
 | 
			
		||||
break;
 | 
			
		||||
case 1:return 10;
 | 
			
		||||
break;
 | 
			
		||||
case 2:return 4;
 | 
			
		||||
break;
 | 
			
		||||
case 3:return 12;
 | 
			
		||||
break;
 | 
			
		||||
case 4:return 13;
 | 
			
		||||
break;
 | 
			
		||||
case 5:return 6;
 | 
			
		||||
break;
 | 
			
		||||
case 6:return 'INVALID';
 | 
			
		||||
break;
 | 
			
		||||
}
 | 
			
		||||
},
 | 
			
		||||
rules: [/^(?:[\n]+)/i,/^(?:showInfo\b)/i,/^(?:info\b)/i,/^(?:say\b)/i,/^(?::[^#\n;]+)/i,/^(?:$)/i,/^(?:.)/i],
 | 
			
		||||
conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6],"inclusive":true}}
 | 
			
		||||
});
 | 
			
		||||
return lexer;
 | 
			
		||||
})();
 | 
			
		||||
parser.lexer = lexer;
 | 
			
		||||
function Parser () {
 | 
			
		||||
  this.yy = {};
 | 
			
		||||
}
 | 
			
		||||
Parser.prototype = parser;parser.Parser = Parser;
 | 
			
		||||
return new Parser;
 | 
			
		||||
})();
 | 
			
		||||
 | 
			
		||||
        var YYSTATE = YY_START
 | 
			
		||||
        switch ($avoiding_name_collisions) {
 | 
			
		||||
          case 0:return 9
 | 
			
		||||
            break
 | 
			
		||||
          case 1:return 10
 | 
			
		||||
            break
 | 
			
		||||
          case 2:return 4
 | 
			
		||||
            break
 | 
			
		||||
          case 3:return 12
 | 
			
		||||
            break
 | 
			
		||||
          case 4:return 13
 | 
			
		||||
            break
 | 
			
		||||
          case 5:return 6
 | 
			
		||||
            break
 | 
			
		||||
          case 6:return 'INVALID'
 | 
			
		||||
            break
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      rules: [/^(?:[\n]+)/i, /^(?:showInfo\b)/i, /^(?:info\b)/i, /^(?:say\b)/i, /^(?::[^#\n;]+)/i, /^(?:$)/i, /^(?:.)/i],
 | 
			
		||||
      conditions: {'INITIAL': {'rules': [0, 1, 2, 3, 4, 5, 6], 'inclusive': true}}
 | 
			
		||||
    })
 | 
			
		||||
    return lexer
 | 
			
		||||
  })()
 | 
			
		||||
  parser.lexer = lexer
 | 
			
		||||
  function Parser () {
 | 
			
		||||
    this.yy = {}
 | 
			
		||||
  }
 | 
			
		||||
  Parser.prototype = parser; parser.Parser = Parser
 | 
			
		||||
  return new Parser()
 | 
			
		||||
})()
 | 
			
		||||
 | 
			
		||||
if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
 | 
			
		||||
exports.parser = parser;
 | 
			
		||||
exports.Parser = parser.Parser;
 | 
			
		||||
exports.parse = function () { return parser.parse.apply(parser, arguments); };
 | 
			
		||||
exports.main = function commonjsMain(args) {
 | 
			
		||||
  exports.parser = parser
 | 
			
		||||
  exports.Parser = parser.Parser
 | 
			
		||||
  exports.parse = function () { return parser.parse.apply(parser, arguments) }
 | 
			
		||||
  exports.main = function commonjsMain (args) {
 | 
			
		||||
    if (!args[1]) {
 | 
			
		||||
        console.log('Usage: '+args[0]+' FILE');
 | 
			
		||||
        process.exit(1);
 | 
			
		||||
      console.log('Usage: ' + args[0] + ' FILE')
 | 
			
		||||
      process.exit(1)
 | 
			
		||||
    }
 | 
			
		||||
    var source = require('fs').readFileSync(require('path').normalize(args[1]), "utf8");
 | 
			
		||||
    return exports.parser.parse(source);
 | 
			
		||||
};
 | 
			
		||||
if (typeof module !== 'undefined' && require.main === module) {
 | 
			
		||||
  exports.main(process.argv.slice(1));
 | 
			
		||||
    var source = require('fs').readFileSync(require('path').normalize(args[1]), 'utf8')
 | 
			
		||||
    return exports.parser.parse(source)
 | 
			
		||||
  }
 | 
			
		||||
  if (typeof module !== 'undefined' && require.main === module) {
 | 
			
		||||
    exports.main(process.argv.slice(1))
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										4
									
								
								src/diagrams/flowchart/d3.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								src/diagrams/flowchart/d3.js
									
									
									
									
										vendored
									
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
/* global window */
 | 
			
		||||
 | 
			
		||||
/*var d3;
 | 
			
		||||
/* var d3;
 | 
			
		||||
 | 
			
		||||
if (require) {
 | 
			
		||||
  try {
 | 
			
		||||
@@ -12,4 +12,4 @@ if (!d3) {
 | 
			
		||||
  d3 = window.d3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = d3;*/
 | 
			
		||||
module.exports = d3; */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,18 +1,18 @@
 | 
			
		||||
/* global window */
 | 
			
		||||
var Logger = require('../../logger');
 | 
			
		||||
var log = Logger.Log;
 | 
			
		||||
var Logger = require('../../logger')
 | 
			
		||||
var log = Logger.Log
 | 
			
		||||
 | 
			
		||||
var dagreD3;
 | 
			
		||||
//log.debug('setting up dagre-d3');
 | 
			
		||||
var dagreD3
 | 
			
		||||
// log.debug('setting up dagre-d3');
 | 
			
		||||
if (require) {
 | 
			
		||||
  try {
 | 
			
		||||
    dagreD3 = require('dagre-d3');
 | 
			
		||||
      //log.debug('Got it (dagre-d3)');
 | 
			
		||||
  } catch (e) {log.debug('Could not load dagre-d3');}
 | 
			
		||||
    dagreD3 = require('dagre-d3')
 | 
			
		||||
      // log.debug('Got it (dagre-d3)');
 | 
			
		||||
  } catch (e) { log.debug('Could not load dagre-d3') }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if (!dagreD3) {
 | 
			
		||||
  dagreD3 = window.dagreD3;
 | 
			
		||||
  dagreD3 = window.dagreD3
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = dagreD3;
 | 
			
		||||
module.exports = dagreD3
 | 
			
		||||
 
 | 
			
		||||
@@ -1,24 +1,23 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Created by knut on 14-12-11.
 | 
			
		||||
 */
 | 
			
		||||
var graph = require('./graphDb');
 | 
			
		||||
var flow = require('./parser/flow');
 | 
			
		||||
var dot = require('./parser/dot');
 | 
			
		||||
var d3 = require('../../d3');
 | 
			
		||||
var dagreD3 = require('./dagre-d3');
 | 
			
		||||
var Logger = require('../../logger');
 | 
			
		||||
var log = Logger.Log;
 | 
			
		||||
 | 
			
		||||
var graph = require('./graphDb')
 | 
			
		||||
var flow = require('./parser/flow')
 | 
			
		||||
var dot = require('./parser/dot')
 | 
			
		||||
var d3 = require('../../d3')
 | 
			
		||||
var dagreD3 = require('./dagre-d3')
 | 
			
		||||
var Logger = require('../../logger')
 | 
			
		||||
var log = Logger.Log
 | 
			
		||||
 | 
			
		||||
var conf = {
 | 
			
		||||
};
 | 
			
		||||
module.exports.setConf = function(cnf){
 | 
			
		||||
    var keys = Object.keys(cnf);
 | 
			
		||||
    var i;
 | 
			
		||||
    for(i=0;i<keys.length;i++){
 | 
			
		||||
        conf[keys[i]] = cnf[keys[i]];
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
module.exports.setConf = function (cnf) {
 | 
			
		||||
  var keys = Object.keys(cnf)
 | 
			
		||||
  var i
 | 
			
		||||
  for (i = 0; i < keys.length; i++) {
 | 
			
		||||
    conf[keys[i]] = cnf[keys[i]]
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Function that adds the vertices found in the graph definition to the graph to be rendered.
 | 
			
		||||
@@ -26,124 +25,119 @@ module.exports.setConf = function(cnf){
 | 
			
		||||
 * @param g The graph that is to be drawn.
 | 
			
		||||
 */
 | 
			
		||||
exports.addVertices = function (vert, g) {
 | 
			
		||||
    var keys = Object.keys(vert);
 | 
			
		||||
  var keys = Object.keys(vert)
 | 
			
		||||
 | 
			
		||||
    var styleFromStyleArr = function(styleStr,arr){
 | 
			
		||||
        var i;
 | 
			
		||||
  var styleFromStyleArr = function (styleStr, arr) {
 | 
			
		||||
    var i
 | 
			
		||||
        // Create a compound style definition from the style definitions found for the node in the graph definition
 | 
			
		||||
        for (i = 0; i < arr.length; i++) {
 | 
			
		||||
            if (typeof arr[i] !== 'undefined') {
 | 
			
		||||
                styleStr = styleStr + arr[i] + ';';
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    for (i = 0; i < arr.length; i++) {
 | 
			
		||||
      if (typeof arr[i] !== 'undefined') {
 | 
			
		||||
        styleStr = styleStr + arr[i] + ';'
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        return styleStr;
 | 
			
		||||
    };
 | 
			
		||||
    return styleStr
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    // Iterate through each item in the vertice object (containing all the vertices found) in the graph definition
 | 
			
		||||
    keys.forEach(function (id) {
 | 
			
		||||
        var vertice = vert[id];
 | 
			
		||||
        var verticeText;
 | 
			
		||||
  keys.forEach(function (id) {
 | 
			
		||||
    var vertice = vert[id]
 | 
			
		||||
    var verticeText
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Variable for storing the classes for the vertice
 | 
			
		||||
         * @type {string}
 | 
			
		||||
         */
 | 
			
		||||
        var classStr = '';
 | 
			
		||||
    var classStr = ''
 | 
			
		||||
 | 
			
		||||
        //log.debug(vertice.classes);
 | 
			
		||||
        // log.debug(vertice.classes);
 | 
			
		||||
 | 
			
		||||
        if(vertice.classes.length >0){
 | 
			
		||||
            classStr = vertice.classes.join(' ');
 | 
			
		||||
        }
 | 
			
		||||
    if (vertice.classes.length > 0) {
 | 
			
		||||
      classStr = vertice.classes.join(' ')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Variable for storing the extracted style for the vertice
 | 
			
		||||
         * @type {string}
 | 
			
		||||
         */
 | 
			
		||||
        var style = '';
 | 
			
		||||
    var style = ''
 | 
			
		||||
        // Create a compound style definition from the style definitions found for the node in the graph definition
 | 
			
		||||
        style = styleFromStyleArr(style, vertice.styles);
 | 
			
		||||
    style = styleFromStyleArr(style, vertice.styles)
 | 
			
		||||
 | 
			
		||||
        // Use vertice id as text in the box if no text is provided by the graph definition
 | 
			
		||||
        if (typeof vertice.text === 'undefined') {
 | 
			
		||||
            verticeText = vertice.id;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            verticeText = vertice.text;
 | 
			
		||||
        }
 | 
			
		||||
    if (typeof vertice.text === 'undefined') {
 | 
			
		||||
      verticeText = vertice.id
 | 
			
		||||
    } else {
 | 
			
		||||
      verticeText = vertice.text
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var labelTypeStr = ''
 | 
			
		||||
    if (conf.htmlLabels) {
 | 
			
		||||
      labelTypeStr = 'html'
 | 
			
		||||
      verticeText = verticeText.replace(/fa:fa[\w\-]+/g, function (s) {
 | 
			
		||||
        return '<i class="fa ' + s.substring(3) + '"></i>'
 | 
			
		||||
      })
 | 
			
		||||
    } else {
 | 
			
		||||
      var svg_label = document.createElementNS('http://www.w3.org/2000/svg', 'text')
 | 
			
		||||
 | 
			
		||||
      var rows = verticeText.split(/<br>/)
 | 
			
		||||
 | 
			
		||||
        var labelTypeStr = '';
 | 
			
		||||
        if(conf.htmlLabels) {
 | 
			
		||||
            labelTypeStr = 'html';
 | 
			
		||||
            verticeText = verticeText.replace(/fa:fa[\w\-]+/g,function(s){
 | 
			
		||||
                return '<i class="fa '+ s.substring(3)+'"></i>';
 | 
			
		||||
            });
 | 
			
		||||
      var j = 0
 | 
			
		||||
      for (j = 0; j < rows.length; j++) {
 | 
			
		||||
        var tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan')
 | 
			
		||||
        tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve')
 | 
			
		||||
        tspan.setAttribute('dy', '1em')
 | 
			
		||||
        tspan.setAttribute('x', '1')
 | 
			
		||||
        tspan.textContent = rows[j]
 | 
			
		||||
        svg_label.appendChild(tspan)
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
        } else {
 | 
			
		||||
            var svg_label = document.createElementNS('http://www.w3.org/2000/svg', 'text');
 | 
			
		||||
      labelTypeStr = 'svg'
 | 
			
		||||
      verticeText = svg_label
 | 
			
		||||
 | 
			
		||||
            var rows = verticeText.split(/<br>/);
 | 
			
		||||
            // verticeText = verticeText.replace(/<br\/>/g, '\n');
 | 
			
		||||
            // labelTypeStr = 'text';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
            var j = 0;
 | 
			
		||||
            for(j=0;j<rows.length;j++){
 | 
			
		||||
                var tspan = document.createElementNS('http://www.w3.org/2000/svg','tspan');
 | 
			
		||||
                tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
 | 
			
		||||
                tspan.setAttribute('dy', '1em');
 | 
			
		||||
                tspan.setAttribute('x', '1');
 | 
			
		||||
                tspan.textContent = rows[j];
 | 
			
		||||
                svg_label.appendChild(tspan);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            labelTypeStr = 'svg';
 | 
			
		||||
            verticeText = svg_label;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            //verticeText = verticeText.replace(/<br\/>/g, '\n');
 | 
			
		||||
            //labelTypeStr = 'text';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var radious = 0;
 | 
			
		||||
        var _shape = '';
 | 
			
		||||
    var radious = 0
 | 
			
		||||
    var _shape = ''
 | 
			
		||||
 | 
			
		||||
        // Set the shape based parameters
 | 
			
		||||
        switch(vertice.type){
 | 
			
		||||
            case 'round':
 | 
			
		||||
                radious = 5;
 | 
			
		||||
                _shape = 'rect';
 | 
			
		||||
                break;
 | 
			
		||||
            case 'square':
 | 
			
		||||
                _shape = 'rect';
 | 
			
		||||
                break;
 | 
			
		||||
            case 'diamond':
 | 
			
		||||
                _shape = 'question';
 | 
			
		||||
                break;
 | 
			
		||||
            case 'odd':
 | 
			
		||||
                _shape = 'rect_left_inv_arrow';
 | 
			
		||||
                break;
 | 
			
		||||
            case 'odd_right':
 | 
			
		||||
                _shape = 'rect_left_inv_arrow';
 | 
			
		||||
                break;
 | 
			
		||||
            case 'circle':
 | 
			
		||||
                _shape = 'circle';
 | 
			
		||||
                break;
 | 
			
		||||
            case 'ellipse':
 | 
			
		||||
                _shape = 'ellipse';
 | 
			
		||||
                break;
 | 
			
		||||
            case 'group':
 | 
			
		||||
                _shape = 'rect';
 | 
			
		||||
    switch (vertice.type) {
 | 
			
		||||
      case 'round':
 | 
			
		||||
        radious = 5
 | 
			
		||||
        _shape = 'rect'
 | 
			
		||||
        break
 | 
			
		||||
      case 'square':
 | 
			
		||||
        _shape = 'rect'
 | 
			
		||||
        break
 | 
			
		||||
      case 'diamond':
 | 
			
		||||
        _shape = 'question'
 | 
			
		||||
        break
 | 
			
		||||
      case 'odd':
 | 
			
		||||
        _shape = 'rect_left_inv_arrow'
 | 
			
		||||
        break
 | 
			
		||||
      case 'odd_right':
 | 
			
		||||
        _shape = 'rect_left_inv_arrow'
 | 
			
		||||
        break
 | 
			
		||||
      case 'circle':
 | 
			
		||||
        _shape = 'circle'
 | 
			
		||||
        break
 | 
			
		||||
      case 'ellipse':
 | 
			
		||||
        _shape = 'ellipse'
 | 
			
		||||
        break
 | 
			
		||||
      case 'group':
 | 
			
		||||
        _shape = 'rect'
 | 
			
		||||
                // Need to create a text node if using svg labels, see #367
 | 
			
		||||
                verticeText = conf.htmlLabels ? '' : document.createElementNS('http://www.w3.org/2000/svg', 'text');
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                _shape = 'rect';
 | 
			
		||||
        }
 | 
			
		||||
        verticeText = conf.htmlLabels ? '' : document.createElementNS('http://www.w3.org/2000/svg', 'text')
 | 
			
		||||
        break
 | 
			
		||||
      default:
 | 
			
		||||
        _shape = 'rect'
 | 
			
		||||
    }
 | 
			
		||||
        // Add the node
 | 
			
		||||
        g.setNode(vertice.id, {labelType: labelTypeStr, shape:_shape, label: verticeText, rx: radious, ry: radious, 'class': classStr, style: style, id:vertice.id});
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
    g.setNode(vertice.id, {labelType: labelTypeStr, shape: _shape, label: verticeText, rx: radious, ry: radious, 'class': classStr, style: style, id: vertice.id})
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Add edges to graph based on parsed graph defninition
 | 
			
		||||
@@ -151,267 +145,260 @@ exports.addVertices = function (vert, g) {
 | 
			
		||||
 * @param {Object} g The graph object
 | 
			
		||||
 */
 | 
			
		||||
exports.addEdges = function (edges, g) {
 | 
			
		||||
    var cnt=0;
 | 
			
		||||
    
 | 
			
		||||
    var defaultStyle;
 | 
			
		||||
    if(typeof edges.defaultStyle !== 'undefined'){
 | 
			
		||||
        defaultStyle = edges.defaultStyle.toString().replace(/,/g , ';');
 | 
			
		||||
    }
 | 
			
		||||
  var cnt = 0
 | 
			
		||||
 | 
			
		||||
    edges.forEach(function (edge) {
 | 
			
		||||
        cnt++;
 | 
			
		||||
        var edgeData = {};
 | 
			
		||||
  var defaultStyle
 | 
			
		||||
  if (typeof edges.defaultStyle !== 'undefined') {
 | 
			
		||||
    defaultStyle = edges.defaultStyle.toString().replace(/,/g, ';')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  edges.forEach(function (edge) {
 | 
			
		||||
    cnt++
 | 
			
		||||
    var edgeData = {}
 | 
			
		||||
 | 
			
		||||
        // Set link type for rendering
 | 
			
		||||
        if(edge.type === 'arrow_open'){
 | 
			
		||||
            edgeData.arrowhead = 'none';
 | 
			
		||||
        }
 | 
			
		||||
        else{
 | 
			
		||||
            edgeData.arrowhead = 'normal';
 | 
			
		||||
        }
 | 
			
		||||
    if (edge.type === 'arrow_open') {
 | 
			
		||||
      edgeData.arrowhead = 'none'
 | 
			
		||||
    } else {
 | 
			
		||||
      edgeData.arrowhead = 'normal'
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        var style = '';
 | 
			
		||||
    var style = ''
 | 
			
		||||
 | 
			
		||||
    if (typeof edge.style !== 'undefined') {
 | 
			
		||||
      edge.style.forEach(function (s) {
 | 
			
		||||
        style = style + s + ';'
 | 
			
		||||
      })
 | 
			
		||||
    } else {
 | 
			
		||||
      switch (edge.stroke) {
 | 
			
		||||
        case 'normal':
 | 
			
		||||
          style = 'fill:none'
 | 
			
		||||
          if (typeof defaultStyle !== 'undefined') {
 | 
			
		||||
            style = defaultStyle
 | 
			
		||||
          }
 | 
			
		||||
          break
 | 
			
		||||
        case 'dotted':
 | 
			
		||||
          style = 'stroke: #333; fill:none;stroke-width:2px;stroke-dasharray:3;'
 | 
			
		||||
          break
 | 
			
		||||
        case 'thick':
 | 
			
		||||
          style = 'stroke: #333; stroke-width: 3.5px;fill:none'
 | 
			
		||||
          break
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    edgeData.style = style
 | 
			
		||||
 | 
			
		||||
        if(typeof edge.style !== 'undefined'){
 | 
			
		||||
            edge.style.forEach(function(s){
 | 
			
		||||
                style = style + s +';';
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        else{
 | 
			
		||||
            switch(edge.stroke){
 | 
			
		||||
                case 'normal':
 | 
			
		||||
                    style = 'fill:none';
 | 
			
		||||
                    if(typeof defaultStyle !== 'undefined'){
 | 
			
		||||
                        style = defaultStyle;
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
                case 'dotted':
 | 
			
		||||
                    style = 'stroke: #333; fill:none;stroke-width:2px;stroke-dasharray:3;';
 | 
			
		||||
                    break;
 | 
			
		||||
                case 'thick':
 | 
			
		||||
                    style = 'stroke: #333; stroke-width: 3.5px;fill:none';
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        edgeData.style = style;
 | 
			
		||||
        
 | 
			
		||||
        if (typeof edge.interpolate !== 'undefined') {
 | 
			
		||||
            edgeData.lineInterpolate = edge.interpolate;
 | 
			
		||||
    if (typeof edge.interpolate !== 'undefined') {
 | 
			
		||||
      edgeData.lineInterpolate = edge.interpolate
 | 
			
		||||
    } else {
 | 
			
		||||
      if (typeof edges.defaultInterpolate !== 'undefined') {
 | 
			
		||||
        edgeData.lineInterpolate = edges.defaultInterpolate
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (typeof edge.text === 'undefined') {
 | 
			
		||||
      if (typeof edge.style !== 'undefined') {
 | 
			
		||||
        edgeData.arrowheadStyle = 'fill: #333'
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      edgeData.arrowheadStyle = 'fill: #333'
 | 
			
		||||
      if (typeof edge.style === 'undefined') {
 | 
			
		||||
        edgeData.labelpos = 'c'
 | 
			
		||||
        if (conf.htmlLabels) {
 | 
			
		||||
          edgeData.labelType = 'html'
 | 
			
		||||
          edgeData.label = '<span class="edgeLabel">' + edge.text + '</span>'
 | 
			
		||||
        } else {
 | 
			
		||||
            if (typeof edges.defaultInterpolate !== 'undefined') {
 | 
			
		||||
                edgeData.lineInterpolate = edges.defaultInterpolate;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (typeof edge.text === 'undefined') {
 | 
			
		||||
            if (typeof edge.style !== 'undefined') {
 | 
			
		||||
                edgeData.arrowheadStyle = 'fill: #333';
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            edgeData.arrowheadStyle = 'fill: #333';
 | 
			
		||||
            if(typeof edge.style === 'undefined') {
 | 
			
		||||
                edgeData.labelpos = 'c';
 | 
			
		||||
                if (conf.htmlLabels) {
 | 
			
		||||
                    edgeData.labelType = 'html';
 | 
			
		||||
                    edgeData.label = '<span class="edgeLabel">'+edge.text+'</span>';
 | 
			
		||||
                } else {
 | 
			
		||||
                    edgeData.labelType = 'text';
 | 
			
		||||
                    edgeData.style = 'stroke: #333; stroke-width: 1.5px;fill:none';
 | 
			
		||||
                    edgeData.label = edge.text.replace(/<br>/g, '\n');
 | 
			
		||||
                }
 | 
			
		||||
             } else {
 | 
			
		||||
                edgeData.label = edge.text.replace(/<br>/g, '\n');
 | 
			
		||||
            }
 | 
			
		||||
          edgeData.labelType = 'text'
 | 
			
		||||
          edgeData.style = 'stroke: #333; stroke-width: 1.5px;fill:none'
 | 
			
		||||
          edgeData.label = edge.text.replace(/<br>/g, '\n')
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        edgeData.label = edge.text.replace(/<br>/g, '\n')
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
        // Add the edge to the graph
 | 
			
		||||
        g.setEdge(edge.start, edge.end, edgeData, cnt);
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
    g.setEdge(edge.start, edge.end, edgeData, cnt)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns the all the styles from classDef statements in the graph definition.
 | 
			
		||||
 * @returns {object} classDef styles
 | 
			
		||||
 */
 | 
			
		||||
exports.getClasses = function (text, isDot) {
 | 
			
		||||
    var parser;
 | 
			
		||||
    graph.clear();
 | 
			
		||||
    if(isDot){
 | 
			
		||||
        parser = dot.parser;
 | 
			
		||||
 | 
			
		||||
    }else{
 | 
			
		||||
        parser = flow.parser;
 | 
			
		||||
    }
 | 
			
		||||
    parser.yy = graph;
 | 
			
		||||
  var parser
 | 
			
		||||
  graph.clear()
 | 
			
		||||
  if (isDot) {
 | 
			
		||||
    parser = dot.parser
 | 
			
		||||
  } else {
 | 
			
		||||
    parser = flow.parser
 | 
			
		||||
  }
 | 
			
		||||
  parser.yy = graph
 | 
			
		||||
 | 
			
		||||
    // Parse the graph definition
 | 
			
		||||
    parser.parse(text);
 | 
			
		||||
  parser.parse(text)
 | 
			
		||||
 | 
			
		||||
    var classes = graph.getClasses();
 | 
			
		||||
  var classes = graph.getClasses()
 | 
			
		||||
 | 
			
		||||
    // Add default class if undefined
 | 
			
		||||
    if(typeof(classes.default) === 'undefined') {
 | 
			
		||||
        classes.default = {id:'default'};
 | 
			
		||||
        //classes.default.styles = ['fill:#ffa','stroke:#666','stroke-width:3px'];
 | 
			
		||||
        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.nodeLabelStyles = ['fill:#000','stroke:none','font-weight:300','font-family:"Helvetica Neue",Helvetica,Arial,sans-serf','font-size:14px'];
 | 
			
		||||
        classes.default.edgeLabelStyles = ['fill:#000','stroke:none','font-weight:300','font-family:"Helvetica Neue",Helvetica,Arial,sans-serf','font-size:14px'];
 | 
			
		||||
    }
 | 
			
		||||
    return classes;
 | 
			
		||||
};
 | 
			
		||||
  if (typeof (classes.default) === 'undefined') {
 | 
			
		||||
    classes.default = {id: 'default'}
 | 
			
		||||
        // classes.default.styles = ['fill:#ffa','stroke:#666','stroke-width:3px'];
 | 
			
		||||
    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.nodeLabelStyles = ['fill:#000', 'stroke:none', 'font-weight:300', 'font-family:"Helvetica Neue",Helvetica,Arial,sans-serf', 'font-size:14px']
 | 
			
		||||
    classes.default.edgeLabelStyles = ['fill:#000', 'stroke:none', 'font-weight:300', 'font-family:"Helvetica Neue",Helvetica,Arial,sans-serf', 'font-size:14px']
 | 
			
		||||
  }
 | 
			
		||||
  return classes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Draws a flowchart in the tag with id: id based on the graph definition in text.
 | 
			
		||||
 * @param text
 | 
			
		||||
 * @param id
 | 
			
		||||
 */
 | 
			
		||||
exports.draw = function (text, id,isDot) {
 | 
			
		||||
    log.debug('Drawing flowchart');
 | 
			
		||||
    var parser;
 | 
			
		||||
    graph.clear();
 | 
			
		||||
    if(isDot){
 | 
			
		||||
        parser = dot.parser;
 | 
			
		||||
 | 
			
		||||
    }else{
 | 
			
		||||
        parser = flow.parser;
 | 
			
		||||
    }
 | 
			
		||||
    parser.yy = graph;
 | 
			
		||||
exports.draw = function (text, id, isDot) {
 | 
			
		||||
  log.debug('Drawing flowchart')
 | 
			
		||||
  var parser
 | 
			
		||||
  graph.clear()
 | 
			
		||||
  if (isDot) {
 | 
			
		||||
    parser = dot.parser
 | 
			
		||||
  } else {
 | 
			
		||||
    parser = flow.parser
 | 
			
		||||
  }
 | 
			
		||||
  parser.yy = graph
 | 
			
		||||
 | 
			
		||||
    // Parse the graph definition
 | 
			
		||||
    try{
 | 
			
		||||
 | 
			
		||||
        parser.parse(text);
 | 
			
		||||
    }
 | 
			
		||||
    catch(err){
 | 
			
		||||
        log.debug('Parsing failed');
 | 
			
		||||
    }
 | 
			
		||||
  try {
 | 
			
		||||
    parser.parse(text)
 | 
			
		||||
  } catch (err) {
 | 
			
		||||
    log.debug('Parsing failed')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    // Fetch the default direction, use TD if none was found
 | 
			
		||||
    var dir;
 | 
			
		||||
    dir = graph.getDirection();
 | 
			
		||||
    if(typeof dir === 'undefined'){
 | 
			
		||||
        dir='TD';
 | 
			
		||||
    }
 | 
			
		||||
  var dir
 | 
			
		||||
  dir = graph.getDirection()
 | 
			
		||||
  if (typeof dir === 'undefined') {
 | 
			
		||||
    dir = 'TD'
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    // Create the input mermaid.graph
 | 
			
		||||
    var g = new dagreD3.graphlib.Graph({
 | 
			
		||||
        multigraph:true,
 | 
			
		||||
        compound: true
 | 
			
		||||
    })
 | 
			
		||||
  var g = new dagreD3.graphlib.Graph({
 | 
			
		||||
    multigraph: true,
 | 
			
		||||
    compound: true
 | 
			
		||||
  })
 | 
			
		||||
        .setGraph({
 | 
			
		||||
            rankdir: dir,
 | 
			
		||||
            marginx: 20,
 | 
			
		||||
            marginy: 20
 | 
			
		||||
          rankdir: dir,
 | 
			
		||||
          marginx: 20,
 | 
			
		||||
          marginy: 20
 | 
			
		||||
 | 
			
		||||
        })
 | 
			
		||||
        .setDefaultEdgeLabel(function () {
 | 
			
		||||
            return {};
 | 
			
		||||
        });
 | 
			
		||||
          return {}
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
    var subG;
 | 
			
		||||
    var subGraphs = graph.getSubGraphs();
 | 
			
		||||
    var i = 0;
 | 
			
		||||
    for(i=subGraphs.length-1;i>=0;i--){
 | 
			
		||||
        subG = subGraphs[i];
 | 
			
		||||
        graph.addVertex(subG.id,subG.title,'group',undefined);
 | 
			
		||||
    }
 | 
			
		||||
  var subG
 | 
			
		||||
  var subGraphs = graph.getSubGraphs()
 | 
			
		||||
  var i = 0
 | 
			
		||||
  for (i = subGraphs.length - 1; i >= 0; i--) {
 | 
			
		||||
    subG = subGraphs[i]
 | 
			
		||||
    graph.addVertex(subG.id, subG.title, 'group', undefined)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    // 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();
 | 
			
		||||
    // log.debug(vert);
 | 
			
		||||
  var edges = graph.getEdges()
 | 
			
		||||
 | 
			
		||||
    i = 0;
 | 
			
		||||
    var j;
 | 
			
		||||
    for(i=subGraphs.length-1;i>=0;i--){
 | 
			
		||||
        subG = subGraphs[i];
 | 
			
		||||
  i = 0
 | 
			
		||||
  var j
 | 
			
		||||
  for (i = subGraphs.length - 1; i >= 0; i--) {
 | 
			
		||||
    subG = subGraphs[i]
 | 
			
		||||
 | 
			
		||||
        d3.selectAll('cluster').append('text');
 | 
			
		||||
    d3.selectAll('cluster').append('text')
 | 
			
		||||
 | 
			
		||||
        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);
 | 
			
		||||
        }
 | 
			
		||||
    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)
 | 
			
		||||
    }
 | 
			
		||||
    exports.addVertices(vert, g);
 | 
			
		||||
    exports.addEdges(edges, g);
 | 
			
		||||
  }
 | 
			
		||||
  exports.addVertices(vert, g)
 | 
			
		||||
  exports.addEdges(edges, g)
 | 
			
		||||
 | 
			
		||||
    // Create the renderer
 | 
			
		||||
    var render = new dagreD3.render();
 | 
			
		||||
  var render = new dagreD3.render()
 | 
			
		||||
 | 
			
		||||
    // Add custom shape for rhombus type of boc (decision)
 | 
			
		||||
    render.shapes().question = function (parent, bbox, node) {
 | 
			
		||||
        var w = bbox.width,
 | 
			
		||||
            h = bbox.height,
 | 
			
		||||
            s = (w + h) * 0.8,
 | 
			
		||||
            points = [
 | 
			
		||||
  render.shapes().question = function (parent, bbox, node) {
 | 
			
		||||
    var w = bbox.width,
 | 
			
		||||
      h = bbox.height,
 | 
			
		||||
      s = (w + h) * 0.8,
 | 
			
		||||
      points = [
 | 
			
		||||
                {x: s / 2, y: 0},
 | 
			
		||||
                {x: s, y: -s / 2},
 | 
			
		||||
                {x: s / 2, y: -s},
 | 
			
		||||
                {x: 0, y: -s / 2}
 | 
			
		||||
            ];
 | 
			
		||||
        var shapeSvg = parent.insert('polygon', ':first-child')
 | 
			
		||||
      ]
 | 
			
		||||
    var shapeSvg = parent.insert('polygon', ':first-child')
 | 
			
		||||
            .attr('points', points.map(function (d) {
 | 
			
		||||
                return d.x + ',' + d.y;
 | 
			
		||||
              return d.x + ',' + d.y
 | 
			
		||||
            }).join(' '))
 | 
			
		||||
            .attr('rx', 5)
 | 
			
		||||
            .attr('ry', 5)
 | 
			
		||||
            .attr('transform', 'translate(' + (-s / 2) + ',' + (s * 2 / 4) + ')');
 | 
			
		||||
        node.intersect = function (point) {
 | 
			
		||||
            return dagreD3.intersect.polygon(node, points, point);
 | 
			
		||||
        };
 | 
			
		||||
        return shapeSvg;
 | 
			
		||||
    };
 | 
			
		||||
            .attr('transform', 'translate(' + (-s / 2) + ',' + (s * 2 / 4) + ')')
 | 
			
		||||
    node.intersect = function (point) {
 | 
			
		||||
      return dagreD3.intersect.polygon(node, points, point)
 | 
			
		||||
    }
 | 
			
		||||
    return shapeSvg
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    // Add custom shape for box with inverted arrow on left side
 | 
			
		||||
    render.shapes().rect_left_inv_arrow = function (parent, bbox, node) {
 | 
			
		||||
        var w = bbox.width,
 | 
			
		||||
            h = bbox.height,
 | 
			
		||||
            points = [
 | 
			
		||||
                {x: -h/2, y: 0},
 | 
			
		||||
  render.shapes().rect_left_inv_arrow = function (parent, bbox, node) {
 | 
			
		||||
    var w = bbox.width,
 | 
			
		||||
      h = bbox.height,
 | 
			
		||||
      points = [
 | 
			
		||||
                {x: -h / 2, y: 0},
 | 
			
		||||
                {x: w, y: 0},
 | 
			
		||||
                {x: w, y: -h},
 | 
			
		||||
                {x: -h/2, y: -h},
 | 
			
		||||
                {x: 0, y: -h/2}
 | 
			
		||||
            ];
 | 
			
		||||
        var shapeSvg = parent.insert('polygon', ':first-child')
 | 
			
		||||
                {x: -h / 2, y: -h},
 | 
			
		||||
                {x: 0, y: -h / 2}
 | 
			
		||||
      ]
 | 
			
		||||
    var shapeSvg = parent.insert('polygon', ':first-child')
 | 
			
		||||
            .attr('points', points.map(function (d) {
 | 
			
		||||
                return d.x + ',' + d.y;
 | 
			
		||||
              return d.x + ',' + d.y
 | 
			
		||||
            }).join(' '))
 | 
			
		||||
            .attr('transform', 'translate(' + (-w / 2) + ',' + (h * 2 / 4) + ')');
 | 
			
		||||
        node.intersect = function (point) {
 | 
			
		||||
            return dagreD3.intersect.polygon(node, points, point);
 | 
			
		||||
        };
 | 
			
		||||
        return shapeSvg;
 | 
			
		||||
    };
 | 
			
		||||
            .attr('transform', 'translate(' + (-w / 2) + ',' + (h * 2 / 4) + ')')
 | 
			
		||||
    node.intersect = function (point) {
 | 
			
		||||
      return dagreD3.intersect.polygon(node, points, point)
 | 
			
		||||
    }
 | 
			
		||||
    return shapeSvg
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    // Add custom shape for box with inverted arrow on right side
 | 
			
		||||
    render.shapes().rect_right_inv_arrow = function (parent, bbox, node) {
 | 
			
		||||
        var w = bbox.width,
 | 
			
		||||
            h = bbox.height,
 | 
			
		||||
            points = [
 | 
			
		||||
  render.shapes().rect_right_inv_arrow = function (parent, bbox, node) {
 | 
			
		||||
    var w = bbox.width,
 | 
			
		||||
      h = bbox.height,
 | 
			
		||||
      points = [
 | 
			
		||||
                {x: 0, y: 0},
 | 
			
		||||
                {x: w+h/2, y: 0},
 | 
			
		||||
                {x: w, y: -h/2},
 | 
			
		||||
                {x: w+h/2, y: -h},
 | 
			
		||||
                {x: w + h / 2, y: 0},
 | 
			
		||||
                {x: w, y: -h / 2},
 | 
			
		||||
                {x: w + h / 2, y: -h},
 | 
			
		||||
                {x: 0, y: -h}
 | 
			
		||||
            ];
 | 
			
		||||
        var shapeSvg = parent.insert('polygon', ':first-child')
 | 
			
		||||
      ]
 | 
			
		||||
    var shapeSvg = parent.insert('polygon', ':first-child')
 | 
			
		||||
            .attr('points', points.map(function (d) {
 | 
			
		||||
                return d.x + ',' + d.y;
 | 
			
		||||
              return d.x + ',' + d.y
 | 
			
		||||
            }).join(' '))
 | 
			
		||||
            .attr('transform', 'translate(' + (-w / 2) + ',' + (h * 2 / 4) + ')');
 | 
			
		||||
        node.intersect = function (point) {
 | 
			
		||||
            return dagreD3.intersect.polygon(node, points, point);
 | 
			
		||||
        };
 | 
			
		||||
        return shapeSvg;
 | 
			
		||||
    };
 | 
			
		||||
            .attr('transform', 'translate(' + (-w / 2) + ',' + (h * 2 / 4) + ')')
 | 
			
		||||
    node.intersect = function (point) {
 | 
			
		||||
      return dagreD3.intersect.polygon(node, points, point)
 | 
			
		||||
    }
 | 
			
		||||
    return shapeSvg
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    // Add our custom arrow - an empty arrowhead
 | 
			
		||||
    render.arrows().none = function normal(parent, id, edge, type) {
 | 
			
		||||
        var marker = parent.append('marker')
 | 
			
		||||
  render.arrows().none = function normal (parent, id, edge, type) {
 | 
			
		||||
    var marker = parent.append('marker')
 | 
			
		||||
            .attr('id', id)
 | 
			
		||||
            .attr('viewBox', '0 0 10 10')
 | 
			
		||||
            .attr('refX', 9)
 | 
			
		||||
@@ -419,45 +406,45 @@ exports.draw = function (text, id,isDot) {
 | 
			
		||||
            .attr('markerUnits', 'strokeWidth')
 | 
			
		||||
            .attr('markerWidth', 8)
 | 
			
		||||
            .attr('markerHeight', 6)
 | 
			
		||||
            .attr('orient', 'auto');
 | 
			
		||||
            .attr('orient', 'auto')
 | 
			
		||||
 | 
			
		||||
        var path = marker.append('path')
 | 
			
		||||
            .attr('d', 'M 0 0 L 0 0 L 0 0 z');
 | 
			
		||||
        dagreD3.util.applyStyle(path, edge[type + 'Style']);
 | 
			
		||||
    };
 | 
			
		||||
    var path = marker.append('path')
 | 
			
		||||
            .attr('d', 'M 0 0 L 0 0 L 0 0 z')
 | 
			
		||||
    dagreD3.util.applyStyle(path, edge[type + 'Style'])
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    // Override normal arrowhead defined in d3. Remove style & add class to allow css styling.
 | 
			
		||||
    render.arrows().normal = function normal(parent, id, edge, type) {
 | 
			
		||||
        var marker = parent.append("marker")
 | 
			
		||||
        .attr("id", id)
 | 
			
		||||
        .attr("viewBox", "0 0 10 10")
 | 
			
		||||
        .attr("refX", 9)
 | 
			
		||||
        .attr("refY", 5)
 | 
			
		||||
        .attr("markerUnits", "strokeWidth")
 | 
			
		||||
        .attr("markerWidth", 8)
 | 
			
		||||
        .attr("markerHeight", 6)
 | 
			
		||||
        .attr("orient", "auto")
 | 
			
		||||
  render.arrows().normal = function normal (parent, id, edge, type) {
 | 
			
		||||
    var marker = parent.append('marker')
 | 
			
		||||
        .attr('id', id)
 | 
			
		||||
        .attr('viewBox', '0 0 10 10')
 | 
			
		||||
        .attr('refX', 9)
 | 
			
		||||
        .attr('refY', 5)
 | 
			
		||||
        .attr('markerUnits', 'strokeWidth')
 | 
			
		||||
        .attr('markerWidth', 8)
 | 
			
		||||
        .attr('markerHeight', 6)
 | 
			
		||||
        .attr('orient', 'auto')
 | 
			
		||||
 | 
			
		||||
        var path = marker.append("path")
 | 
			
		||||
        .attr("d", "M 0 0 L 10 5 L 0 10 z")
 | 
			
		||||
        .attr("class", "arrowheadPath")
 | 
			
		||||
        .style("stroke-width", 1)
 | 
			
		||||
        .style("stroke-dasharray", "1,0");
 | 
			
		||||
    };
 | 
			
		||||
    var path = marker.append('path')
 | 
			
		||||
        .attr('d', 'M 0 0 L 10 5 L 0 10 z')
 | 
			
		||||
        .attr('class', 'arrowheadPath')
 | 
			
		||||
        .style('stroke-width', 1)
 | 
			
		||||
        .style('stroke-dasharray', '1,0')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    // Set up an SVG group so that we can translate the final graph.
 | 
			
		||||
    var svg = d3.select('#' + id);
 | 
			
		||||
    //svgGroup = d3.select('#' + id + ' g');
 | 
			
		||||
  var svg = d3.select('#' + id)
 | 
			
		||||
    // svgGroup = d3.select('#' + id + ' g');
 | 
			
		||||
 | 
			
		||||
    // Run the renderer. This is what draws the final graph.
 | 
			
		||||
    var element = d3.select('#' + id + ' g');
 | 
			
		||||
    render(element, g);
 | 
			
		||||
  var element = d3.select('#' + id + ' g')
 | 
			
		||||
  render(element, g)
 | 
			
		||||
 | 
			
		||||
    //var tip = d3.tip().html(function(d) { return d; });
 | 
			
		||||
    element.selectAll('g.node')
 | 
			
		||||
                .attr('title', function(){
 | 
			
		||||
            return graph.getTooltip(this.id);
 | 
			
		||||
        });
 | 
			
		||||
    // var tip = d3.tip().html(function(d) { return d; });
 | 
			
		||||
  element.selectAll('g.node')
 | 
			
		||||
                .attr('title', function () {
 | 
			
		||||
                  return graph.getTooltip(this.id)
 | 
			
		||||
                })
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 var xPos = document.querySelectorAll('.clusters rect')[0].x.baseVal.value;
 | 
			
		||||
@@ -471,79 +458,75 @@ exports.draw = function (text, id,isDot) {
 | 
			
		||||
    te.style('text-anchor', 'middle');
 | 
			
		||||
    te.text('Title for cluster');
 | 
			
		||||
*/
 | 
			
		||||
    if(conf.useMaxWidth) {
 | 
			
		||||
  if (conf.useMaxWidth) {
 | 
			
		||||
        // Center the graph
 | 
			
		||||
        svg.attr('height', '100%');
 | 
			
		||||
        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('style', 'max-width:' + (g.graph().width + 20) + 'px;');
 | 
			
		||||
    svg.attr('height', '100%')
 | 
			
		||||
    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('style', 'max-width:' + (g.graph().width + 20) + 'px;')
 | 
			
		||||
  } else {
 | 
			
		||||
        // Center the graph
 | 
			
		||||
    svg.attr('height', g.graph().height)
 | 
			
		||||
    if (typeof conf.width === 'undefined') {
 | 
			
		||||
      svg.attr('width', g.graph().width)
 | 
			
		||||
    } else {
 | 
			
		||||
      svg.attr('width', conf.width)
 | 
			
		||||
    }
 | 
			
		||||
    else{
 | 
			
		||||
        // Center the graph
 | 
			
		||||
        svg.attr('height', g.graph().height );
 | 
			
		||||
        if(typeof conf.width === 'undefined'){
 | 
			
		||||
            svg.attr('width', g.graph().width );
 | 
			
		||||
        }else{
 | 
			
		||||
            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', svgb.getBBox().x + ' 0 '+ g.graph().width+' '+ g.graph().height);
 | 
			
		||||
    svg.attr('viewBox', '0 0 ' + (g.graph().width + 20) + ' ' + (g.graph().height + 20))
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    // Index nodes
 | 
			
		||||
    graph.indexNodes('subGraph'+i);
 | 
			
		||||
    
 | 
			
		||||
    for(i=0;i<subGraphs.length;i++){
 | 
			
		||||
        subG = subGraphs[i];
 | 
			
		||||
  graph.indexNodes('subGraph' + i)
 | 
			
		||||
 | 
			
		||||
        if (subG.title !== 'undefined') {
 | 
			
		||||
            var clusterRects = document.querySelectorAll('#' + id + ' #' + subG.id + ' rect');
 | 
			
		||||
            //log.debug('looking up: #' + id + ' #' + subG.id)
 | 
			
		||||
            var clusterEl = document.querySelectorAll('#' + id + ' #' + subG.id);
 | 
			
		||||
  for (i = 0; i < subGraphs.length; i++) {
 | 
			
		||||
    subG = subGraphs[i]
 | 
			
		||||
 | 
			
		||||
            var xPos = clusterRects[0].x.baseVal.value;
 | 
			
		||||
            var yPos = clusterRects[0].y.baseVal.value;
 | 
			
		||||
            var width = clusterRects[0].width.baseVal.value;
 | 
			
		||||
            var cluster = d3.select(clusterEl[0]);
 | 
			
		||||
            var te = cluster.append('text');
 | 
			
		||||
            te.attr('x', xPos + width / 2);
 | 
			
		||||
            te.attr('y', yPos + 14);
 | 
			
		||||
            te.attr('fill', 'black');
 | 
			
		||||
            te.attr('stroke', 'none');
 | 
			
		||||
            te.attr('id', id + 'Text');
 | 
			
		||||
            te.style('text-anchor', 'middle');
 | 
			
		||||
    if (subG.title !== 'undefined') {
 | 
			
		||||
      var clusterRects = document.querySelectorAll('#' + id + ' #' + subG.id + ' rect')
 | 
			
		||||
            // log.debug('looking up: #' + id + ' #' + subG.id)
 | 
			
		||||
      var clusterEl = document.querySelectorAll('#' + id + ' #' + subG.id)
 | 
			
		||||
 | 
			
		||||
            if(typeof subG.title === 'undefined'){
 | 
			
		||||
                te.text('Undef');
 | 
			
		||||
            }else{
 | 
			
		||||
                //te.text(subGraphs[subGraphs.length-i-1].title);
 | 
			
		||||
                te.text(subG.title);
 | 
			
		||||
      var xPos = clusterRects[0].x.baseVal.value
 | 
			
		||||
      var yPos = clusterRects[0].y.baseVal.value
 | 
			
		||||
      var width = clusterRects[0].width.baseVal.value
 | 
			
		||||
      var cluster = d3.select(clusterEl[0])
 | 
			
		||||
      var te = cluster.append('text')
 | 
			
		||||
      te.attr('x', xPos + width / 2)
 | 
			
		||||
      te.attr('y', yPos + 14)
 | 
			
		||||
      te.attr('fill', 'black')
 | 
			
		||||
      te.attr('stroke', 'none')
 | 
			
		||||
      te.attr('id', id + 'Text')
 | 
			
		||||
      te.style('text-anchor', 'middle')
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
      if (typeof subG.title === 'undefined') {
 | 
			
		||||
        te.text('Undef')
 | 
			
		||||
      } else {
 | 
			
		||||
                // te.text(subGraphs[subGraphs.length-i-1].title);
 | 
			
		||||
        te.text(subG.title)
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    // Add label rects for non html labels
 | 
			
		||||
    if(!conf.htmlLabels){
 | 
			
		||||
        var labels = document.querySelectorAll('#' + id +' .edgeLabel .label');
 | 
			
		||||
        var i;
 | 
			
		||||
        for(i=0;i<labels.length;i++){
 | 
			
		||||
            var label = labels[i];
 | 
			
		||||
  if (!conf.htmlLabels) {
 | 
			
		||||
    var labels = document.querySelectorAll('#' + id + ' .edgeLabel .label')
 | 
			
		||||
    var i
 | 
			
		||||
    for (i = 0; i < labels.length; i++) {
 | 
			
		||||
      var label = labels[i]
 | 
			
		||||
 | 
			
		||||
            // Get dimensions of label
 | 
			
		||||
            var dim = label.getBBox();
 | 
			
		||||
      var dim = label.getBBox()
 | 
			
		||||
 | 
			
		||||
            var rect =  document.createElementNS('http://www.w3.org/2000/svg', 'rect');
 | 
			
		||||
            rect.setAttribute('rx',0);
 | 
			
		||||
            rect.setAttribute('ry',0);
 | 
			
		||||
            rect.setAttribute('width',dim.width);
 | 
			
		||||
            rect.setAttribute('height',dim.height);
 | 
			
		||||
            rect.setAttribute('style','fill:#e8e8e8;');
 | 
			
		||||
      var rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
 | 
			
		||||
      rect.setAttribute('rx', 0)
 | 
			
		||||
      rect.setAttribute('ry', 0)
 | 
			
		||||
      rect.setAttribute('width', dim.width)
 | 
			
		||||
      rect.setAttribute('height', dim.height)
 | 
			
		||||
      rect.setAttribute('style', 'fill:#e8e8e8;')
 | 
			
		||||
 | 
			
		||||
            label.insertBefore(rect, label.firstChild);
 | 
			
		||||
        }
 | 
			
		||||
      label.insertBefore(rect, label.firstChild)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,20 +1,20 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Created by knut on 14-11-03.
 | 
			
		||||
 */
 | 
			
		||||
var Logger = require('../../logger');
 | 
			
		||||
var log = Logger.Log;
 | 
			
		||||
var utils = require('../../utils');
 | 
			
		||||
var Logger = require('../../logger')
 | 
			
		||||
var log = Logger.Log
 | 
			
		||||
var utils = require('../../utils')
 | 
			
		||||
 | 
			
		||||
var d3 = require('../../d3');
 | 
			
		||||
var vertices = {};
 | 
			
		||||
var edges = [];
 | 
			
		||||
var classes = [];
 | 
			
		||||
var subGraphs = [];
 | 
			
		||||
var tooltips = {};
 | 
			
		||||
var subCount=0;
 | 
			
		||||
var direction;
 | 
			
		||||
var d3 = require('../../d3')
 | 
			
		||||
var vertices = {}
 | 
			
		||||
var edges = []
 | 
			
		||||
var classes = []
 | 
			
		||||
var subGraphs = []
 | 
			
		||||
var tooltips = {}
 | 
			
		||||
var subCount = 0
 | 
			
		||||
var direction
 | 
			
		||||
// Functions to be run after graph rendering
 | 
			
		||||
var funs = [];
 | 
			
		||||
var funs = []
 | 
			
		||||
/**
 | 
			
		||||
 * Function called by parser when a node definition has been found
 | 
			
		||||
 * @param id
 | 
			
		||||
@@ -23,42 +23,42 @@ var funs = [];
 | 
			
		||||
 * @param style
 | 
			
		||||
 */
 | 
			
		||||
exports.addVertex = function (id, text, type, style) {
 | 
			
		||||
    var txt;
 | 
			
		||||
    
 | 
			
		||||
    if(typeof id === 'undefined'){
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if(id.trim().length === 0){
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
  var txt
 | 
			
		||||
 | 
			
		||||
  if (typeof id === 'undefined') {
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
  if (id.trim().length === 0) {
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (typeof vertices[id] === 'undefined') {
 | 
			
		||||
    vertices[id] = {id: id, styles: [], classes: []}
 | 
			
		||||
  }
 | 
			
		||||
  if (typeof text !== 'undefined') {
 | 
			
		||||
    txt = text.trim()
 | 
			
		||||
 | 
			
		||||
    if (typeof vertices[id] === 'undefined') {
 | 
			
		||||
        vertices[id] = {id: id, styles: [], classes:[]};
 | 
			
		||||
    }
 | 
			
		||||
    if (typeof text !== 'undefined') {
 | 
			
		||||
        txt = text.trim();
 | 
			
		||||
        
 | 
			
		||||
        // strip quotes if string starts and exnds with a quote
 | 
			
		||||
        if(txt[0] === '"' && txt[txt.length-1] === '"'){
 | 
			
		||||
            txt = txt.substring(1,txt.length-1);
 | 
			
		||||
        }
 | 
			
		||||
    if (txt[0] === '"' && txt[txt.length - 1] === '"') {
 | 
			
		||||
      txt = txt.substring(1, txt.length - 1)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        vertices[id].text = txt;
 | 
			
		||||
    vertices[id].text = txt
 | 
			
		||||
  }
 | 
			
		||||
  if (typeof type !== 'undefined') {
 | 
			
		||||
    vertices[id].type = type
 | 
			
		||||
  }
 | 
			
		||||
  if (typeof type !== 'undefined') {
 | 
			
		||||
    vertices[id].type = type
 | 
			
		||||
  }
 | 
			
		||||
  if (typeof style !== 'undefined') {
 | 
			
		||||
    if (style !== null) {
 | 
			
		||||
      style.forEach(function (s) {
 | 
			
		||||
        vertices[id].styles.push(s)
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
    if (typeof type !== 'undefined') {
 | 
			
		||||
        vertices[id].type = type;
 | 
			
		||||
    }
 | 
			
		||||
    if (typeof type !== 'undefined') {
 | 
			
		||||
        vertices[id].type = type;
 | 
			
		||||
    }
 | 
			
		||||
    if (typeof style !== 'undefined') {
 | 
			
		||||
        if (style !== null) {
 | 
			
		||||
            style.forEach(function (s) {
 | 
			
		||||
                vertices[id].styles.push(s);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Function called by parser when a link/edge definition has been found
 | 
			
		||||
@@ -68,25 +68,25 @@ exports.addVertex = function (id, text, type, style) {
 | 
			
		||||
 * @param linktext
 | 
			
		||||
 */
 | 
			
		||||
exports.addLink = function (start, end, type, linktext) {
 | 
			
		||||
    log.info('Got edge...', start, end);
 | 
			
		||||
    var edge = {start: start, end: end, type: undefined, text: ''};
 | 
			
		||||
    linktext = type.text;
 | 
			
		||||
  log.info('Got edge...', start, end)
 | 
			
		||||
  var edge = {start: start, end: end, type: undefined, text: ''}
 | 
			
		||||
  linktext = type.text
 | 
			
		||||
 | 
			
		||||
  if (typeof linktext !== 'undefined') {
 | 
			
		||||
    edge.text = linktext.trim()
 | 
			
		||||
 | 
			
		||||
    if (typeof linktext !== 'undefined') {
 | 
			
		||||
        edge.text = linktext.trim();
 | 
			
		||||
        
 | 
			
		||||
        // strip quotes if string starts and exnds with a quote
 | 
			
		||||
        if(edge.text[0] === '"' && edge.text[edge.text.length-1] === '"'){
 | 
			
		||||
            edge.text = edge.text.substring(1,edge.text.length-1);
 | 
			
		||||
        }
 | 
			
		||||
    if (edge.text[0] === '"' && edge.text[edge.text.length - 1] === '"') {
 | 
			
		||||
      edge.text = edge.text.substring(1, edge.text.length - 1)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    if (typeof type !== 'undefined') {
 | 
			
		||||
        edge.type = type.type;
 | 
			
		||||
        edge.stroke = type.stroke;
 | 
			
		||||
    }
 | 
			
		||||
    edges.push(edge);
 | 
			
		||||
};
 | 
			
		||||
  if (typeof type !== 'undefined') {
 | 
			
		||||
    edge.type = type.type
 | 
			
		||||
    edge.stroke = type.stroke
 | 
			
		||||
  }
 | 
			
		||||
  edges.push(edge)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Updates a link's line interpolation algorithm
 | 
			
		||||
@@ -94,12 +94,12 @@ exports.addLink = function (start, end, type, linktext) {
 | 
			
		||||
 * @param interpolate
 | 
			
		||||
 */
 | 
			
		||||
exports.updateLinkInterpolate = function (pos, interp) {
 | 
			
		||||
    if(pos === 'default'){
 | 
			
		||||
        edges.defaultInterpolate = interp;
 | 
			
		||||
    }else{
 | 
			
		||||
        edges[pos].interpolate = interp;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
  if (pos === 'default') {
 | 
			
		||||
    edges.defaultInterpolate = interp
 | 
			
		||||
  } else {
 | 
			
		||||
    edges[pos].interpolate = interp
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Updates a link with a style
 | 
			
		||||
@@ -107,315 +107,304 @@ exports.updateLinkInterpolate = function (pos, interp) {
 | 
			
		||||
 * @param style
 | 
			
		||||
 */
 | 
			
		||||
exports.updateLink = function (pos, style) {
 | 
			
		||||
    if(pos === 'default'){
 | 
			
		||||
        edges.defaultStyle = style;
 | 
			
		||||
    }else{
 | 
			
		||||
        if(utils.isSubstringInArray('fill', style) === -1) {
 | 
			
		||||
            style.push('fill:none');
 | 
			
		||||
        }
 | 
			
		||||
        edges[pos].style = style;
 | 
			
		||||
  if (pos === 'default') {
 | 
			
		||||
    edges.defaultStyle = style
 | 
			
		||||
  } else {
 | 
			
		||||
    if (utils.isSubstringInArray('fill', style) === -1) {
 | 
			
		||||
      style.push('fill:none')
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
    edges[pos].style = style
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.addClass = function (id, style) {
 | 
			
		||||
    if (typeof classes[id] === 'undefined') {
 | 
			
		||||
        classes[id] = {id: id, styles: []};
 | 
			
		||||
    }
 | 
			
		||||
  if (typeof classes[id] === 'undefined') {
 | 
			
		||||
    classes[id] = {id: id, styles: []}
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    if (typeof style !== 'undefined') {
 | 
			
		||||
        if (style !== null) {
 | 
			
		||||
            style.forEach(function (s) {
 | 
			
		||||
                classes[id].styles.push(s);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
  if (typeof style !== 'undefined') {
 | 
			
		||||
    if (style !== null) {
 | 
			
		||||
      style.forEach(function (s) {
 | 
			
		||||
        classes[id].styles.push(s)
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Called by parser when a graph definition is found, stores the direction of the chart.
 | 
			
		||||
 * @param dir
 | 
			
		||||
 */
 | 
			
		||||
exports.setDirection = function (dir) {
 | 
			
		||||
    direction = dir;
 | 
			
		||||
};
 | 
			
		||||
  direction = dir
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Called by parser when a graph definition is found, stores the direction of the chart.
 | 
			
		||||
 * @param dir
 | 
			
		||||
 */
 | 
			
		||||
exports.setClass = function (id,className) {
 | 
			
		||||
    if(id.indexOf(',')>0){
 | 
			
		||||
        id.split(',').forEach(function(id2){
 | 
			
		||||
            if(typeof vertices[id2] !== 'undefined'){
 | 
			
		||||
                vertices[id2].classes.push(className);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }else{
 | 
			
		||||
        if(typeof vertices[id] !== 'undefined'){
 | 
			
		||||
            vertices[id].classes.push(className);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var setTooltip = function(id,tooltip){
 | 
			
		||||
    if(typeof  tooltip !== 'undefined'){
 | 
			
		||||
        tooltips[id]=tooltip;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var setClickFun = function(id, functionName){
 | 
			
		||||
    if(typeof functionName === 'undefined'){
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
exports.setClass = function (id, className) {
 | 
			
		||||
  if (id.indexOf(',') > 0) {
 | 
			
		||||
    id.split(',').forEach(function (id2) {
 | 
			
		||||
      if (typeof vertices[id2] !== 'undefined') {
 | 
			
		||||
        vertices[id2].classes.push(className)
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
  } else {
 | 
			
		||||
    if (typeof vertices[id] !== 'undefined') {
 | 
			
		||||
        funs.push(function (element) {
 | 
			
		||||
            var elem = d3.select(element).select('#'+id);
 | 
			
		||||
            if (elem !== null) {
 | 
			
		||||
                elem.on('click', function () {
 | 
			
		||||
                    eval(functionName + '(\'' + id + '\')'); // jshint ignore:line
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
      vertices[id].classes.push(className)
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var setLink = function(id, linkStr){
 | 
			
		||||
    if(typeof linkStr === 'undefined'){
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (typeof vertices[id] !== 'undefined') {
 | 
			
		||||
        funs.push(function (element) {
 | 
			
		||||
            var elem = d3.select(element).select('#'+id);
 | 
			
		||||
            if (elem !== null) {
 | 
			
		||||
                elem.on('click', function () {
 | 
			
		||||
                    window.open(linkStr,'newTab'); // jshint ignore:line
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
exports.getTooltip = function(id){
 | 
			
		||||
    return tooltips[id];
 | 
			
		||||
};
 | 
			
		||||
var setTooltip = function (id, tooltip) {
 | 
			
		||||
  if (typeof tooltip !== 'undefined') {
 | 
			
		||||
    tooltips[id] = tooltip
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var setClickFun = function (id, functionName) {
 | 
			
		||||
  if (typeof functionName === 'undefined') {
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
  if (typeof vertices[id] !== 'undefined') {
 | 
			
		||||
    funs.push(function (element) {
 | 
			
		||||
      var elem = d3.select(element).select('#' + id)
 | 
			
		||||
      if (elem !== null) {
 | 
			
		||||
        elem.on('click', function () {
 | 
			
		||||
          eval(functionName + '(\'' + id + '\')') // jshint ignore:line
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var setLink = function (id, linkStr) {
 | 
			
		||||
  if (typeof linkStr === 'undefined') {
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
  if (typeof vertices[id] !== 'undefined') {
 | 
			
		||||
    funs.push(function (element) {
 | 
			
		||||
      var elem = d3.select(element).select('#' + id)
 | 
			
		||||
      if (elem !== null) {
 | 
			
		||||
        elem.on('click', function () {
 | 
			
		||||
          window.open(linkStr, 'newTab') // jshint ignore:line
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
exports.getTooltip = function (id) {
 | 
			
		||||
  return tooltips[id]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Called by parser when a graph definition is found, stores the direction of the chart.
 | 
			
		||||
 * @param dir
 | 
			
		||||
 */
 | 
			
		||||
exports.setClickEvent = function (id,functionName, link,tooltip) {
 | 
			
		||||
        if(id.indexOf(',')>0){
 | 
			
		||||
            id.split(',').forEach(function(id2) {
 | 
			
		||||
                setTooltip(id2,tooltip);
 | 
			
		||||
                setClickFun(id2, functionName);
 | 
			
		||||
                setLink(id2, link);
 | 
			
		||||
            });
 | 
			
		||||
        }else{
 | 
			
		||||
            setTooltip(id,tooltip);
 | 
			
		||||
            setClickFun(id, functionName);
 | 
			
		||||
            setLink(id, link);
 | 
			
		||||
        }
 | 
			
		||||
};
 | 
			
		||||
exports.setClickEvent = function (id, functionName, link, tooltip) {
 | 
			
		||||
  if (id.indexOf(',') > 0) {
 | 
			
		||||
    id.split(',').forEach(function (id2) {
 | 
			
		||||
      setTooltip(id2, tooltip)
 | 
			
		||||
      setClickFun(id2, functionName)
 | 
			
		||||
      setLink(id2, link)
 | 
			
		||||
    })
 | 
			
		||||
  } else {
 | 
			
		||||
    setTooltip(id, tooltip)
 | 
			
		||||
    setClickFun(id, functionName)
 | 
			
		||||
    setLink(id, link)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.bindFunctions = function(element){
 | 
			
		||||
    funs.forEach(function(fun){
 | 
			
		||||
        fun(element);
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
exports.bindFunctions = function (element) {
 | 
			
		||||
  funs.forEach(function (fun) {
 | 
			
		||||
    fun(element)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
exports.getDirection = function () {
 | 
			
		||||
    return direction;
 | 
			
		||||
};
 | 
			
		||||
  return direction
 | 
			
		||||
}
 | 
			
		||||
/**
 | 
			
		||||
 * Retrieval function for fetching the found nodes after parsing has completed.
 | 
			
		||||
 * @returns {{}|*|vertices}
 | 
			
		||||
 */
 | 
			
		||||
exports.getVertices = function () {
 | 
			
		||||
    return vertices;
 | 
			
		||||
};
 | 
			
		||||
  return vertices
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Retrieval function for fetching the found links after parsing has completed.
 | 
			
		||||
 * @returns {{}|*|edges}
 | 
			
		||||
 */
 | 
			
		||||
exports.getEdges = function () {
 | 
			
		||||
    return edges;
 | 
			
		||||
};
 | 
			
		||||
  return edges
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Retrieval function for fetching the found class definitions after parsing has completed.
 | 
			
		||||
 * @returns {{}|*|classes}
 | 
			
		||||
 */
 | 
			
		||||
exports.getClasses = function () {
 | 
			
		||||
    return classes;
 | 
			
		||||
};
 | 
			
		||||
  return classes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var setupToolTips = function(element){
 | 
			
		||||
 | 
			
		||||
    var tooltipElem = d3.select('.mermaidTooltip');
 | 
			
		||||
    if(tooltipElem[0][0] === null){
 | 
			
		||||
        tooltipElem = d3.select('body')
 | 
			
		||||
var setupToolTips = function (element) {
 | 
			
		||||
  var tooltipElem = d3.select('.mermaidTooltip')
 | 
			
		||||
  if (tooltipElem[0][0] === null) {
 | 
			
		||||
    tooltipElem = d3.select('body')
 | 
			
		||||
            .append('div')
 | 
			
		||||
            .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');
 | 
			
		||||
    nodes
 | 
			
		||||
        .on('mouseover', function() {
 | 
			
		||||
            var el = d3.select(this);
 | 
			
		||||
            var title = el.attr('title');
 | 
			
		||||
  var nodes = svg.selectAll('g.node')
 | 
			
		||||
  nodes
 | 
			
		||||
        .on('mouseover', function () {
 | 
			
		||||
          var el = d3.select(this)
 | 
			
		||||
          var title = el.attr('title')
 | 
			
		||||
            // Dont try to draw a tooltip if no data is provided
 | 
			
		||||
            if(title === null){
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            var rect = this.getBoundingClientRect();
 | 
			
		||||
          if (title === null) {
 | 
			
		||||
            return
 | 
			
		||||
          }
 | 
			
		||||
          var rect = this.getBoundingClientRect()
 | 
			
		||||
 | 
			
		||||
            tooltipElem.transition()
 | 
			
		||||
          tooltipElem.transition()
 | 
			
		||||
                .duration(200)
 | 
			
		||||
                .style('opacity', '.9');
 | 
			
		||||
            tooltipElem.html(el.attr('title'))
 | 
			
		||||
                .style('left', (rect.left+(rect.right-rect.left)/2) + 'px')
 | 
			
		||||
                .style('top', (rect.top-14+document.body.scrollTop) + 'px');
 | 
			
		||||
            el.classed('hover',true);
 | 
			
		||||
 | 
			
		||||
                .style('opacity', '.9')
 | 
			
		||||
          tooltipElem.html(el.attr('title'))
 | 
			
		||||
                .style('left', (rect.left + (rect.right - rect.left) / 2) + 'px')
 | 
			
		||||
                .style('top', (rect.top - 14 + document.body.scrollTop) + 'px')
 | 
			
		||||
          el.classed('hover', true)
 | 
			
		||||
        })
 | 
			
		||||
        .on('mouseout', function() {
 | 
			
		||||
            tooltipElem.transition()
 | 
			
		||||
        .on('mouseout', function () {
 | 
			
		||||
          tooltipElem.transition()
 | 
			
		||||
                .duration(500)
 | 
			
		||||
                .style('opacity', 0);
 | 
			
		||||
            var el = d3.select(this);
 | 
			
		||||
            el.classed('hover',false);
 | 
			
		||||
        });
 | 
			
		||||
};
 | 
			
		||||
funs.push(setupToolTips);
 | 
			
		||||
                .style('opacity', 0)
 | 
			
		||||
          var el = d3.select(this)
 | 
			
		||||
          el.classed('hover', false)
 | 
			
		||||
        })
 | 
			
		||||
}
 | 
			
		||||
funs.push(setupToolTips)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Clears the internal graph db so that a new graph can be parsed.
 | 
			
		||||
 */
 | 
			
		||||
exports.clear = function () {
 | 
			
		||||
    vertices = {};
 | 
			
		||||
    classes = {};
 | 
			
		||||
    edges = [];
 | 
			
		||||
    funs = [];
 | 
			
		||||
    funs.push(setupToolTips);
 | 
			
		||||
    subGraphs = [];
 | 
			
		||||
    subCount = 0;
 | 
			
		||||
    tooltips = [];
 | 
			
		||||
};
 | 
			
		||||
  vertices = {}
 | 
			
		||||
  classes = {}
 | 
			
		||||
  edges = []
 | 
			
		||||
  funs = []
 | 
			
		||||
  funs.push(setupToolTips)
 | 
			
		||||
  subGraphs = []
 | 
			
		||||
  subCount = 0
 | 
			
		||||
  tooltips = []
 | 
			
		||||
}
 | 
			
		||||
/**
 | 
			
		||||
 *
 | 
			
		||||
 * @returns {string}
 | 
			
		||||
 */
 | 
			
		||||
exports.defaultStyle = function () {
 | 
			
		||||
    return 'fill:#ffa;stroke: #f66; stroke-width: 3px; stroke-dasharray: 5, 5;fill:#ffa;stroke: #666;';
 | 
			
		||||
};
 | 
			
		||||
  return 'fill:#ffa;stroke: #f66; stroke-width: 3px; stroke-dasharray: 5, 5;fill:#ffa;stroke: #666;'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Clears the internal graph db so that a new graph can be parsed.
 | 
			
		||||
 */
 | 
			
		||||
exports.addSubGraph = function (list, title) {
 | 
			
		||||
    function uniq(a) {
 | 
			
		||||
        var prims = {'boolean':{}, 'number':{}, 'string':{}}, objs = [];
 | 
			
		||||
  function uniq (a) {
 | 
			
		||||
    var prims = {'boolean': {}, 'number': {}, 'string': {}}, objs = []
 | 
			
		||||
 | 
			
		||||
        return a.filter(function(item) {
 | 
			
		||||
            var type = typeof item;
 | 
			
		||||
            if(item===' '){
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            if(type in prims)
 | 
			
		||||
                return prims[type].hasOwnProperty(item) ? false : (prims[type][item] = true);
 | 
			
		||||
            else
 | 
			
		||||
                return objs.indexOf(item) >= 0 ? false : objs.push(item);
 | 
			
		||||
        });
 | 
			
		||||
    return a.filter(function (item) {
 | 
			
		||||
      var type = typeof item
 | 
			
		||||
      if (item === ' ') {
 | 
			
		||||
        return false
 | 
			
		||||
      }
 | 
			
		||||
      if (type in prims) { return prims[type].hasOwnProperty(item) ? false : (prims[type][item] = true) } else { return objs.indexOf(item) >= 0 ? false : objs.push(item) }
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  var nodeList = []
 | 
			
		||||
 | 
			
		||||
  nodeList = uniq(nodeList.concat.apply(nodeList, list))
 | 
			
		||||
 | 
			
		||||
  var subGraph = {id: 'subGraph' + subCount, nodes: nodeList, title: title}
 | 
			
		||||
// log.debug('subGraph:' + subGraph.title + subGraph.id);
 | 
			
		||||
// log.debug(subGraph.nodes);
 | 
			
		||||
  subGraphs.push(subGraph)
 | 
			
		||||
  subCount = subCount + 1
 | 
			
		||||
  return subGraph.id
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var getPosForId = function (id) {
 | 
			
		||||
  var i
 | 
			
		||||
  for (i = 0; i < subGraphs.length; i++) {
 | 
			
		||||
    if (subGraphs[i].id === id) {
 | 
			
		||||
            // log.debug('Found pos for ',id,' ',i);
 | 
			
		||||
      return i
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var nodeList = [];
 | 
			
		||||
 | 
			
		||||
    nodeList = uniq(nodeList.concat.apply(nodeList,list));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    var subGraph = {id:'subGraph'+subCount, nodes:nodeList,title:title};
 | 
			
		||||
//log.debug('subGraph:' + subGraph.title + subGraph.id);
 | 
			
		||||
//log.debug(subGraph.nodes);
 | 
			
		||||
    subGraphs.push(subGraph);
 | 
			
		||||
    subCount = subCount + 1;
 | 
			
		||||
    return subGraph.id;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var getPosForId = function(id){
 | 
			
		||||
    var i;
 | 
			
		||||
    for(i=0;i<subGraphs.length;i++){
 | 
			
		||||
        if(subGraphs[i].id===id){
 | 
			
		||||
            //log.debug('Found pos for ',id,' ',i);
 | 
			
		||||
            return i;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    //log.debug('No pos found for ',id,' ',i);
 | 
			
		||||
    return -1;
 | 
			
		||||
};
 | 
			
		||||
var secCount = -1;
 | 
			
		||||
var posCrossRef = [];
 | 
			
		||||
  }
 | 
			
		||||
    // log.debug('No pos found for ',id,' ',i);
 | 
			
		||||
  return -1
 | 
			
		||||
}
 | 
			
		||||
var secCount = -1
 | 
			
		||||
var posCrossRef = []
 | 
			
		||||
var indexNodes = function (id, pos) {
 | 
			
		||||
    var nodes = subGraphs[pos].nodes;
 | 
			
		||||
    secCount = secCount + 1;
 | 
			
		||||
    if(secCount>2000){
 | 
			
		||||
        return;
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
    //var nPos = getPosForId(subGraphs[pos].id);
 | 
			
		||||
    posCrossRef[secCount]=pos;
 | 
			
		||||
  var nodes = subGraphs[pos].nodes
 | 
			
		||||
  secCount = secCount + 1
 | 
			
		||||
  if (secCount > 2000) {
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
    // var nPos = getPosForId(subGraphs[pos].id);
 | 
			
		||||
  posCrossRef[secCount] = pos
 | 
			
		||||
    // Check if match
 | 
			
		||||
    if(subGraphs[pos].id === id){
 | 
			
		||||
        return {
 | 
			
		||||
            result:true,
 | 
			
		||||
            count:0
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    var count = 0;
 | 
			
		||||
    var posCount = 1;
 | 
			
		||||
    while(count<nodes.length){
 | 
			
		||||
        var childPos = getPosForId(nodes[count]);
 | 
			
		||||
        // Ignore regular nodes (pos will be -1)
 | 
			
		||||
        if(childPos>=0){
 | 
			
		||||
            var res = indexNodes(id,childPos);
 | 
			
		||||
            if(res.result){
 | 
			
		||||
                return {
 | 
			
		||||
                    result:true,
 | 
			
		||||
                    count:posCount+res.count
 | 
			
		||||
                };
 | 
			
		||||
            }else{
 | 
			
		||||
                posCount = posCount + res.count;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        count = count +1;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
  if (subGraphs[pos].id === id) {
 | 
			
		||||
    return {
 | 
			
		||||
        result:false,
 | 
			
		||||
        count:posCount
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
      result: true,
 | 
			
		||||
      count: 0
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  var count = 0
 | 
			
		||||
  var posCount = 1
 | 
			
		||||
  while (count < nodes.length) {
 | 
			
		||||
    var childPos = getPosForId(nodes[count])
 | 
			
		||||
        // Ignore regular nodes (pos will be -1)
 | 
			
		||||
    if (childPos >= 0) {
 | 
			
		||||
      var res = indexNodes(id, childPos)
 | 
			
		||||
      if (res.result) {
 | 
			
		||||
        return {
 | 
			
		||||
          result: true,
 | 
			
		||||
          count: posCount + res.count
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        posCount = posCount + res.count
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    count = count + 1
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    result: false,
 | 
			
		||||
    count: posCount
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.getDepthFirstPos = function (pos) {
 | 
			
		||||
    return posCrossRef[pos];
 | 
			
		||||
};
 | 
			
		||||
  return posCrossRef[pos]
 | 
			
		||||
}
 | 
			
		||||
exports.indexNodes = function () {
 | 
			
		||||
    secCount = -1;
 | 
			
		||||
    if(subGraphs.length>0){
 | 
			
		||||
        indexNodes('none',subGraphs.length-1,0);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
  secCount = -1
 | 
			
		||||
  if (subGraphs.length > 0) {
 | 
			
		||||
    indexNodes('none', subGraphs.length - 1, 0)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.getSubGraphs = function () {
 | 
			
		||||
    return subGraphs;
 | 
			
		||||
};
 | 
			
		||||
  return subGraphs
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.parseError = function(err,hash){
 | 
			
		||||
    global.mermaidAPI.parseError(err,hash);
 | 
			
		||||
};
 | 
			
		||||
exports.parseError = function (err, hash) {
 | 
			
		||||
  global.mermaidAPI.parseError(err, hash)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,55 +1,55 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Created by knut on 14-11-18.
 | 
			
		||||
 */
 | 
			
		||||
describe('when parsing a gantt diagram it',function() {
 | 
			
		||||
    var gantt;
 | 
			
		||||
    beforeEach(function () {
 | 
			
		||||
        gantt = require('./parser/gantt').parser;
 | 
			
		||||
        gantt.yy = require('./ganttDb');
 | 
			
		||||
describe('when parsing a gantt diagram it', function () {
 | 
			
		||||
  var gantt
 | 
			
		||||
  beforeEach(function () {
 | 
			
		||||
    gantt = require('./parser/gantt').parser
 | 
			
		||||
    gantt.yy = require('./ganttDb')
 | 
			
		||||
 | 
			
		||||
        //ex.yy.parseError = parseError;
 | 
			
		||||
    });
 | 
			
		||||
        // ex.yy.parseError = parseError;
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    it('should handle an dateFormat definition', function () {
 | 
			
		||||
        var str = 'gantt\ndateFormat yyyy-mm-dd';
 | 
			
		||||
  it('should handle an dateFormat definition', function () {
 | 
			
		||||
    var str = 'gantt\ndateFormat yyyy-mm-dd'
 | 
			
		||||
 | 
			
		||||
        gantt.parse(str);
 | 
			
		||||
    });
 | 
			
		||||
    it('should handle an dateFormat definition', function () {
 | 
			
		||||
        var str = 'gantt\ndateFormat yyyy-mm-dd\ntitle Adding gantt diagram functionality to mermaid';
 | 
			
		||||
    gantt.parse(str)
 | 
			
		||||
  })
 | 
			
		||||
  it('should handle an dateFormat definition', function () {
 | 
			
		||||
    var str = 'gantt\ndateFormat yyyy-mm-dd\ntitle Adding gantt diagram functionality to mermaid'
 | 
			
		||||
 | 
			
		||||
        gantt.parse(str);
 | 
			
		||||
    });
 | 
			
		||||
    it('should handle an dateFormat definition', function () {
 | 
			
		||||
        var str = 'gantt\ndateFormat yyyy-mm-dd\ntitle Adding gantt diagram functionality to mermaid';
 | 
			
		||||
    gantt.parse(str)
 | 
			
		||||
  })
 | 
			
		||||
  it('should handle an dateFormat definition', function () {
 | 
			
		||||
    var str = 'gantt\ndateFormat yyyy-mm-dd\ntitle Adding gantt diagram functionality to mermaid'
 | 
			
		||||
 | 
			
		||||
        gantt.parse(str);
 | 
			
		||||
    });
 | 
			
		||||
    it('should handle an section definition', function () {
 | 
			
		||||
        var str = 'gantt\ndateFormat yyyy-mm-dd\ntitle Adding gantt diagram functionality to mermaid';
 | 
			
		||||
    gantt.parse(str)
 | 
			
		||||
  })
 | 
			
		||||
  it('should handle an section definition', function () {
 | 
			
		||||
    var str = 'gantt\ndateFormat yyyy-mm-dd\ntitle Adding gantt diagram functionality to mermaid'
 | 
			
		||||
 | 
			
		||||
        gantt.parse(str);
 | 
			
		||||
    });
 | 
			
		||||
    gantt.parse(str)
 | 
			
		||||
  })
 | 
			
		||||
    /**
 | 
			
		||||
     * Beslutsflöde inligt nedan. Obs bla bla bla 
 | 
			
		||||
     * Beslutsflöde inligt nedan. Obs bla bla bla
 | 
			
		||||
     * ```
 | 
			
		||||
     * graph TD
 | 
			
		||||
     * A[Hard pledge] -- text on link -->B(Round edge)
 | 
			
		||||
     * B --> C{to do or not to do}
 | 
			
		||||
     * C -->|Too| D[Result one]
 | 
			
		||||
     * C -->|Doo| E[Result two]
 | 
			
		||||
     ``` 
 | 
			
		||||
     ```
 | 
			
		||||
     * params bapa - a unique bapap
 | 
			
		||||
     */
 | 
			
		||||
    it('should handle a task definition', function () {
 | 
			
		||||
        var str = 'gantt\n' +
 | 
			
		||||
  it('should handle a task definition', function () {
 | 
			
		||||
    var str = 'gantt\n' +
 | 
			
		||||
            'dateFormat yyyy-mm-dd\n' +
 | 
			
		||||
            'title Adding gantt diagram functionality to mermaid\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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,152 +1,148 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Created by knut on 15-01-14.
 | 
			
		||||
 */
 | 
			
		||||
var moment = require('moment');
 | 
			
		||||
var Logger = require('../../logger');
 | 
			
		||||
var log = Logger.Log;
 | 
			
		||||
var moment = require('moment')
 | 
			
		||||
var Logger = require('../../logger')
 | 
			
		||||
var log = Logger.Log
 | 
			
		||||
 | 
			
		||||
var dateFormat = ''
 | 
			
		||||
var title = ''
 | 
			
		||||
var sections = []
 | 
			
		||||
var tasks = []
 | 
			
		||||
var currentSection = ''
 | 
			
		||||
 | 
			
		||||
var dateFormat = '';
 | 
			
		||||
var title = '';
 | 
			
		||||
var sections = [];
 | 
			
		||||
var tasks = [];
 | 
			
		||||
var currentSection = '';
 | 
			
		||||
exports.clear = function () {
 | 
			
		||||
  sections = []
 | 
			
		||||
  tasks = []
 | 
			
		||||
  currentSection = ''
 | 
			
		||||
  title = ''
 | 
			
		||||
  taskCnt = 0
 | 
			
		||||
  lastTask = undefined
 | 
			
		||||
  lastTaskID = undefined
 | 
			
		||||
  rawTasks = []
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.clear = function(){
 | 
			
		||||
    sections = [];
 | 
			
		||||
    tasks = [];
 | 
			
		||||
    currentSection = '';
 | 
			
		||||
    title = '';
 | 
			
		||||
    taskCnt = 0;
 | 
			
		||||
    lastTask = undefined;
 | 
			
		||||
    lastTaskID = undefined;
 | 
			
		||||
    rawTasks = [];
 | 
			
		||||
};
 | 
			
		||||
exports.setDateFormat = function (txt) {
 | 
			
		||||
  dateFormat = txt
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.setDateFormat = function(txt){
 | 
			
		||||
    dateFormat = txt;
 | 
			
		||||
};
 | 
			
		||||
exports.getDateFormat = function () {
 | 
			
		||||
  return dateFormat
 | 
			
		||||
}
 | 
			
		||||
exports.setTitle = function (txt) {
 | 
			
		||||
  title = txt
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.getDateFormat = function(){
 | 
			
		||||
    return dateFormat;
 | 
			
		||||
};
 | 
			
		||||
exports.setTitle = function(txt){
 | 
			
		||||
    title = txt;
 | 
			
		||||
};
 | 
			
		||||
exports.getTitle = function () {
 | 
			
		||||
  return title
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.getTitle = function(){
 | 
			
		||||
    return title;
 | 
			
		||||
};
 | 
			
		||||
exports.addSection = function (txt) {
 | 
			
		||||
  currentSection = txt
 | 
			
		||||
  sections.push(txt)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.addSection = function(txt){
 | 
			
		||||
    currentSection = txt;
 | 
			
		||||
    sections.push(txt);
 | 
			
		||||
};
 | 
			
		||||
exports.getTasks = function () {
 | 
			
		||||
  var allItemsPricessed = compileTasks()
 | 
			
		||||
  var maxDepth = 10
 | 
			
		||||
  var iterationCount = 0
 | 
			
		||||
  while (!allItemsPricessed && (iterationCount < maxDepth)) {
 | 
			
		||||
    allItemsPricessed = compileTasks()
 | 
			
		||||
    iterationCount++
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  tasks = rawTasks
 | 
			
		||||
 | 
			
		||||
exports.getTasks=function(){
 | 
			
		||||
    var allItemsPricessed = compileTasks();
 | 
			
		||||
    var maxDepth = 10;
 | 
			
		||||
    var iterationCount = 0;
 | 
			
		||||
    while(!allItemsPricessed && (iterationCount < maxDepth)){
 | 
			
		||||
        allItemsPricessed = compileTasks();
 | 
			
		||||
        iterationCount++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tasks = rawTasks;
 | 
			
		||||
 | 
			
		||||
    //var i;
 | 
			
		||||
    //for(i=10000;i<tasks.length;i++){
 | 
			
		||||
    // 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) {
 | 
			
		||||
    // console.log('Deciding start date:'+JSON.stringify(str));
 | 
			
		||||
    // log.debug('Deciding start date:'+str);
 | 
			
		||||
    // log.debug('with dateformat:'+dateFormat);
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
    var re = /^after\s+([\d\w\-]+)/;
 | 
			
		||||
    var afterStatement = re.exec(str.trim());
 | 
			
		||||
  var re = /^after\s+([\d\w\-]+)/
 | 
			
		||||
  var afterStatement = re.exec(str.trim())
 | 
			
		||||
 | 
			
		||||
    if(afterStatement!==null){
 | 
			
		||||
        var task = exports.findTaskById(afterStatement[1]);
 | 
			
		||||
  if (afterStatement !== null) {
 | 
			
		||||
    var task = exports.findTaskById(afterStatement[1])
 | 
			
		||||
 | 
			
		||||
        if(typeof task === 'undefined'){
 | 
			
		||||
            var dt = new Date();
 | 
			
		||||
            dt.setHours(0,0,0,0);
 | 
			
		||||
            return dt;
 | 
			
		||||
            //return undefined;
 | 
			
		||||
        }
 | 
			
		||||
        return task.endTime;
 | 
			
		||||
    if (typeof task === 'undefined') {
 | 
			
		||||
      var dt = new Date()
 | 
			
		||||
      dt.setHours(0, 0, 0, 0)
 | 
			
		||||
      return dt
 | 
			
		||||
            // return undefined;
 | 
			
		||||
    }
 | 
			
		||||
    return task.endTime
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    // Check for actual date set
 | 
			
		||||
    if(moment(str,dateFormat.trim(),true).isValid()){
 | 
			
		||||
        return moment(str,dateFormat.trim(),true).toDate();
 | 
			
		||||
    }else{
 | 
			
		||||
        log.debug('Invalid date:'+str);
 | 
			
		||||
        log.debug('With date format:'+dateFormat.trim());
 | 
			
		||||
        //log.debug('----');
 | 
			
		||||
    }
 | 
			
		||||
  if (moment(str, dateFormat.trim(), true).isValid()) {
 | 
			
		||||
    return moment(str, dateFormat.trim(), true).toDate()
 | 
			
		||||
  } else {
 | 
			
		||||
    log.debug('Invalid date:' + str)
 | 
			
		||||
    log.debug('With date format:' + dateFormat.trim())
 | 
			
		||||
        // log.debug('----');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    // Default date - now
 | 
			
		||||
    return new Date();
 | 
			
		||||
};
 | 
			
		||||
  return new Date()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var getEndDate = function(prevTime, dateFormat, str){
 | 
			
		||||
    str = str.trim();
 | 
			
		||||
var getEndDate = function (prevTime, dateFormat, str) {
 | 
			
		||||
  str = str.trim()
 | 
			
		||||
 | 
			
		||||
    // 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
 | 
			
		||||
    var re = /^([\d]+)([wdhms])/;
 | 
			
		||||
    var durationStatement = re.exec(str.trim());
 | 
			
		||||
  var re = /^([\d]+)([wdhms])/
 | 
			
		||||
  var durationStatement = re.exec(str.trim())
 | 
			
		||||
 | 
			
		||||
    if(durationStatement!== null){
 | 
			
		||||
        switch(durationStatement[2]){
 | 
			
		||||
            case 's':
 | 
			
		||||
                d.add(durationStatement[1], 'seconds');
 | 
			
		||||
                break;
 | 
			
		||||
            case 'm':
 | 
			
		||||
                d.add(durationStatement[1], 'minutes');
 | 
			
		||||
                break;
 | 
			
		||||
            case 'h':
 | 
			
		||||
                d.add(durationStatement[1], 'hours');
 | 
			
		||||
                break;
 | 
			
		||||
            case 'd':
 | 
			
		||||
                d.add(durationStatement[1], 'days');
 | 
			
		||||
                break;
 | 
			
		||||
            case 'w':
 | 
			
		||||
                d.add(durationStatement[1], 'weeks');
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        return d.toDate();
 | 
			
		||||
  if (durationStatement !== null) {
 | 
			
		||||
    switch (durationStatement[2]) {
 | 
			
		||||
      case 's':
 | 
			
		||||
        d.add(durationStatement[1], 'seconds')
 | 
			
		||||
        break
 | 
			
		||||
      case 'm':
 | 
			
		||||
        d.add(durationStatement[1], 'minutes')
 | 
			
		||||
        break
 | 
			
		||||
      case 'h':
 | 
			
		||||
        d.add(durationStatement[1], 'hours')
 | 
			
		||||
        break
 | 
			
		||||
      case 'd':
 | 
			
		||||
        d.add(durationStatement[1], 'days')
 | 
			
		||||
        break
 | 
			
		||||
      case 'w':
 | 
			
		||||
        d.add(durationStatement[1], 'weeks')
 | 
			
		||||
        break
 | 
			
		||||
    }
 | 
			
		||||
    return d.toDate()
 | 
			
		||||
  }
 | 
			
		||||
    // Default date - now
 | 
			
		||||
    return d.toDate();
 | 
			
		||||
};
 | 
			
		||||
  return d.toDate()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var taskCnt = 0;
 | 
			
		||||
var parseId = function(idStr){
 | 
			
		||||
    if(typeof idStr === 'undefined'){
 | 
			
		||||
        taskCnt = taskCnt + 1;
 | 
			
		||||
        return 'task'+taskCnt;
 | 
			
		||||
    }
 | 
			
		||||
    return idStr;
 | 
			
		||||
};
 | 
			
		||||
var taskCnt = 0
 | 
			
		||||
var parseId = function (idStr) {
 | 
			
		||||
  if (typeof idStr === 'undefined') {
 | 
			
		||||
    taskCnt = taskCnt + 1
 | 
			
		||||
    return 'task' + taskCnt
 | 
			
		||||
  }
 | 
			
		||||
  return idStr
 | 
			
		||||
}
 | 
			
		||||
// id, startDate, endDate
 | 
			
		||||
// id, startDate, length
 | 
			
		||||
// id, after x, endDate
 | 
			
		||||
@@ -158,241 +154,224 @@ var parseId = function(idStr){
 | 
			
		||||
// endDate
 | 
			
		||||
// length
 | 
			
		||||
 | 
			
		||||
var compileData = function(prevTask, dataStr){
 | 
			
		||||
    var ds;
 | 
			
		||||
var compileData = function (prevTask, dataStr) {
 | 
			
		||||
  var ds
 | 
			
		||||
 | 
			
		||||
    if(dataStr.substr(0,1) === ':'){
 | 
			
		||||
        ds = dataStr.substr(1,dataStr.length);
 | 
			
		||||
    }
 | 
			
		||||
    else{
 | 
			
		||||
        ds=dataStr;
 | 
			
		||||
    }
 | 
			
		||||
  if (dataStr.substr(0, 1) === ':') {
 | 
			
		||||
    ds = dataStr.substr(1, dataStr.length)
 | 
			
		||||
  } else {
 | 
			
		||||
    ds = dataStr
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    var data = ds.split(',');
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    var task = {};
 | 
			
		||||
    var df = exports.getDateFormat();
 | 
			
		||||
  var data = ds.split(',')
 | 
			
		||||
 | 
			
		||||
  var task = {}
 | 
			
		||||
  var df = exports.getDateFormat()
 | 
			
		||||
 | 
			
		||||
    // Get tags like active, done cand crit
 | 
			
		||||
    var matchFound = true;
 | 
			
		||||
    while(matchFound){
 | 
			
		||||
        matchFound = false;
 | 
			
		||||
        if(data[0].match(/^\s*active\s*$/)){
 | 
			
		||||
            task.active = true;
 | 
			
		||||
            data.shift(1);
 | 
			
		||||
            matchFound = true;
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        if(data[0].match(/^\s*done\s*$/)){
 | 
			
		||||
            task.done = true;
 | 
			
		||||
            data.shift(1);
 | 
			
		||||
            matchFound = true;
 | 
			
		||||
        }
 | 
			
		||||
        if(data[0].match(/^\s*crit\s*$/)){
 | 
			
		||||
            task.crit = true;
 | 
			
		||||
            data.shift(1);
 | 
			
		||||
            matchFound = true;
 | 
			
		||||
        }
 | 
			
		||||
  var matchFound = true
 | 
			
		||||
  while (matchFound) {
 | 
			
		||||
    matchFound = false
 | 
			
		||||
    if (data[0].match(/^\s*active\s*$/)) {
 | 
			
		||||
      task.active = true
 | 
			
		||||
      data.shift(1)
 | 
			
		||||
      matchFound = true
 | 
			
		||||
    }
 | 
			
		||||
    var i;
 | 
			
		||||
    for(i=0;i<data.length;i++){
 | 
			
		||||
        data[i] = data[i].trim();
 | 
			
		||||
    if (data[0].match(/^\s*done\s*$/)) {
 | 
			
		||||
      task.done = true
 | 
			
		||||
      data.shift(1)
 | 
			
		||||
      matchFound = true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    switch(data.length){
 | 
			
		||||
        case 1:
 | 
			
		||||
            task.id = parseId();
 | 
			
		||||
            task.startTime = prevTask.endTime;
 | 
			
		||||
            task.endTime   = getEndDate(task.startTime, df, data[0]);
 | 
			
		||||
            break;
 | 
			
		||||
        case 2:
 | 
			
		||||
            task.id = parseId();
 | 
			
		||||
            task.startTime = getStartDate(undefined, df, data[0]);
 | 
			
		||||
            task.endTime   = getEndDate(task.startTime, df, data[1]);
 | 
			
		||||
            break;
 | 
			
		||||
        case 3:
 | 
			
		||||
            task.id = parseId(data[0]);
 | 
			
		||||
            task.startTime = getStartDate(undefined, df, data[1]);
 | 
			
		||||
            task.endTime   = getEndDate(task.startTime, df, data[2]);
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
 | 
			
		||||
    if (data[0].match(/^\s*crit\s*$/)) {
 | 
			
		||||
      task.crit = true
 | 
			
		||||
      data.shift(1)
 | 
			
		||||
      matchFound = true
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  var i
 | 
			
		||||
  for (i = 0; i < data.length; i++) {
 | 
			
		||||
    data[i] = data[i].trim()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    return task;
 | 
			
		||||
};
 | 
			
		||||
  switch (data.length) {
 | 
			
		||||
    case 1:
 | 
			
		||||
      task.id = parseId()
 | 
			
		||||
      task.startTime = prevTask.endTime
 | 
			
		||||
      task.endTime = getEndDate(task.startTime, df, data[0])
 | 
			
		||||
      break
 | 
			
		||||
    case 2:
 | 
			
		||||
      task.id = parseId()
 | 
			
		||||
      task.startTime = getStartDate(undefined, df, data[0])
 | 
			
		||||
      task.endTime = getEndDate(task.startTime, df, data[1])
 | 
			
		||||
      break
 | 
			
		||||
    case 3:
 | 
			
		||||
      task.id = parseId(data[0])
 | 
			
		||||
      task.startTime = getStartDate(undefined, df, data[1])
 | 
			
		||||
      task.endTime = getEndDate(task.startTime, df, data[2])
 | 
			
		||||
      break
 | 
			
		||||
    default:
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
var parseData = function(prevTaskId, dataStr){
 | 
			
		||||
    var ds;
 | 
			
		||||
  return task
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    if(dataStr.substr(0,1) === ':'){
 | 
			
		||||
        ds = dataStr.substr(1,dataStr.length);
 | 
			
		||||
    }
 | 
			
		||||
    else{
 | 
			
		||||
        ds=dataStr;
 | 
			
		||||
    }
 | 
			
		||||
var parseData = function (prevTaskId, dataStr) {
 | 
			
		||||
  var ds
 | 
			
		||||
 | 
			
		||||
    var data = ds.split(',');
 | 
			
		||||
  if (dataStr.substr(0, 1) === ':') {
 | 
			
		||||
    ds = dataStr.substr(1, dataStr.length)
 | 
			
		||||
  } else {
 | 
			
		||||
    ds = dataStr
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  var data = ds.split(',')
 | 
			
		||||
 | 
			
		||||
    var task = {};
 | 
			
		||||
  var task = {}
 | 
			
		||||
 | 
			
		||||
    // Get tags like active, done cand crit
 | 
			
		||||
    var matchFound = true;
 | 
			
		||||
    while(matchFound){
 | 
			
		||||
        matchFound = false;
 | 
			
		||||
        if(data[0].match(/^\s*active\s*$/)){
 | 
			
		||||
            task.active = true;
 | 
			
		||||
            data.shift(1);
 | 
			
		||||
            matchFound = true;
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        if(data[0].match(/^\s*done\s*$/)){
 | 
			
		||||
            task.done = true;
 | 
			
		||||
            data.shift(1);
 | 
			
		||||
            matchFound = true;
 | 
			
		||||
        }
 | 
			
		||||
        if(data[0].match(/^\s*crit\s*$/)){
 | 
			
		||||
            task.crit = true;
 | 
			
		||||
            data.shift(1);
 | 
			
		||||
            matchFound = true;
 | 
			
		||||
        }
 | 
			
		||||
  var matchFound = true
 | 
			
		||||
  while (matchFound) {
 | 
			
		||||
    matchFound = false
 | 
			
		||||
    if (data[0].match(/^\s*active\s*$/)) {
 | 
			
		||||
      task.active = true
 | 
			
		||||
      data.shift(1)
 | 
			
		||||
      matchFound = true
 | 
			
		||||
    }
 | 
			
		||||
    var i;
 | 
			
		||||
    for(i=0;i<data.length;i++){
 | 
			
		||||
        data[i] = data[i].trim();
 | 
			
		||||
    if (data[0].match(/^\s*done\s*$/)) {
 | 
			
		||||
      task.done = true
 | 
			
		||||
      data.shift(1)
 | 
			
		||||
      matchFound = true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    switch(data.length){
 | 
			
		||||
        case 1:
 | 
			
		||||
            task.id = parseId();
 | 
			
		||||
            task.startTime = {type: 'prevTaskEnd', id:prevTaskId};
 | 
			
		||||
            task.endTime   = {data: data[0]};
 | 
			
		||||
            break;
 | 
			
		||||
        case 2:
 | 
			
		||||
            task.id = parseId();
 | 
			
		||||
            task.startTime = {type:'getStartDate',startData:data[0]};
 | 
			
		||||
            task.endTime   = {data: data[1]};
 | 
			
		||||
            break;
 | 
			
		||||
        case 3:
 | 
			
		||||
            task.id = parseId(data[0]);
 | 
			
		||||
            task.startTime = {type:'getStartDate',startData: data[1]};
 | 
			
		||||
            task.endTime   = {data: data[2]};
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
 | 
			
		||||
    if (data[0].match(/^\s*crit\s*$/)) {
 | 
			
		||||
      task.crit = true
 | 
			
		||||
      data.shift(1)
 | 
			
		||||
      matchFound = true
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  var i
 | 
			
		||||
  for (i = 0; i < data.length; i++) {
 | 
			
		||||
    data[i] = data[i].trim()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    return task;
 | 
			
		||||
};
 | 
			
		||||
  switch (data.length) {
 | 
			
		||||
    case 1:
 | 
			
		||||
      task.id = parseId()
 | 
			
		||||
      task.startTime = {type: 'prevTaskEnd', id: prevTaskId}
 | 
			
		||||
      task.endTime = {data: data[0]}
 | 
			
		||||
      break
 | 
			
		||||
    case 2:
 | 
			
		||||
      task.id = parseId()
 | 
			
		||||
      task.startTime = {type: 'getStartDate', startData: data[0]}
 | 
			
		||||
      task.endTime = {data: data[1]}
 | 
			
		||||
      break
 | 
			
		||||
    case 3:
 | 
			
		||||
      task.id = parseId(data[0])
 | 
			
		||||
      task.startTime = {type: 'getStartDate', startData: data[1]}
 | 
			
		||||
      task.endTime = {data: data[2]}
 | 
			
		||||
      break
 | 
			
		||||
    default:
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return task
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var lastTask
 | 
			
		||||
var lastTaskID
 | 
			
		||||
var rawTasks = []
 | 
			
		||||
var taskDb = {}
 | 
			
		||||
exports.addTask = function (descr, data) {
 | 
			
		||||
  var rawTask = {
 | 
			
		||||
    section: currentSection,
 | 
			
		||||
    type: currentSection,
 | 
			
		||||
    processed: false,
 | 
			
		||||
    raw: {data: data},
 | 
			
		||||
    task: descr
 | 
			
		||||
  }
 | 
			
		||||
  var taskInfo = parseData(lastTaskID, data)
 | 
			
		||||
  rawTask.raw.startTime = taskInfo.startTime
 | 
			
		||||
  rawTask.raw.endTime = taskInfo.endTime
 | 
			
		||||
  rawTask.id = taskInfo.id
 | 
			
		||||
  rawTask.prevTaskId = lastTaskID
 | 
			
		||||
  rawTask.active = taskInfo.active
 | 
			
		||||
  rawTask.done = taskInfo.done
 | 
			
		||||
  rawTask.crit = taskInfo.crit
 | 
			
		||||
 | 
			
		||||
var lastTask;
 | 
			
		||||
var lastTaskID;
 | 
			
		||||
var rawTasks = [];
 | 
			
		||||
var taskDb = {};
 | 
			
		||||
exports.addTask = function(descr,data){
 | 
			
		||||
    var rawTask = {
 | 
			
		||||
        section:currentSection,
 | 
			
		||||
        type:currentSection,
 | 
			
		||||
        processed:false,
 | 
			
		||||
        raw:{data:data},
 | 
			
		||||
        task:descr
 | 
			
		||||
    };
 | 
			
		||||
    var taskInfo = parseData(lastTaskID, data);
 | 
			
		||||
    rawTask.raw.startTime  = taskInfo.startTime;
 | 
			
		||||
    rawTask.raw.endTime    = taskInfo.endTime;
 | 
			
		||||
    rawTask.id         = taskInfo.id;
 | 
			
		||||
    rawTask.prevTaskId = lastTaskID;
 | 
			
		||||
    rawTask.active     = taskInfo.active;
 | 
			
		||||
    rawTask.done       = taskInfo.done;
 | 
			
		||||
    rawTask.crit       = taskInfo.crit;
 | 
			
		||||
  var pos = rawTasks.push(rawTask)
 | 
			
		||||
 | 
			
		||||
    var pos = rawTasks.push(rawTask);
 | 
			
		||||
 | 
			
		||||
    lastTaskID = rawTask.id;
 | 
			
		||||
  lastTaskID = rawTask.id
 | 
			
		||||
    // Store cross ref
 | 
			
		||||
    taskDb[rawTask.id]= pos-1;
 | 
			
		||||
  taskDb[rawTask.id] = pos - 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
exports.findTaskById = function(id) {
 | 
			
		||||
    //var i;
 | 
			
		||||
    //for(i=0;i<tasks.length;i++){
 | 
			
		||||
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];
 | 
			
		||||
    return rawTasks[pos];
 | 
			
		||||
};
 | 
			
		||||
  var pos = taskDb[id]
 | 
			
		||||
  return rawTasks[pos]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.addTaskOrg = function(descr,data){
 | 
			
		||||
exports.addTaskOrg = function (descr, data) {
 | 
			
		||||
  var newTask = {
 | 
			
		||||
    section: currentSection,
 | 
			
		||||
    type: currentSection,
 | 
			
		||||
    description: descr,
 | 
			
		||||
    task: descr
 | 
			
		||||
  }
 | 
			
		||||
  var taskInfo = compileData(lastTask, data)
 | 
			
		||||
  newTask.startTime = taskInfo.startTime
 | 
			
		||||
  newTask.endTime = taskInfo.endTime
 | 
			
		||||
  newTask.id = taskInfo.id
 | 
			
		||||
  newTask.active = taskInfo.active
 | 
			
		||||
  newTask.done = taskInfo.done
 | 
			
		||||
  newTask.crit = taskInfo.crit
 | 
			
		||||
  lastTask = newTask
 | 
			
		||||
  tasks.push(newTask)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    var newTask = {
 | 
			
		||||
        section:currentSection,
 | 
			
		||||
        type:currentSection,
 | 
			
		||||
        description:descr,
 | 
			
		||||
        task:descr
 | 
			
		||||
    };
 | 
			
		||||
    var taskInfo = compileData(lastTask, data);
 | 
			
		||||
    newTask.startTime = taskInfo.startTime;
 | 
			
		||||
    newTask.endTime   = taskInfo.endTime;
 | 
			
		||||
    newTask.id        = taskInfo.id;
 | 
			
		||||
    newTask.active    = taskInfo.active;
 | 
			
		||||
    newTask.done      = taskInfo.done;
 | 
			
		||||
    newTask.crit      = taskInfo.crit;
 | 
			
		||||
    lastTask = newTask;
 | 
			
		||||
    tasks.push(newTask);
 | 
			
		||||
};
 | 
			
		||||
var compileTasks = function () {
 | 
			
		||||
  var df = exports.getDateFormat()
 | 
			
		||||
 | 
			
		||||
var compileTasks=function(){
 | 
			
		||||
    var df = exports.getDateFormat();
 | 
			
		||||
 | 
			
		||||
    var compileTask = function(pos){
 | 
			
		||||
        var task = rawTasks[pos];
 | 
			
		||||
        var startTime = '';
 | 
			
		||||
        switch(rawTasks[pos].raw.startTime.type){
 | 
			
		||||
            case 'prevTaskEnd':
 | 
			
		||||
                var prevTask = exports.findTaskById(task.prevTaskId);
 | 
			
		||||
                task.startTime = prevTask.endTime;
 | 
			
		||||
                break;
 | 
			
		||||
            case 'getStartDate':
 | 
			
		||||
                startTime = getStartDate(undefined, df, rawTasks[pos].raw.startTime.startData);
 | 
			
		||||
                if(startTime){
 | 
			
		||||
                    rawTasks[pos].startTime = startTime;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
  var compileTask = function (pos) {
 | 
			
		||||
    var task = rawTasks[pos]
 | 
			
		||||
    var startTime = ''
 | 
			
		||||
    switch (rawTasks[pos].raw.startTime.type) {
 | 
			
		||||
      case 'prevTaskEnd':
 | 
			
		||||
        var prevTask = exports.findTaskById(task.prevTaskId)
 | 
			
		||||
        task.startTime = prevTask.endTime
 | 
			
		||||
        break
 | 
			
		||||
      case 'getStartDate':
 | 
			
		||||
        startTime = getStartDate(undefined, df, rawTasks[pos].raw.startTime.startData)
 | 
			
		||||
        if (startTime) {
 | 
			
		||||
          rawTasks[pos].startTime = startTime
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(rawTasks[pos].startTime){
 | 
			
		||||
            rawTasks[pos].endTime = getEndDate(rawTasks[pos].startTime, df, rawTasks[pos].raw.endTime.data);
 | 
			
		||||
            if(rawTasks[pos].endTime){
 | 
			
		||||
                rawTasks[pos].processed = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return rawTasks[pos].processed;
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    var i;
 | 
			
		||||
    var allProcessed = true;
 | 
			
		||||
    for(i=0;i<rawTasks.length;i++){
 | 
			
		||||
        compileTask(i);
 | 
			
		||||
 | 
			
		||||
        allProcessed = allProcessed && rawTasks[i].processed;
 | 
			
		||||
        break
 | 
			
		||||
    }
 | 
			
		||||
    return allProcessed;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
exports.parseError = function(err,hash){
 | 
			
		||||
    global.mermaidAPI.parseError(err,hash);
 | 
			
		||||
};
 | 
			
		||||
    if (rawTasks[pos].startTime) {
 | 
			
		||||
      rawTasks[pos].endTime = getEndDate(rawTasks[pos].startTime, df, rawTasks[pos].raw.endTime.data)
 | 
			
		||||
      if (rawTasks[pos].endTime) {
 | 
			
		||||
        rawTasks[pos].processed = true
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return rawTasks[pos].processed
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  var i
 | 
			
		||||
  var allProcessed = true
 | 
			
		||||
  for (i = 0; i < rawTasks.length; i++) {
 | 
			
		||||
    compileTask(i)
 | 
			
		||||
 | 
			
		||||
    allProcessed = allProcessed && rawTasks[i].processed
 | 
			
		||||
  }
 | 
			
		||||
  return allProcessed
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.parseError = function (err, hash) {
 | 
			
		||||
  global.mermaidAPI.parseError(err, hash)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,184 +1,183 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Created by knut on 14-11-18.
 | 
			
		||||
 */
 | 
			
		||||
describe('when using the ganttDb',function() {
 | 
			
		||||
    var gDb;
 | 
			
		||||
    var moment = require('moment');
 | 
			
		||||
    
 | 
			
		||||
    beforeEach(function () {
 | 
			
		||||
        //gantt = require('./parser/gantt').parser;
 | 
			
		||||
describe('when using the ganttDb', function () {
 | 
			
		||||
  var gDb
 | 
			
		||||
  var moment = require('moment')
 | 
			
		||||
 | 
			
		||||
        gDb = require('./ganttDb');
 | 
			
		||||
        gDb.clear();
 | 
			
		||||
        //ex.yy.parseError = parseError;
 | 
			
		||||
    });
 | 
			
		||||
  beforeEach(function () {
 | 
			
		||||
        // gantt = require('./parser/gantt').parser;
 | 
			
		||||
 | 
			
		||||
    it('should handle an fixed dates', function () {
 | 
			
		||||
        gDb.setDateFormat('YYYY-MM-DD');
 | 
			
		||||
        gDb.addSection('testa1');
 | 
			
		||||
        gDb.addTask('test1','id1,2013-01-01,2013-01-12');
 | 
			
		||||
        var tasks = gDb.getTasks();
 | 
			
		||||
        expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate());
 | 
			
		||||
        expect(tasks[0].endTime  ).toEqual(moment('2013-01-12', 'YYYY-MM-DD').toDate());
 | 
			
		||||
        expect(tasks[0].id       ).toEqual('id1');
 | 
			
		||||
        expect(tasks[0].task).toEqual('test1');
 | 
			
		||||
    });
 | 
			
		||||
    it('should handle duration (days) instead of fixed date to determine end date', function () {
 | 
			
		||||
        gDb.setDateFormat('YYYY-MM-DD');
 | 
			
		||||
        gDb.addSection('testa1');
 | 
			
		||||
        gDb.addTask('test1','id1,2013-01-01,2d');
 | 
			
		||||
        var tasks = gDb.getTasks();
 | 
			
		||||
        expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate());
 | 
			
		||||
        expect(tasks[0].endTime  ).toEqual(moment('2013-01-03', 'YYYY-MM-DD').toDate());
 | 
			
		||||
        expect(tasks[0].id       ).toEqual('id1');
 | 
			
		||||
        expect(tasks[0].task).toEqual('test1');
 | 
			
		||||
    });
 | 
			
		||||
    it('should handle duration (hours) instead of fixed date to determine end date', function () {
 | 
			
		||||
        gDb.setDateFormat('YYYY-MM-DD');
 | 
			
		||||
        gDb.addSection('testa1');
 | 
			
		||||
        gDb.addTask('test1','id1,2013-01-01,2h');
 | 
			
		||||
        var tasks = gDb.getTasks();
 | 
			
		||||
        expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate());
 | 
			
		||||
        expect(tasks[0].endTime  ).toEqual(moment('2013-01-01 2:00', 'YYYY-MM-DD hh:mm').toDate());
 | 
			
		||||
        expect(tasks[0].id       ).toEqual('id1');
 | 
			
		||||
        expect(tasks[0].task).toEqual('test1');
 | 
			
		||||
    });
 | 
			
		||||
    it('should handle duration (minutes) instead of fixed date to determine end date', function () {
 | 
			
		||||
        gDb.setDateFormat('YYYY-MM-DD');
 | 
			
		||||
        gDb.addSection('testa1');
 | 
			
		||||
        gDb.addTask('test1','id1,2013-01-01,2m');
 | 
			
		||||
        var tasks = gDb.getTasks();
 | 
			
		||||
        expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate());
 | 
			
		||||
        expect(tasks[0].endTime  ).toEqual(moment('2013-01-01 00:02', 'YYYY-MM-DD hh:mm').toDate());
 | 
			
		||||
        expect(tasks[0].id       ).toEqual('id1');
 | 
			
		||||
        expect(tasks[0].task).toEqual('test1');
 | 
			
		||||
    });
 | 
			
		||||
    it('should handle duration (seconds) instead of fixed date to determine end date', function () {
 | 
			
		||||
        gDb.setDateFormat('YYYY-MM-DD');
 | 
			
		||||
        gDb.addSection('testa1');
 | 
			
		||||
        gDb.addTask('test1','id1,2013-01-01,2s');
 | 
			
		||||
        var tasks = gDb.getTasks();
 | 
			
		||||
        expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate());
 | 
			
		||||
        expect(tasks[0].endTime  ).toEqual(moment('2013-01-01 00:00:02', 'YYYY-MM-DD hh:mm:ss').toDate());
 | 
			
		||||
        expect(tasks[0].id       ).toEqual('id1');
 | 
			
		||||
        expect(tasks[0].task).toEqual('test1');
 | 
			
		||||
    });
 | 
			
		||||
    it('should handle duration (weeks) instead of fixed date to determine end date', function () {
 | 
			
		||||
        gDb.setDateFormat('YYYY-MM-DD');
 | 
			
		||||
        gDb.addSection('testa1');
 | 
			
		||||
        gDb.addTask('test1','id1,2013-01-01,2w');
 | 
			
		||||
        var tasks = gDb.getTasks();
 | 
			
		||||
        expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate());
 | 
			
		||||
        expect(tasks[0].endTime  ).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate());
 | 
			
		||||
        expect(tasks[0].id       ).toEqual('id1');
 | 
			
		||||
        expect(tasks[0].task).toEqual('test1');
 | 
			
		||||
    });
 | 
			
		||||
    
 | 
			
		||||
    it('should handle relative start date based on id', function () {
 | 
			
		||||
        gDb.setDateFormat('YYYY-MM-DD');
 | 
			
		||||
        gDb.addSection('testa1');
 | 
			
		||||
        gDb.addTask('test1','id1,2013-01-01,2w');
 | 
			
		||||
        gDb.addTask('test2','id2,after id1,1d');
 | 
			
		||||
        
 | 
			
		||||
        var tasks = gDb.getTasks();
 | 
			
		||||
        
 | 
			
		||||
        expect(tasks[1].startTime  ).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate());
 | 
			
		||||
        expect(tasks[1].id         ).toEqual('id2');
 | 
			
		||||
        expect(tasks[1].task).toEqual('test2');
 | 
			
		||||
    });
 | 
			
		||||
    
 | 
			
		||||
    it('should handle relative start date based on id when id is invalid', function () {
 | 
			
		||||
        gDb.setDateFormat('YYYY-MM-DD');
 | 
			
		||||
        gDb.addSection('testa1');
 | 
			
		||||
        gDb.addTask('test1','id1,2013-01-01,2w');
 | 
			
		||||
        gDb.addTask('test2','id2,after id3,1d');
 | 
			
		||||
        var tasks = gDb.getTasks();
 | 
			
		||||
        expect(tasks[1].startTime).toEqual(new Date((new Date()).setHours(0,0,0,0)));
 | 
			
		||||
        expect(tasks[1].id       ).toEqual('id2');
 | 
			
		||||
        expect(tasks[1].task).toEqual('test2');
 | 
			
		||||
    });
 | 
			
		||||
    gDb = require('./ganttDb')
 | 
			
		||||
    gDb.clear()
 | 
			
		||||
        // ex.yy.parseError = parseError;
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    it('should handle fixed dates without id', function () {
 | 
			
		||||
        gDb.setDateFormat('YYYY-MM-DD');
 | 
			
		||||
        gDb.addSection('testa1');
 | 
			
		||||
        gDb.addTask('test1','2013-01-01,2013-01-12');
 | 
			
		||||
        var tasks = gDb.getTasks();
 | 
			
		||||
        expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate());
 | 
			
		||||
        expect(tasks[0].endTime  ).toEqual(moment('2013-01-12', 'YYYY-MM-DD').toDate());
 | 
			
		||||
        expect(tasks[0].id       ).toEqual('task1');
 | 
			
		||||
        expect(tasks[0].task).toEqual('test1');
 | 
			
		||||
    });
 | 
			
		||||
  it('should handle an fixed dates', function () {
 | 
			
		||||
    gDb.setDateFormat('YYYY-MM-DD')
 | 
			
		||||
    gDb.addSection('testa1')
 | 
			
		||||
    gDb.addTask('test1', 'id1,2013-01-01,2013-01-12')
 | 
			
		||||
    var tasks = gDb.getTasks()
 | 
			
		||||
    expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate())
 | 
			
		||||
    expect(tasks[0].endTime).toEqual(moment('2013-01-12', 'YYYY-MM-DD').toDate())
 | 
			
		||||
    expect(tasks[0].id).toEqual('id1')
 | 
			
		||||
    expect(tasks[0].task).toEqual('test1')
 | 
			
		||||
  })
 | 
			
		||||
  it('should handle duration (days) instead of fixed date to determine end date', function () {
 | 
			
		||||
    gDb.setDateFormat('YYYY-MM-DD')
 | 
			
		||||
    gDb.addSection('testa1')
 | 
			
		||||
    gDb.addTask('test1', 'id1,2013-01-01,2d')
 | 
			
		||||
    var tasks = gDb.getTasks()
 | 
			
		||||
    expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate())
 | 
			
		||||
    expect(tasks[0].endTime).toEqual(moment('2013-01-03', 'YYYY-MM-DD').toDate())
 | 
			
		||||
    expect(tasks[0].id).toEqual('id1')
 | 
			
		||||
    expect(tasks[0].task).toEqual('test1')
 | 
			
		||||
  })
 | 
			
		||||
  it('should handle duration (hours) instead of fixed date to determine end date', function () {
 | 
			
		||||
    gDb.setDateFormat('YYYY-MM-DD')
 | 
			
		||||
    gDb.addSection('testa1')
 | 
			
		||||
    gDb.addTask('test1', 'id1,2013-01-01,2h')
 | 
			
		||||
    var tasks = gDb.getTasks()
 | 
			
		||||
    expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate())
 | 
			
		||||
    expect(tasks[0].endTime).toEqual(moment('2013-01-01 2:00', 'YYYY-MM-DD hh:mm').toDate())
 | 
			
		||||
    expect(tasks[0].id).toEqual('id1')
 | 
			
		||||
    expect(tasks[0].task).toEqual('test1')
 | 
			
		||||
  })
 | 
			
		||||
  it('should handle duration (minutes) instead of fixed date to determine end date', function () {
 | 
			
		||||
    gDb.setDateFormat('YYYY-MM-DD')
 | 
			
		||||
    gDb.addSection('testa1')
 | 
			
		||||
    gDb.addTask('test1', 'id1,2013-01-01,2m')
 | 
			
		||||
    var tasks = gDb.getTasks()
 | 
			
		||||
    expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate())
 | 
			
		||||
    expect(tasks[0].endTime).toEqual(moment('2013-01-01 00:02', 'YYYY-MM-DD hh:mm').toDate())
 | 
			
		||||
    expect(tasks[0].id).toEqual('id1')
 | 
			
		||||
    expect(tasks[0].task).toEqual('test1')
 | 
			
		||||
  })
 | 
			
		||||
  it('should handle duration (seconds) instead of fixed date to determine end date', function () {
 | 
			
		||||
    gDb.setDateFormat('YYYY-MM-DD')
 | 
			
		||||
    gDb.addSection('testa1')
 | 
			
		||||
    gDb.addTask('test1', 'id1,2013-01-01,2s')
 | 
			
		||||
    var tasks = gDb.getTasks()
 | 
			
		||||
    expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate())
 | 
			
		||||
    expect(tasks[0].endTime).toEqual(moment('2013-01-01 00:00:02', 'YYYY-MM-DD hh:mm:ss').toDate())
 | 
			
		||||
    expect(tasks[0].id).toEqual('id1')
 | 
			
		||||
    expect(tasks[0].task).toEqual('test1')
 | 
			
		||||
  })
 | 
			
		||||
  it('should handle duration (weeks) instead of fixed date to determine end date', function () {
 | 
			
		||||
    gDb.setDateFormat('YYYY-MM-DD')
 | 
			
		||||
    gDb.addSection('testa1')
 | 
			
		||||
    gDb.addTask('test1', 'id1,2013-01-01,2w')
 | 
			
		||||
    var tasks = gDb.getTasks()
 | 
			
		||||
    expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate())
 | 
			
		||||
    expect(tasks[0].endTime).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate())
 | 
			
		||||
    expect(tasks[0].id).toEqual('id1')
 | 
			
		||||
    expect(tasks[0].task).toEqual('test1')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    it('should handle duration instead of a fixed date to determine end date without id', function () {
 | 
			
		||||
        gDb.setDateFormat('YYYY-MM-DD');
 | 
			
		||||
        gDb.addSection('testa1');
 | 
			
		||||
        gDb.addTask('test1','2013-01-01,4d');
 | 
			
		||||
        var tasks = gDb.getTasks();
 | 
			
		||||
        expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate());
 | 
			
		||||
        expect(tasks[0].endTime  ).toEqual(moment('2013-01-05', 'YYYY-MM-DD').toDate());
 | 
			
		||||
        expect(tasks[0].id       ).toEqual('task1');
 | 
			
		||||
        expect(tasks[0].task).toEqual('test1');
 | 
			
		||||
    });
 | 
			
		||||
  it('should handle relative start date based on id', function () {
 | 
			
		||||
    gDb.setDateFormat('YYYY-MM-DD')
 | 
			
		||||
    gDb.addSection('testa1')
 | 
			
		||||
    gDb.addTask('test1', 'id1,2013-01-01,2w')
 | 
			
		||||
    gDb.addTask('test2', 'id2,after id1,1d')
 | 
			
		||||
 | 
			
		||||
    it('should handle relative start date of a fixed date to determine end date without id', function () {
 | 
			
		||||
        gDb.setDateFormat('YYYY-MM-DD');
 | 
			
		||||
        gDb.addSection('testa1');
 | 
			
		||||
        gDb.addTask('test1','id1,2013-01-01,2w');
 | 
			
		||||
        gDb.addTask('test2','after id1,1d');
 | 
			
		||||
    var tasks = gDb.getTasks()
 | 
			
		||||
 | 
			
		||||
        var tasks = gDb.getTasks();
 | 
			
		||||
    expect(tasks[1].startTime).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate())
 | 
			
		||||
    expect(tasks[1].id).toEqual('id2')
 | 
			
		||||
    expect(tasks[1].task).toEqual('test2')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
        expect(tasks[1].startTime  ).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate());
 | 
			
		||||
        expect(tasks[1].id         ).toEqual('task1');
 | 
			
		||||
        expect(tasks[1].task).toEqual('test2');
 | 
			
		||||
    });
 | 
			
		||||
    it('should handle a new task with only an end date as definition', function () {
 | 
			
		||||
        gDb.setDateFormat('YYYY-MM-DD');
 | 
			
		||||
        gDb.addSection('testa1');
 | 
			
		||||
        gDb.addTask('test1','id1,2013-01-01,2w');
 | 
			
		||||
        gDb.addTask('test2','2013-01-26');
 | 
			
		||||
  it('should handle relative start date based on id when id is invalid', function () {
 | 
			
		||||
    gDb.setDateFormat('YYYY-MM-DD')
 | 
			
		||||
    gDb.addSection('testa1')
 | 
			
		||||
    gDb.addTask('test1', 'id1,2013-01-01,2w')
 | 
			
		||||
    gDb.addTask('test2', 'id2,after id3,1d')
 | 
			
		||||
    var tasks = gDb.getTasks()
 | 
			
		||||
    expect(tasks[1].startTime).toEqual(new Date((new Date()).setHours(0, 0, 0, 0)))
 | 
			
		||||
    expect(tasks[1].id).toEqual('id2')
 | 
			
		||||
    expect(tasks[1].task).toEqual('test2')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
        var tasks = gDb.getTasks();
 | 
			
		||||
  it('should handle fixed dates without id', function () {
 | 
			
		||||
    gDb.setDateFormat('YYYY-MM-DD')
 | 
			
		||||
    gDb.addSection('testa1')
 | 
			
		||||
    gDb.addTask('test1', '2013-01-01,2013-01-12')
 | 
			
		||||
    var tasks = gDb.getTasks()
 | 
			
		||||
    expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate())
 | 
			
		||||
    expect(tasks[0].endTime).toEqual(moment('2013-01-12', 'YYYY-MM-DD').toDate())
 | 
			
		||||
    expect(tasks[0].id).toEqual('task1')
 | 
			
		||||
    expect(tasks[0].task).toEqual('test1')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
        expect(tasks[1].startTime).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate());
 | 
			
		||||
        expect(tasks[1].endTime  ).toEqual(moment('2013-01-26', 'YYYY-MM-DD').toDate());
 | 
			
		||||
        expect(tasks[1].id       ).toEqual('task1');
 | 
			
		||||
        expect(tasks[1].task).toEqual('test2');
 | 
			
		||||
    });
 | 
			
		||||
    it('should handle a new task with only an end date as definition', function () {
 | 
			
		||||
        gDb.setDateFormat('YYYY-MM-DD');
 | 
			
		||||
        gDb.addSection('testa1');
 | 
			
		||||
        gDb.addTask('test1','id1,2013-01-01,2w');
 | 
			
		||||
        gDb.addTask('test2','2d');
 | 
			
		||||
  it('should handle duration instead of a fixed date to determine end date without id', function () {
 | 
			
		||||
    gDb.setDateFormat('YYYY-MM-DD')
 | 
			
		||||
    gDb.addSection('testa1')
 | 
			
		||||
    gDb.addTask('test1', '2013-01-01,4d')
 | 
			
		||||
    var tasks = gDb.getTasks()
 | 
			
		||||
    expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate())
 | 
			
		||||
    expect(tasks[0].endTime).toEqual(moment('2013-01-05', 'YYYY-MM-DD').toDate())
 | 
			
		||||
    expect(tasks[0].id).toEqual('task1')
 | 
			
		||||
    expect(tasks[0].task).toEqual('test1')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
        var tasks = gDb.getTasks();
 | 
			
		||||
  it('should handle relative start date of a fixed date to determine end date without id', function () {
 | 
			
		||||
    gDb.setDateFormat('YYYY-MM-DD')
 | 
			
		||||
    gDb.addSection('testa1')
 | 
			
		||||
    gDb.addTask('test1', 'id1,2013-01-01,2w')
 | 
			
		||||
    gDb.addTask('test2', 'after id1,1d')
 | 
			
		||||
 | 
			
		||||
        expect(tasks[1].startTime).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate());
 | 
			
		||||
        expect(tasks[1].endTime  ).toEqual(moment('2013-01-17', 'YYYY-MM-DD').toDate());
 | 
			
		||||
        expect(tasks[1].id       ).toEqual('task1');
 | 
			
		||||
        expect(tasks[1].task).toEqual('test2');
 | 
			
		||||
    });
 | 
			
		||||
    it('should handle relative start date based on id regardless of sections', function () {
 | 
			
		||||
        gDb.setDateFormat('YYYY-MM-DD');
 | 
			
		||||
        gDb.addSection('testa1');
 | 
			
		||||
        gDb.addTask('test1','id1,2013-01-01,2w');
 | 
			
		||||
        gDb.addTask('test2','id2,after id3,1d');
 | 
			
		||||
        gDb.addSection('testa2');
 | 
			
		||||
        gDb.addTask('test3','id3,after id1,2d');
 | 
			
		||||
    var tasks = gDb.getTasks()
 | 
			
		||||
 | 
			
		||||
        var tasks = gDb.getTasks();
 | 
			
		||||
    expect(tasks[1].startTime).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate())
 | 
			
		||||
    expect(tasks[1].id).toEqual('task1')
 | 
			
		||||
    expect(tasks[1].task).toEqual('test2')
 | 
			
		||||
  })
 | 
			
		||||
  it('should handle a new task with only an end date as definition', function () {
 | 
			
		||||
    gDb.setDateFormat('YYYY-MM-DD')
 | 
			
		||||
    gDb.addSection('testa1')
 | 
			
		||||
    gDb.addTask('test1', 'id1,2013-01-01,2w')
 | 
			
		||||
    gDb.addTask('test2', '2013-01-26')
 | 
			
		||||
 | 
			
		||||
        expect(tasks[1].startTime  ).toEqual(moment('2013-01-17', 'YYYY-MM-DD').toDate());
 | 
			
		||||
        expect(tasks[1].endTime  ).toEqual(moment('2013-01-18', 'YYYY-MM-DD').toDate());
 | 
			
		||||
        expect(tasks[1].id         ).toEqual('id2');
 | 
			
		||||
        expect(tasks[1].task).toEqual('test2');
 | 
			
		||||
    var tasks = gDb.getTasks()
 | 
			
		||||
 | 
			
		||||
        expect(tasks[2].id         ).toEqual('id3');
 | 
			
		||||
        expect(tasks[2].task).toEqual('test3');
 | 
			
		||||
        expect(tasks[2].startTime  ).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate());
 | 
			
		||||
        expect(tasks[2].endTime  ).toEqual(moment('2013-01-17', 'YYYY-MM-DD').toDate());
 | 
			
		||||
    });
 | 
			
		||||
    expect(tasks[1].startTime).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate())
 | 
			
		||||
    expect(tasks[1].endTime).toEqual(moment('2013-01-26', 'YYYY-MM-DD').toDate())
 | 
			
		||||
    expect(tasks[1].id).toEqual('task1')
 | 
			
		||||
    expect(tasks[1].task).toEqual('test2')
 | 
			
		||||
  })
 | 
			
		||||
  it('should handle a new task with only an end date as definition', function () {
 | 
			
		||||
    gDb.setDateFormat('YYYY-MM-DD')
 | 
			
		||||
    gDb.addSection('testa1')
 | 
			
		||||
    gDb.addTask('test1', 'id1,2013-01-01,2w')
 | 
			
		||||
    gDb.addTask('test2', '2d')
 | 
			
		||||
 | 
			
		||||
});
 | 
			
		||||
    var tasks = gDb.getTasks()
 | 
			
		||||
 | 
			
		||||
    expect(tasks[1].startTime).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate())
 | 
			
		||||
    expect(tasks[1].endTime).toEqual(moment('2013-01-17', 'YYYY-MM-DD').toDate())
 | 
			
		||||
    expect(tasks[1].id).toEqual('task1')
 | 
			
		||||
    expect(tasks[1].task).toEqual('test2')
 | 
			
		||||
  })
 | 
			
		||||
  it('should handle relative start date based on id regardless of sections', function () {
 | 
			
		||||
    gDb.setDateFormat('YYYY-MM-DD')
 | 
			
		||||
    gDb.addSection('testa1')
 | 
			
		||||
    gDb.addTask('test1', 'id1,2013-01-01,2w')
 | 
			
		||||
    gDb.addTask('test2', 'id2,after id3,1d')
 | 
			
		||||
    gDb.addSection('testa2')
 | 
			
		||||
    gDb.addTask('test3', 'id3,after id1,2d')
 | 
			
		||||
 | 
			
		||||
    var tasks = gDb.getTasks()
 | 
			
		||||
 | 
			
		||||
    expect(tasks[1].startTime).toEqual(moment('2013-01-17', 'YYYY-MM-DD').toDate())
 | 
			
		||||
    expect(tasks[1].endTime).toEqual(moment('2013-01-18', 'YYYY-MM-DD').toDate())
 | 
			
		||||
    expect(tasks[1].id).toEqual('id2')
 | 
			
		||||
    expect(tasks[1].task).toEqual('test2')
 | 
			
		||||
 | 
			
		||||
    expect(tasks[2].id).toEqual('id3')
 | 
			
		||||
    expect(tasks[2].task).toEqual('test3')
 | 
			
		||||
    expect(tasks[2].startTime).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate())
 | 
			
		||||
    expect(tasks[2].endTime).toEqual(moment('2013-01-17', 'YYYY-MM-DD').toDate())
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
// Ogiltigt id i after id
 | 
			
		||||
 
 | 
			
		||||
@@ -1,339 +1,319 @@
 | 
			
		||||
var gantt = require('./parser/gantt').parser;
 | 
			
		||||
gantt.yy = require('./ganttDb');
 | 
			
		||||
var d3 = require('../../d3');
 | 
			
		||||
var moment = require('moment');
 | 
			
		||||
//var log = require('../../logger').create();
 | 
			
		||||
var gantt = require('./parser/gantt').parser
 | 
			
		||||
gantt.yy = require('./ganttDb')
 | 
			
		||||
var d3 = require('../../d3')
 | 
			
		||||
var moment = require('moment')
 | 
			
		||||
// var log = require('../../logger').create();
 | 
			
		||||
 | 
			
		||||
var daysInChart;
 | 
			
		||||
var daysInChart
 | 
			
		||||
var conf = {
 | 
			
		||||
    titleTopMargin: 25,
 | 
			
		||||
    barHeight: 20,
 | 
			
		||||
    barGap: 4,
 | 
			
		||||
    topPadding: 50,
 | 
			
		||||
    rightPadding: 75,
 | 
			
		||||
    leftPadding: 75,
 | 
			
		||||
    gridLineStartPadding: 35,
 | 
			
		||||
    fontSize: 11,
 | 
			
		||||
    fontFamily: '"Open-Sans", "sans-serif"'
 | 
			
		||||
};
 | 
			
		||||
  titleTopMargin: 25,
 | 
			
		||||
  barHeight: 20,
 | 
			
		||||
  barGap: 4,
 | 
			
		||||
  topPadding: 50,
 | 
			
		||||
  rightPadding: 75,
 | 
			
		||||
  leftPadding: 75,
 | 
			
		||||
  gridLineStartPadding: 35,
 | 
			
		||||
  fontSize: 11,
 | 
			
		||||
  fontFamily: '"Open-Sans", "sans-serif"'
 | 
			
		||||
}
 | 
			
		||||
module.exports.setConf = function (cnf) {
 | 
			
		||||
    var keys = Object.keys(cnf);
 | 
			
		||||
  var keys = Object.keys(cnf)
 | 
			
		||||
 | 
			
		||||
    keys.forEach(function (key) {
 | 
			
		||||
        conf[key] = cnf[key];
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
var w;
 | 
			
		||||
  keys.forEach(function (key) {
 | 
			
		||||
    conf[key] = cnf[key]
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
var w
 | 
			
		||||
module.exports.draw = function (text, id) {
 | 
			
		||||
    gantt.yy.clear();
 | 
			
		||||
    gantt.parse(text);
 | 
			
		||||
  gantt.yy.clear()
 | 
			
		||||
  gantt.parse(text)
 | 
			
		||||
 | 
			
		||||
    var elem = document.getElementById(id);
 | 
			
		||||
    w = elem.parentElement.offsetWidth;
 | 
			
		||||
  var elem = document.getElementById(id)
 | 
			
		||||
  w = elem.parentElement.offsetWidth
 | 
			
		||||
 | 
			
		||||
    if (typeof w === 'undefined') {
 | 
			
		||||
        w = 1200;
 | 
			
		||||
    }
 | 
			
		||||
  if (typeof w === 'undefined') {
 | 
			
		||||
    w = 1200
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    if(typeof conf.useWidth !== 'undefined'){
 | 
			
		||||
        w = conf.useWidth;
 | 
			
		||||
    }
 | 
			
		||||
  if (typeof conf.useWidth !== 'undefined') {
 | 
			
		||||
    w = conf.useWidth
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    var taskArray = gantt.yy.getTasks();
 | 
			
		||||
  var taskArray = gantt.yy.getTasks()
 | 
			
		||||
 | 
			
		||||
    // Set height based on number of tasks
 | 
			
		||||
    var h = taskArray.length * (conf.barHeight + conf.barGap) + 2 * conf.topPadding;
 | 
			
		||||
  var h = taskArray.length * (conf.barHeight + conf.barGap) + 2 * conf.topPadding
 | 
			
		||||
 | 
			
		||||
    elem.setAttribute('height', '100%');
 | 
			
		||||
  elem.setAttribute('height', '100%')
 | 
			
		||||
    // Set viewBox
 | 
			
		||||
    elem.setAttribute('viewBox','0 0 '+w+' '+h);
 | 
			
		||||
    var svg = d3.select('#' + id);
 | 
			
		||||
  elem.setAttribute('viewBox', '0 0 ' + w + ' ' + h)
 | 
			
		||||
  var svg = d3.select('#' + id)
 | 
			
		||||
 | 
			
		||||
    // var dateFormat = d3.time.format('%Y-%m-%d');
 | 
			
		||||
 | 
			
		||||
  var startDate = d3.min(taskArray, function (d) {
 | 
			
		||||
    return d.startTime
 | 
			
		||||
  })
 | 
			
		||||
  var endDate = d3.max(taskArray, function (d) {
 | 
			
		||||
    return d.endTime
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    //var dateFormat = d3.time.format('%Y-%m-%d');
 | 
			
		||||
    
 | 
			
		||||
    var startDate = d3.min(taskArray, function (d) {
 | 
			
		||||
        return d.startTime;
 | 
			
		||||
    });
 | 
			
		||||
    var endDate = d3.max(taskArray, function (d) {
 | 
			
		||||
        return d.endTime;
 | 
			
		||||
    });
 | 
			
		||||
    
 | 
			
		||||
    // Set timescale
 | 
			
		||||
    var timeScale = d3.time.scale()
 | 
			
		||||
  var timeScale = d3.time.scale()
 | 
			
		||||
        .domain([d3.min(taskArray, function (d) {
 | 
			
		||||
            return d.startTime;
 | 
			
		||||
          return d.startTime
 | 
			
		||||
        }),
 | 
			
		||||
            d3.max(taskArray, function (d) {
 | 
			
		||||
                return d.endTime;
 | 
			
		||||
            })])
 | 
			
		||||
        .rangeRound([0, w - conf.leftPadding - conf.rightPadding]);
 | 
			
		||||
        //.nice(d3.time.monday);
 | 
			
		||||
          d3.max(taskArray, function (d) {
 | 
			
		||||
            return d.endTime
 | 
			
		||||
          })])
 | 
			
		||||
        .rangeRound([0, w - conf.leftPadding - conf.rightPadding])
 | 
			
		||||
        // .nice(d3.time.monday);
 | 
			
		||||
 | 
			
		||||
    var categories = [];
 | 
			
		||||
    
 | 
			
		||||
    daysInChart = moment.duration(endDate-startDate).asDays();
 | 
			
		||||
  var categories = []
 | 
			
		||||
 | 
			
		||||
    for (var i = 0; i < taskArray.length; i++) {
 | 
			
		||||
        categories.push(taskArray[i].type);
 | 
			
		||||
    }
 | 
			
		||||
  daysInChart = moment.duration(endDate - startDate).asDays()
 | 
			
		||||
 | 
			
		||||
    var catsUnfiltered = categories; //for vert labels
 | 
			
		||||
  for (var i = 0; i < taskArray.length; i++) {
 | 
			
		||||
    categories.push(taskArray[i].type)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    categories = checkUnique(categories);
 | 
			
		||||
  var catsUnfiltered = categories // for vert labels
 | 
			
		||||
 | 
			
		||||
  categories = checkUnique(categories)
 | 
			
		||||
 | 
			
		||||
    makeGant(taskArray, w, h);
 | 
			
		||||
    if(typeof conf.useWidth !== 'undefined'){
 | 
			
		||||
        elem.setAttribute('width', w);
 | 
			
		||||
  makeGant(taskArray, w, h)
 | 
			
		||||
  if (typeof conf.useWidth !== 'undefined') {
 | 
			
		||||
    elem.setAttribute('width', w)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    svg.append('text')
 | 
			
		||||
  svg.append('text')
 | 
			
		||||
        .text(gantt.yy.getTitle())
 | 
			
		||||
        .attr('x', w / 2)
 | 
			
		||||
        .attr('y', conf.titleTopMargin)
 | 
			
		||||
        .attr('class', 'titleText');
 | 
			
		||||
        .attr('class', 'titleText')
 | 
			
		||||
 | 
			
		||||
  function makeGant (tasks, pageWidth, pageHeight) {
 | 
			
		||||
    var barHeight = conf.barHeight
 | 
			
		||||
    var gap = barHeight + conf.barGap
 | 
			
		||||
    var topPadding = conf.topPadding
 | 
			
		||||
    var leftPadding = conf.leftPadding
 | 
			
		||||
 | 
			
		||||
    function makeGant(tasks, pageWidth, pageHeight) {
 | 
			
		||||
 | 
			
		||||
        var barHeight = conf.barHeight;
 | 
			
		||||
        var gap = barHeight + conf.barGap;
 | 
			
		||||
        var topPadding = conf.topPadding;
 | 
			
		||||
        var leftPadding = conf.leftPadding;
 | 
			
		||||
 | 
			
		||||
        var colorScale = d3.scale.linear()
 | 
			
		||||
    var colorScale = d3.scale.linear()
 | 
			
		||||
            .domain([0, categories.length])
 | 
			
		||||
            .range(['#00B9FA', '#F95002'])
 | 
			
		||||
            .interpolate(d3.interpolateHcl);
 | 
			
		||||
            .interpolate(d3.interpolateHcl)
 | 
			
		||||
 | 
			
		||||
        makeGrid(leftPadding, topPadding, pageWidth, pageHeight);
 | 
			
		||||
        drawRects(tasks, gap, topPadding, leftPadding, barHeight, colorScale, pageWidth, pageHeight);
 | 
			
		||||
        vertLabels(gap, topPadding, leftPadding, barHeight, colorScale);
 | 
			
		||||
        drawToday(leftPadding, topPadding, pageWidth, pageHeight);
 | 
			
		||||
    makeGrid(leftPadding, topPadding, pageWidth, pageHeight)
 | 
			
		||||
    drawRects(tasks, gap, topPadding, leftPadding, barHeight, colorScale, pageWidth, pageHeight)
 | 
			
		||||
    vertLabels(gap, topPadding, leftPadding, barHeight, colorScale)
 | 
			
		||||
    drawToday(leftPadding, topPadding, pageWidth, pageHeight)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    function drawRects(theArray, theGap, theTopPad, theSidePad, theBarHeight, theColorScale, w, h) { //eslint-disable-line no-unused-vars
 | 
			
		||||
 | 
			
		||||
        svg.append('g')
 | 
			
		||||
  function drawRects (theArray, theGap, theTopPad, theSidePad, theBarHeight, theColorScale, w, h) { // eslint-disable-line no-unused-vars
 | 
			
		||||
    svg.append('g')
 | 
			
		||||
            .selectAll('rect')
 | 
			
		||||
            .data(theArray)
 | 
			
		||||
            .enter()
 | 
			
		||||
            .append('rect')
 | 
			
		||||
            .attr('x', 0)
 | 
			
		||||
            .attr('y', function (d, i) {
 | 
			
		||||
                return i * theGap + theTopPad - 2;
 | 
			
		||||
              return i * theGap + theTopPad - 2
 | 
			
		||||
            })
 | 
			
		||||
            .attr('width', function () {
 | 
			
		||||
                return w - conf.rightPadding / 2;
 | 
			
		||||
              return w - conf.rightPadding / 2
 | 
			
		||||
            })
 | 
			
		||||
            .attr('height', theGap)
 | 
			
		||||
            .attr('class', function (d) { //eslint-disable-line no-unused-vars
 | 
			
		||||
                for (var i = 0; i < categories.length; i++) {
 | 
			
		||||
                    if (d.type === categories[i]) {
 | 
			
		||||
                        return 'section section' + (i % conf.numberSectionStyles);
 | 
			
		||||
                    }
 | 
			
		||||
            .attr('class', function (d) { // eslint-disable-line no-unused-vars
 | 
			
		||||
              for (var i = 0; i < categories.length; i++) {
 | 
			
		||||
                if (d.type === categories[i]) {
 | 
			
		||||
                  return 'section section' + (i % conf.numberSectionStyles)
 | 
			
		||||
                }
 | 
			
		||||
                return 'section section0';
 | 
			
		||||
            });
 | 
			
		||||
              }
 | 
			
		||||
              return 'section section0'
 | 
			
		||||
            })
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        var rectangles = svg.append('g')
 | 
			
		||||
    var rectangles = svg.append('g')
 | 
			
		||||
            .selectAll('rect')
 | 
			
		||||
            .data(theArray)
 | 
			
		||||
            .enter();
 | 
			
		||||
            .enter()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        rectangles.append('rect')
 | 
			
		||||
    rectangles.append('rect')
 | 
			
		||||
                .attr('rx', 3)
 | 
			
		||||
                .attr('ry', 3)
 | 
			
		||||
                .attr('x', function (d) {
 | 
			
		||||
                    return timeScale(d.startTime) + theSidePad;
 | 
			
		||||
                  return timeScale(d.startTime) + theSidePad
 | 
			
		||||
                })
 | 
			
		||||
                .attr('y', function (d, i) {
 | 
			
		||||
                    return i * theGap + theTopPad;
 | 
			
		||||
                  return i * theGap + theTopPad
 | 
			
		||||
                })
 | 
			
		||||
                .attr('width', function (d) {
 | 
			
		||||
                    return (timeScale(d.endTime) - timeScale(d.startTime));
 | 
			
		||||
                  return (timeScale(d.endTime) - timeScale(d.startTime))
 | 
			
		||||
                })
 | 
			
		||||
                .attr('height', theBarHeight)
 | 
			
		||||
                .attr('class', function (d) {
 | 
			
		||||
                    var res = 'task ';
 | 
			
		||||
                    
 | 
			
		||||
                    
 | 
			
		||||
                    var secNum = 0;
 | 
			
		||||
                    for (var i = 0; i < categories.length; i++) {
 | 
			
		||||
                        if (d.type === categories[i]) {
 | 
			
		||||
                            secNum = (i % conf.numberSectionStyles);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    
 | 
			
		||||
                    if(d.active){
 | 
			
		||||
                        if (d.crit) {
 | 
			
		||||
                            return res + ' activeCrit'+secNum;
 | 
			
		||||
                        }else{
 | 
			
		||||
                            return res + ' active'+secNum;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                  var res = 'task '
 | 
			
		||||
 | 
			
		||||
                    if (d.done) {
 | 
			
		||||
                        if (d.crit) {
 | 
			
		||||
                            return res + ' doneCrit'+secNum;
 | 
			
		||||
                        }else{
 | 
			
		||||
                            return res + ' done'+secNum;
 | 
			
		||||
                        }
 | 
			
		||||
                  var secNum = 0
 | 
			
		||||
                  for (var i = 0; i < categories.length; i++) {
 | 
			
		||||
                    if (d.type === categories[i]) {
 | 
			
		||||
                      secNum = (i % conf.numberSectionStyles)
 | 
			
		||||
                    }
 | 
			
		||||
                  }
 | 
			
		||||
 | 
			
		||||
                  if (d.active) {
 | 
			
		||||
                    if (d.crit) {
 | 
			
		||||
                        return res + ' crit'+secNum;
 | 
			
		||||
                      return res + ' activeCrit' + secNum
 | 
			
		||||
                    } else {
 | 
			
		||||
                      return res + ' active' + secNum
 | 
			
		||||
                    }
 | 
			
		||||
                  }
 | 
			
		||||
 | 
			
		||||
                  if (d.done) {
 | 
			
		||||
                    if (d.crit) {
 | 
			
		||||
                      return res + ' doneCrit' + secNum
 | 
			
		||||
                    } else {
 | 
			
		||||
                      return res + ' done' + secNum
 | 
			
		||||
                    }
 | 
			
		||||
                  }
 | 
			
		||||
 | 
			
		||||
                    return res + ' task'+secNum;
 | 
			
		||||
                  if (d.crit) {
 | 
			
		||||
                    return res + ' crit' + secNum
 | 
			
		||||
                  }
 | 
			
		||||
 | 
			
		||||
                  return res + ' task' + secNum
 | 
			
		||||
                })
 | 
			
		||||
            ;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        rectangles.append('text')
 | 
			
		||||
    rectangles.append('text')
 | 
			
		||||
            .text(function (d) {
 | 
			
		||||
                return d.task;
 | 
			
		||||
              return d.task
 | 
			
		||||
            })
 | 
			
		||||
            .attr('font-size',conf.fontSize)
 | 
			
		||||
            //.attr('font-family',conf.fontFamily)
 | 
			
		||||
            .attr('font-size', conf.fontSize)
 | 
			
		||||
            // .attr('font-family',conf.fontFamily)
 | 
			
		||||
            .attr('x', function (d) {
 | 
			
		||||
                var startX = timeScale(d.startTime),
 | 
			
		||||
                    endX = timeScale(d.endTime),
 | 
			
		||||
                    textWidth = this.getBBox().width;
 | 
			
		||||
              var startX = timeScale(d.startTime),
 | 
			
		||||
                endX = timeScale(d.endTime),
 | 
			
		||||
                textWidth = this.getBBox().width
 | 
			
		||||
 | 
			
		||||
                // Check id text width > width of rectangle
 | 
			
		||||
                if (textWidth > (endX - startX)) {
 | 
			
		||||
                    if (endX + textWidth  + 1.5*conf.leftPadding> w) {
 | 
			
		||||
                        return startX + theSidePad - 5;
 | 
			
		||||
                    } else {
 | 
			
		||||
                        return endX + theSidePad + 5;
 | 
			
		||||
                    }
 | 
			
		||||
              if (textWidth > (endX - startX)) {
 | 
			
		||||
                if (endX + textWidth + 1.5 * conf.leftPadding > w) {
 | 
			
		||||
                  return startX + theSidePad - 5
 | 
			
		||||
                } else {
 | 
			
		||||
                    return (endX - startX) / 2 + startX + theSidePad;
 | 
			
		||||
                  return endX + theSidePad + 5
 | 
			
		||||
                }
 | 
			
		||||
              } else {
 | 
			
		||||
                return (endX - startX) / 2 + startX + theSidePad
 | 
			
		||||
              }
 | 
			
		||||
            })
 | 
			
		||||
            .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-anchor', 'middle')
 | 
			
		||||
            .attr('text-height', theBarHeight)
 | 
			
		||||
            .attr('class', function (d) {
 | 
			
		||||
                var startX = timeScale(d.startTime),
 | 
			
		||||
                    endX = timeScale(d.endTime),
 | 
			
		||||
                    textWidth = this.getBBox().width;
 | 
			
		||||
                var secNum = 0;
 | 
			
		||||
                for (var i = 0; i < categories.length; i++) {
 | 
			
		||||
                    if (d.type === categories[i]) {
 | 
			
		||||
                        secNum = (i % conf.numberSectionStyles);
 | 
			
		||||
                    }
 | 
			
		||||
              var startX = timeScale(d.startTime),
 | 
			
		||||
                endX = timeScale(d.endTime),
 | 
			
		||||
                textWidth = this.getBBox().width
 | 
			
		||||
              var secNum = 0
 | 
			
		||||
              for (var i = 0; i < categories.length; i++) {
 | 
			
		||||
                if (d.type === categories[i]) {
 | 
			
		||||
                  secNum = (i % conf.numberSectionStyles)
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
                var taskType = '';
 | 
			
		||||
                if(d.active){
 | 
			
		||||
                    if (d.crit) {
 | 
			
		||||
                        taskType = 'activeCritText'+secNum;
 | 
			
		||||
                    }else{
 | 
			
		||||
                        taskType = 'activeText'+secNum;
 | 
			
		||||
                    }
 | 
			
		||||
              var taskType = ''
 | 
			
		||||
              if (d.active) {
 | 
			
		||||
                if (d.crit) {
 | 
			
		||||
                  taskType = 'activeCritText' + secNum
 | 
			
		||||
                } else {
 | 
			
		||||
                  taskType = 'activeText' + secNum
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
                if (d.done) {
 | 
			
		||||
                    if (d.crit) {
 | 
			
		||||
                        taskType = taskType + ' doneCritText'+secNum;
 | 
			
		||||
                    }else{
 | 
			
		||||
                        taskType = taskType + ' doneText'+secNum;
 | 
			
		||||
                    }
 | 
			
		||||
                }else{
 | 
			
		||||
                    if (d.crit) {
 | 
			
		||||
                        taskType = taskType + ' critText'+secNum;
 | 
			
		||||
                    }
 | 
			
		||||
              if (d.done) {
 | 
			
		||||
                if (d.crit) {
 | 
			
		||||
                  taskType = taskType + ' doneCritText' + secNum
 | 
			
		||||
                } else {
 | 
			
		||||
                  taskType = taskType + ' doneText' + secNum
 | 
			
		||||
                }
 | 
			
		||||
              } else {
 | 
			
		||||
                if (d.crit) {
 | 
			
		||||
                  taskType = taskType + ' critText' + secNum
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
                // Check id text width > width of rectangle
 | 
			
		||||
                if (textWidth > (endX - startX)) {
 | 
			
		||||
                    if (endX + textWidth + 1.5*conf.leftPadding > w) {
 | 
			
		||||
                        return 'taskTextOutsideLeft taskTextOutside' + secNum + ' ' + taskType;
 | 
			
		||||
                    } else {
 | 
			
		||||
                        return 'taskTextOutsideRight taskTextOutside' + secNum+ ' ' + taskType;
 | 
			
		||||
                    }
 | 
			
		||||
              if (textWidth > (endX - startX)) {
 | 
			
		||||
                if (endX + textWidth + 1.5 * conf.leftPadding > w) {
 | 
			
		||||
                  return 'taskTextOutsideLeft taskTextOutside' + secNum + ' ' + taskType
 | 
			
		||||
                } else {
 | 
			
		||||
                    return 'taskText taskText' + secNum+ ' ' + taskType;
 | 
			
		||||
                  return 'taskTextOutsideRight taskTextOutside' + secNum + ' ' + taskType
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
              } else {
 | 
			
		||||
                return 'taskText taskText' + secNum + ' ' + taskType
 | 
			
		||||
              }
 | 
			
		||||
            })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    function makeGrid(theSidePad, theTopPad, w, h) {
 | 
			
		||||
 | 
			
		||||
        var pre = [
 | 
			
		||||
            ['.%L', function (d) {
 | 
			
		||||
                return d.getMilliseconds();
 | 
			
		||||
            }],
 | 
			
		||||
            [':%S', function (d) {
 | 
			
		||||
                return d.getSeconds();
 | 
			
		||||
            }],
 | 
			
		||||
  function makeGrid (theSidePad, theTopPad, w, h) {
 | 
			
		||||
    var pre = [
 | 
			
		||||
      ['.%L', function (d) {
 | 
			
		||||
        return d.getMilliseconds()
 | 
			
		||||
      }],
 | 
			
		||||
      [':%S', function (d) {
 | 
			
		||||
        return d.getSeconds()
 | 
			
		||||
      }],
 | 
			
		||||
            // Within a hour
 | 
			
		||||
            ['h1 %I:%M', function (d) {
 | 
			
		||||
                return d.getMinutes();
 | 
			
		||||
            }]];
 | 
			
		||||
        var post = [
 | 
			
		||||
            ['%Y', function () {
 | 
			
		||||
                return true;
 | 
			
		||||
            }]];
 | 
			
		||||
        
 | 
			
		||||
        var mid = [                    
 | 
			
		||||
            // Within a day
 | 
			
		||||
            ['%I:%M', function (d) {
 | 
			
		||||
                return d.getHours();
 | 
			
		||||
            }],
 | 
			
		||||
            // Day within a week (not monday)
 | 
			
		||||
            ['%a %d', function (d) {
 | 
			
		||||
                //return d.getDay() ==1;
 | 
			
		||||
                return d.getDay() && d.getDate() != 1;
 | 
			
		||||
            }],
 | 
			
		||||
            // within a month
 | 
			
		||||
            ['%b %d', function (d) {
 | 
			
		||||
                return d.getDate() != 1;
 | 
			
		||||
            }],
 | 
			
		||||
            // Month
 | 
			
		||||
            ['%B', function (d) {
 | 
			
		||||
                return d.getMonth();
 | 
			
		||||
            }]
 | 
			
		||||
        ];
 | 
			
		||||
        var formatter;
 | 
			
		||||
        if(typeof conf.axisFormatter !== 'undefined'){
 | 
			
		||||
            mid = [];
 | 
			
		||||
            conf.axisFormatter.forEach(function(item){
 | 
			
		||||
                var n = [];
 | 
			
		||||
                n[0] = item[0];
 | 
			
		||||
                n[1] = item[1];
 | 
			
		||||
                mid.push(n);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        formatter = pre.concat(mid).concat(post);
 | 
			
		||||
      ['h1 %I:%M', function (d) {
 | 
			
		||||
        return d.getMinutes()
 | 
			
		||||
      }]]
 | 
			
		||||
    var post = [
 | 
			
		||||
      ['%Y', function () {
 | 
			
		||||
        return true
 | 
			
		||||
      }]]
 | 
			
		||||
 | 
			
		||||
        var xAxis = d3.svg.axis()
 | 
			
		||||
    var mid = [
 | 
			
		||||
            // Within a day
 | 
			
		||||
      ['%I:%M', function (d) {
 | 
			
		||||
        return d.getHours()
 | 
			
		||||
      }],
 | 
			
		||||
            // Day within a week (not monday)
 | 
			
		||||
      ['%a %d', function (d) {
 | 
			
		||||
                // return d.getDay() ==1;
 | 
			
		||||
        return d.getDay() && d.getDate() != 1
 | 
			
		||||
      }],
 | 
			
		||||
            // within a month
 | 
			
		||||
      ['%b %d', function (d) {
 | 
			
		||||
        return d.getDate() != 1
 | 
			
		||||
      }],
 | 
			
		||||
            // Month
 | 
			
		||||
      ['%B', function (d) {
 | 
			
		||||
        return d.getMonth()
 | 
			
		||||
      }]
 | 
			
		||||
    ]
 | 
			
		||||
    var formatter
 | 
			
		||||
    if (typeof conf.axisFormatter !== 'undefined') {
 | 
			
		||||
      mid = []
 | 
			
		||||
      conf.axisFormatter.forEach(function (item) {
 | 
			
		||||
        var n = []
 | 
			
		||||
        n[0] = item[0]
 | 
			
		||||
        n[1] = item[1]
 | 
			
		||||
        mid.push(n)
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
    formatter = pre.concat(mid).concat(post)
 | 
			
		||||
 | 
			
		||||
    var xAxis = d3.svg.axis()
 | 
			
		||||
                .scale(timeScale)
 | 
			
		||||
                .orient('bottom')
 | 
			
		||||
                .tickSize(-h + theTopPad + conf.gridLineStartPadding, 0, 0)
 | 
			
		||||
                .tickFormat(d3.time.format.multi(formatter))
 | 
			
		||||
            ;
 | 
			
		||||
 | 
			
		||||
        if(daysInChart >7 && daysInChart<230){
 | 
			
		||||
            xAxis = xAxis.ticks(d3.time.monday.range);
 | 
			
		||||
        }
 | 
			
		||||
    if (daysInChart > 7 && daysInChart < 230) {
 | 
			
		||||
      xAxis = xAxis.ticks(d3.time.monday.range)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        svg.append('g')
 | 
			
		||||
    svg.append('g')
 | 
			
		||||
            .attr('class', 'grid')
 | 
			
		||||
            .attr('transform', 'translate(' + theSidePad + ', ' + (h - 50) + ')')
 | 
			
		||||
            .call(xAxis)
 | 
			
		||||
@@ -342,87 +322,85 @@ module.exports.draw = function (text, id) {
 | 
			
		||||
            .attr('fill', '#000')
 | 
			
		||||
            .attr('stroke', 'none')
 | 
			
		||||
            .attr('font-size', 10)
 | 
			
		||||
            .attr('dy', '1em');
 | 
			
		||||
            .attr('dy', '1em')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function vertLabels (theGap, theTopPad) {
 | 
			
		||||
    var numOccurances = []
 | 
			
		||||
    var prevGap = 0
 | 
			
		||||
 | 
			
		||||
    for (var i = 0; i < categories.length; i++) {
 | 
			
		||||
      numOccurances[i] = [categories[i], getCount(categories[i], catsUnfiltered)]
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function vertLabels(theGap, theTopPad) {
 | 
			
		||||
        var numOccurances = [];
 | 
			
		||||
        var prevGap = 0;
 | 
			
		||||
 | 
			
		||||
        for (var i = 0; i < categories.length; i++) {
 | 
			
		||||
            numOccurances[i] = [categories[i], getCount(categories[i], catsUnfiltered)];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        svg.append('g') //without doing this, impossible to put grid lines behind text
 | 
			
		||||
    svg.append('g') // without doing this, impossible to put grid lines behind text
 | 
			
		||||
            .selectAll('text')
 | 
			
		||||
            .data(numOccurances)
 | 
			
		||||
            .enter()
 | 
			
		||||
            .append('text')
 | 
			
		||||
            .text(function (d) {
 | 
			
		||||
                return d[0];
 | 
			
		||||
              return d[0]
 | 
			
		||||
            })
 | 
			
		||||
            .attr('x', 10)
 | 
			
		||||
            .attr('y', function (d, i) {
 | 
			
		||||
                if (i > 0) {
 | 
			
		||||
                    for (var j = 0; j < i; j++) {
 | 
			
		||||
                        prevGap += numOccurances[i - 1][1];
 | 
			
		||||
              if (i > 0) {
 | 
			
		||||
                for (var j = 0; j < i; j++) {
 | 
			
		||||
                  prevGap += numOccurances[i - 1][1]
 | 
			
		||||
                        // log.debug(prevGap);
 | 
			
		||||
                        return d[1] * theGap / 2 + prevGap * theGap + theTopPad;
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    return d[1] * theGap / 2 + theTopPad;
 | 
			
		||||
                  return d[1] * theGap / 2 + prevGap * theGap + theTopPad
 | 
			
		||||
                }
 | 
			
		||||
              } else {
 | 
			
		||||
                return d[1] * theGap / 2 + theTopPad
 | 
			
		||||
              }
 | 
			
		||||
            })
 | 
			
		||||
            .attr('class', function (d) {
 | 
			
		||||
                for (var i = 0; i < categories.length; i++) {
 | 
			
		||||
                    if (d[0] === categories[i]) {
 | 
			
		||||
                        return 'sectionTitle sectionTitle' + (i % conf.numberSectionStyles);
 | 
			
		||||
                    }
 | 
			
		||||
              for (var i = 0; i < categories.length; i++) {
 | 
			
		||||
                if (d[0] === categories[i]) {
 | 
			
		||||
                  return 'sectionTitle sectionTitle' + (i % conf.numberSectionStyles)
 | 
			
		||||
                }
 | 
			
		||||
                return 'sectionTitle';
 | 
			
		||||
            });
 | 
			
		||||
              }
 | 
			
		||||
              return 'sectionTitle'
 | 
			
		||||
            })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
  function drawToday (theSidePad, theTopPad, w, h) {
 | 
			
		||||
    var todayG = svg.append('g')
 | 
			
		||||
            .attr('class', 'today')
 | 
			
		||||
 | 
			
		||||
    function drawToday(theSidePad, theTopPad, w, h) {
 | 
			
		||||
        var todayG = svg.append('g')
 | 
			
		||||
            .attr('class', 'today');
 | 
			
		||||
    var today = new Date()
 | 
			
		||||
 | 
			
		||||
        var today = new Date();
 | 
			
		||||
 | 
			
		||||
        todayG.append('line')
 | 
			
		||||
    todayG.append('line')
 | 
			
		||||
                .attr('x1', timeScale(today) + theSidePad)
 | 
			
		||||
                .attr('x2', timeScale(today) + theSidePad)
 | 
			
		||||
                .attr('y1', conf.titleTopMargin)
 | 
			
		||||
                .attr('y2', h-conf.titleTopMargin)
 | 
			
		||||
                .attr('y2', h - conf.titleTopMargin)
 | 
			
		||||
                .attr('class', 'today')
 | 
			
		||||
            ;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
//from this stackexchange question: http://stackoverflow.com/questions/1890203/unique-for-arrays-in-javascript
 | 
			
		||||
    function checkUnique(arr) {
 | 
			
		||||
        var hash = {}, result = [];
 | 
			
		||||
        for (var i = 0, l = arr.length; i < l; ++i) {
 | 
			
		||||
            if (!hash.hasOwnProperty(arr[i])) { //it works with objects! in FF, at least
 | 
			
		||||
                hash[arr[i]] = true;
 | 
			
		||||
                result.push(arr[i]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return result;
 | 
			
		||||
// from this stackexchange question: http://stackoverflow.com/questions/1890203/unique-for-arrays-in-javascript
 | 
			
		||||
  function checkUnique (arr) {
 | 
			
		||||
    var hash = {}, result = []
 | 
			
		||||
    for (var i = 0, l = arr.length; i < l; ++i) {
 | 
			
		||||
      if (!hash.hasOwnProperty(arr[i])) { // it works with objects! in FF, at least
 | 
			
		||||
        hash[arr[i]] = true
 | 
			
		||||
        result.push(arr[i])
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return result
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
//from this stackexchange question: http://stackoverflow.com/questions/14227981/count-how-many-strings-in-an-array-have-duplicates-in-the-same-array
 | 
			
		||||
    function getCounts(arr) {
 | 
			
		||||
        var i = arr.length, // var to loop over
 | 
			
		||||
            obj = {}; // obj to store results
 | 
			
		||||
        while (i) {
 | 
			
		||||
            obj[arr[--i]] = (obj[arr[i]] || 0) + 1; // count occurrences
 | 
			
		||||
        }
 | 
			
		||||
        return obj;
 | 
			
		||||
// from this stackexchange question: http://stackoverflow.com/questions/14227981/count-how-many-strings-in-an-array-have-duplicates-in-the-same-array
 | 
			
		||||
  function getCounts (arr) {
 | 
			
		||||
    var i = arr.length, // var to loop over
 | 
			
		||||
      obj = {} // obj to store results
 | 
			
		||||
    while (i) {
 | 
			
		||||
      obj[arr[--i]] = (obj[arr[i]] || 0) + 1 // count occurrences
 | 
			
		||||
    }
 | 
			
		||||
    return obj
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
// get specific from everything
 | 
			
		||||
    function getCount(word, arr) {
 | 
			
		||||
        return getCounts(arr)[word] || 0;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
  function getCount (word, arr) {
 | 
			
		||||
    return getCounts(arr)[word] || 0
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,214 +1,211 @@
 | 
			
		||||
var Logger = require('../../logger');
 | 
			
		||||
var log = Logger.Log;
 | 
			
		||||
var _ = require('lodash');
 | 
			
		||||
var Logger = require('../../logger')
 | 
			
		||||
var log = Logger.Log
 | 
			
		||||
var _ = require('lodash')
 | 
			
		||||
 | 
			
		||||
var commits = {}
 | 
			
		||||
var head = null
 | 
			
		||||
var branches = { 'master': head }
 | 
			
		||||
var curBranch = 'master'
 | 
			
		||||
var direction = 'LR'
 | 
			
		||||
var seq = 0
 | 
			
		||||
 | 
			
		||||
var commits = {};
 | 
			
		||||
var head  = null;
 | 
			
		||||
var branches = { 'master' : head };
 | 
			
		||||
var curBranch = 'master';
 | 
			
		||||
var direction = 'LR';
 | 
			
		||||
var seq = 0;
 | 
			
		||||
 | 
			
		||||
function getRandomInt(min, max) {
 | 
			
		||||
  return Math.floor(Math.random() * (max - min)) + min;
 | 
			
		||||
function getRandomInt (min, max) {
 | 
			
		||||
  return Math.floor(Math.random() * (max - min)) + min
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getId() {
 | 
			
		||||
    var pool='0123456789abcdef';
 | 
			
		||||
    var id = '';
 | 
			
		||||
    for (var i = 0; i < 7; i++) {
 | 
			
		||||
        id += pool[getRandomInt(0,16)]
 | 
			
		||||
    }
 | 
			
		||||
    return id;
 | 
			
		||||
function getId () {
 | 
			
		||||
  var pool = '0123456789abcdef'
 | 
			
		||||
  var id = ''
 | 
			
		||||
  for (var i = 0; i < 7; i++) {
 | 
			
		||||
    id += pool[getRandomInt(0, 16)]
 | 
			
		||||
  }
 | 
			
		||||
  return id
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function isfastforwardable(currentCommit, otherCommit) {
 | 
			
		||||
    log.debug('Entering isfastforwardable:', currentCommit.id, otherCommit.id);
 | 
			
		||||
    while (currentCommit.seq <= otherCommit.seq && currentCommit != otherCommit) {
 | 
			
		||||
function isfastforwardable (currentCommit, otherCommit) {
 | 
			
		||||
  log.debug('Entering isfastforwardable:', currentCommit.id, otherCommit.id)
 | 
			
		||||
  while (currentCommit.seq <= otherCommit.seq && currentCommit != otherCommit) {
 | 
			
		||||
        // only if other branch has more commits
 | 
			
		||||
        if (otherCommit.parent == null) break;
 | 
			
		||||
        if (Array.isArray(otherCommit.parent)){
 | 
			
		||||
            log.debug('In merge commit:', otherCommit.parent);
 | 
			
		||||
            return isfastforwardable(currentCommit, commits[otherCommit.parent[0]]) ||
 | 
			
		||||
    if (otherCommit.parent == null) break
 | 
			
		||||
    if (Array.isArray(otherCommit.parent)) {
 | 
			
		||||
      log.debug('In merge commit:', otherCommit.parent)
 | 
			
		||||
      return isfastforwardable(currentCommit, commits[otherCommit.parent[0]]) ||
 | 
			
		||||
                    isfastforwardable(currentCommit, commits[otherCommit.parent[1]])
 | 
			
		||||
        } else {
 | 
			
		||||
            otherCommit = commits[otherCommit.parent];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    log.debug(currentCommit.id, otherCommit.id);
 | 
			
		||||
    return currentCommit.id == otherCommit.id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function isReachableFrom(currentCommit, otherCommit) {
 | 
			
		||||
    var currentSeq = currentCommit.seq;
 | 
			
		||||
    var otherSeq = otherCommit.seq;
 | 
			
		||||
    if (currentSeq > otherSeq) return isfastforwardable(otherCommit, currentCommit);
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.setDirection = function(dir) {
 | 
			
		||||
    direction = dir;
 | 
			
		||||
}
 | 
			
		||||
var options = {};
 | 
			
		||||
exports.setOptions = function(rawOptString) {
 | 
			
		||||
    log.debug('options str', rawOptString);
 | 
			
		||||
    rawOptString = rawOptString && rawOptString.trim();
 | 
			
		||||
    rawOptString = rawOptString || '{}';
 | 
			
		||||
    try {
 | 
			
		||||
        options = JSON.parse(rawOptString)
 | 
			
		||||
    } catch(e) {
 | 
			
		||||
        log.error('error while parsing gitGraph options', e.message);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.getOptions = function() {
 | 
			
		||||
    return options;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.commit = function(msg) {
 | 
			
		||||
    var commit = { id: getId(),
 | 
			
		||||
        message: msg,
 | 
			
		||||
        seq: seq++,
 | 
			
		||||
        parent:  head == null ? null : head.id};
 | 
			
		||||
    head = commit;
 | 
			
		||||
    commits[commit.id] = commit;
 | 
			
		||||
    branches[curBranch] = commit.id;
 | 
			
		||||
    log.debug('in pushCommit ' + commit.id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.branch = function(name) {
 | 
			
		||||
    branches[name] = head != null ? head.id: null;
 | 
			
		||||
    log.debug('in createBranch');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.merge = function(otherBranch) {
 | 
			
		||||
    var currentCommit = commits[branches[curBranch]];
 | 
			
		||||
    var otherCommit = commits[branches[otherBranch]];
 | 
			
		||||
    if (isReachableFrom(currentCommit, otherCommit)) {
 | 
			
		||||
        log.debug('Already merged');
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (isfastforwardable(currentCommit, otherCommit)){
 | 
			
		||||
        branches[curBranch] = branches[otherBranch];
 | 
			
		||||
        head = commits[branches[curBranch]];
 | 
			
		||||
    } else {
 | 
			
		||||
      otherCommit = commits[otherCommit.parent]
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  log.debug(currentCommit.id, otherCommit.id)
 | 
			
		||||
  return currentCommit.id == otherCommit.id
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function isReachableFrom (currentCommit, otherCommit) {
 | 
			
		||||
  var currentSeq = currentCommit.seq
 | 
			
		||||
  var otherSeq = otherCommit.seq
 | 
			
		||||
  if (currentSeq > otherSeq) return isfastforwardable(otherCommit, currentCommit)
 | 
			
		||||
  return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.setDirection = function (dir) {
 | 
			
		||||
  direction = dir
 | 
			
		||||
}
 | 
			
		||||
var options = {}
 | 
			
		||||
exports.setOptions = function (rawOptString) {
 | 
			
		||||
  log.debug('options str', rawOptString)
 | 
			
		||||
  rawOptString = rawOptString && rawOptString.trim()
 | 
			
		||||
  rawOptString = rawOptString || '{}'
 | 
			
		||||
  try {
 | 
			
		||||
    options = JSON.parse(rawOptString)
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    log.error('error while parsing gitGraph options', e.message)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.getOptions = function () {
 | 
			
		||||
  return options
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.commit = function (msg) {
 | 
			
		||||
  var commit = { id: getId(),
 | 
			
		||||
    message: msg,
 | 
			
		||||
    seq: seq++,
 | 
			
		||||
    parent: head == null ? null : head.id}
 | 
			
		||||
  head = commit
 | 
			
		||||
  commits[commit.id] = commit
 | 
			
		||||
  branches[curBranch] = commit.id
 | 
			
		||||
  log.debug('in pushCommit ' + commit.id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.branch = function (name) {
 | 
			
		||||
  branches[name] = head != null ? head.id : null
 | 
			
		||||
  log.debug('in createBranch')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.merge = function (otherBranch) {
 | 
			
		||||
  var currentCommit = commits[branches[curBranch]]
 | 
			
		||||
  var otherCommit = commits[branches[otherBranch]]
 | 
			
		||||
  if (isReachableFrom(currentCommit, otherCommit)) {
 | 
			
		||||
    log.debug('Already merged')
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
  if (isfastforwardable(currentCommit, otherCommit)) {
 | 
			
		||||
    branches[curBranch] = branches[otherBranch]
 | 
			
		||||
    head = commits[branches[curBranch]]
 | 
			
		||||
  } else {
 | 
			
		||||
        // create merge commit
 | 
			
		||||
        var commit = {
 | 
			
		||||
            id: getId(),
 | 
			
		||||
            message: 'merged branch ' + otherBranch + ' into ' + curBranch,
 | 
			
		||||
            seq: seq++,
 | 
			
		||||
            parent:  [head == null ? null : head.id, branches[otherBranch]]
 | 
			
		||||
        };
 | 
			
		||||
        head = commit;
 | 
			
		||||
        commits[commit.id] = commit;
 | 
			
		||||
        branches[curBranch] = commit.id;
 | 
			
		||||
    var commit = {
 | 
			
		||||
      id: getId(),
 | 
			
		||||
      message: 'merged branch ' + otherBranch + ' into ' + curBranch,
 | 
			
		||||
      seq: seq++,
 | 
			
		||||
      parent: [head == null ? null : head.id, branches[otherBranch]]
 | 
			
		||||
    }
 | 
			
		||||
    log.debug(branches);
 | 
			
		||||
    log.debug('in mergeBranch');
 | 
			
		||||
    head = commit
 | 
			
		||||
    commits[commit.id] = commit
 | 
			
		||||
    branches[curBranch] = commit.id
 | 
			
		||||
  }
 | 
			
		||||
  log.debug(branches)
 | 
			
		||||
  log.debug('in mergeBranch')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.checkout = function(branch) {
 | 
			
		||||
    log.debug('in checkout');
 | 
			
		||||
    curBranch = branch;
 | 
			
		||||
    var id = branches[curBranch];
 | 
			
		||||
    head = commits[id];
 | 
			
		||||
exports.checkout = function (branch) {
 | 
			
		||||
  log.debug('in checkout')
 | 
			
		||||
  curBranch = branch
 | 
			
		||||
  var id = branches[curBranch]
 | 
			
		||||
  head = commits[id]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.reset = function(commitRef) {
 | 
			
		||||
    log.debug('in reset', commitRef);
 | 
			
		||||
    var ref = commitRef.split(':')[0];
 | 
			
		||||
    var parentCount = parseInt(commitRef.split(':')[1]);
 | 
			
		||||
    var commit = ref == 'HEAD' ? head : commits[branches[ref]];
 | 
			
		||||
    log.debug(commit, parentCount);
 | 
			
		||||
    while (parentCount > 0) {
 | 
			
		||||
        commit = commits[commit.parent];
 | 
			
		||||
        parentCount--;
 | 
			
		||||
        if (!commit) {
 | 
			
		||||
            var err = 'Critical error - unique parent commit not found during reset';
 | 
			
		||||
            log.error(err);
 | 
			
		||||
            throw err;
 | 
			
		||||
        }
 | 
			
		||||
exports.reset = function (commitRef) {
 | 
			
		||||
  log.debug('in reset', commitRef)
 | 
			
		||||
  var ref = commitRef.split(':')[0]
 | 
			
		||||
  var parentCount = parseInt(commitRef.split(':')[1])
 | 
			
		||||
  var commit = ref == 'HEAD' ? head : commits[branches[ref]]
 | 
			
		||||
  log.debug(commit, parentCount)
 | 
			
		||||
  while (parentCount > 0) {
 | 
			
		||||
    commit = commits[commit.parent]
 | 
			
		||||
    parentCount--
 | 
			
		||||
    if (!commit) {
 | 
			
		||||
      var err = 'Critical error - unique parent commit not found during reset'
 | 
			
		||||
      log.error(err)
 | 
			
		||||
      throw err
 | 
			
		||||
    }
 | 
			
		||||
    head = commit;
 | 
			
		||||
    branches[curBranch] = commit.id;
 | 
			
		||||
  }
 | 
			
		||||
  head = commit
 | 
			
		||||
  branches[curBranch] = commit.id
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function upsert(arr, key, newval) {
 | 
			
		||||
    var match = _.find(arr, key);
 | 
			
		||||
    if(match){
 | 
			
		||||
        var index = _.indexOf(arr, _.find(arr, key));
 | 
			
		||||
        arr.splice(index, 1, newval);
 | 
			
		||||
function upsert (arr, key, newval) {
 | 
			
		||||
  var match = _.find(arr, key)
 | 
			
		||||
  if (match) {
 | 
			
		||||
    var index = _.indexOf(arr, _.find(arr, key))
 | 
			
		||||
    arr.splice(index, 1, newval)
 | 
			
		||||
  } else {
 | 
			
		||||
    arr.push(newval)
 | 
			
		||||
  }
 | 
			
		||||
    // console.log(arr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function prettyPrintCommitHistory (commitArr) {
 | 
			
		||||
  var commit = _.maxBy(commitArr, 'seq')
 | 
			
		||||
  var line = ''
 | 
			
		||||
  _.each(commitArr, function (c) {
 | 
			
		||||
    if (c == commit) {
 | 
			
		||||
      line += '\t*'
 | 
			
		||||
    } else {
 | 
			
		||||
        arr.push(newval);
 | 
			
		||||
      line += '\t|'
 | 
			
		||||
    }
 | 
			
		||||
    //console.log(arr);
 | 
			
		||||
  })
 | 
			
		||||
  var label = [line, commit.id, commit.seq]
 | 
			
		||||
  _.each(branches, function (v, k) {
 | 
			
		||||
    if (v == commit.id) label.push(k)
 | 
			
		||||
  })
 | 
			
		||||
  log.debug(label.join(' '))
 | 
			
		||||
  if (Array.isArray(commit.parent)) {
 | 
			
		||||
        // console.log("here", commit.parent);
 | 
			
		||||
    var newCommit = commits[commit.parent[0]]
 | 
			
		||||
    upsert(commitArr, commit, newCommit)
 | 
			
		||||
    commitArr.push(commits[commit.parent[1]])
 | 
			
		||||
        // console.log("shoudl have 2", commitArr);
 | 
			
		||||
  } else if (commit.parent == null) {
 | 
			
		||||
    return
 | 
			
		||||
  } else {
 | 
			
		||||
    var nextCommit = commits[commit.parent]
 | 
			
		||||
    upsert(commitArr, commit, nextCommit)
 | 
			
		||||
  }
 | 
			
		||||
  commitArr = _.uniqBy(commitArr, 'id')
 | 
			
		||||
  prettyPrintCommitHistory(commitArr)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function prettyPrintCommitHistory(commitArr) {
 | 
			
		||||
    var commit = _.maxBy(commitArr, 'seq');
 | 
			
		||||
    var line = '';
 | 
			
		||||
    _.each(commitArr, function(c) {
 | 
			
		||||
        if (c == commit) {
 | 
			
		||||
            line += '\t*'
 | 
			
		||||
        } else {
 | 
			
		||||
            line +='\t|'
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
    var label = [line, commit.id, commit.seq];
 | 
			
		||||
    _.each(branches, function(v,k){
 | 
			
		||||
        if (v == commit.id) label.push(k);
 | 
			
		||||
    });
 | 
			
		||||
    log.debug(label.join(' '));
 | 
			
		||||
    if (Array.isArray(commit.parent)) {
 | 
			
		||||
        //console.log("here", commit.parent);
 | 
			
		||||
        var newCommit = commits[commit.parent[0]];
 | 
			
		||||
        upsert(commitArr, commit, newCommit);
 | 
			
		||||
        commitArr.push(commits[commit.parent[1]]);
 | 
			
		||||
        //console.log("shoudl have 2", commitArr);
 | 
			
		||||
    } else if(commit.parent == null){
 | 
			
		||||
        return;
 | 
			
		||||
    } else {
 | 
			
		||||
        var nextCommit = commits[commit.parent];
 | 
			
		||||
        upsert(commitArr, commit, nextCommit);
 | 
			
		||||
    }
 | 
			
		||||
    commitArr = _.uniqBy(commitArr, 'id');
 | 
			
		||||
    prettyPrintCommitHistory(commitArr);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.prettyPrint = function() {
 | 
			
		||||
    log.debug(commits);
 | 
			
		||||
    var node = exports.getCommitsArray()[0];
 | 
			
		||||
    prettyPrintCommitHistory([node]);
 | 
			
		||||
exports.prettyPrint = function () {
 | 
			
		||||
  log.debug(commits)
 | 
			
		||||
  var node = exports.getCommitsArray()[0]
 | 
			
		||||
  prettyPrintCommitHistory([node])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.clear = function () {
 | 
			
		||||
    commits = {};
 | 
			
		||||
    head  = null;
 | 
			
		||||
    branches = { 'master' : head };
 | 
			
		||||
    curBranch = 'master';
 | 
			
		||||
    seq =0;
 | 
			
		||||
  commits = {}
 | 
			
		||||
  head = null
 | 
			
		||||
  branches = { 'master': head }
 | 
			
		||||
  curBranch = 'master'
 | 
			
		||||
  seq = 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.getBranchesAsObjArray = function() {
 | 
			
		||||
    var branchArr = _.map(branches, function(v,k) {
 | 
			
		||||
        return {'name': k, 'commit': commits[v]};
 | 
			
		||||
    });
 | 
			
		||||
    //return _.orderBy(branchArr, [function(b) { return b.commit.seq}], ['desc']);
 | 
			
		||||
    return branchArr;
 | 
			
		||||
exports.getBranchesAsObjArray = function () {
 | 
			
		||||
  var branchArr = _.map(branches, function (v, k) {
 | 
			
		||||
    return {'name': k, 'commit': commits[v]}
 | 
			
		||||
  })
 | 
			
		||||
    // return _.orderBy(branchArr, [function(b) { return b.commit.seq}], ['desc']);
 | 
			
		||||
  return branchArr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.getBranches = function() { return branches; }
 | 
			
		||||
exports.getCommits = function() { return commits; }
 | 
			
		||||
exports.getCommitsArray = function() {
 | 
			
		||||
    var commitArr = Object.keys(commits).map(function (key) {
 | 
			
		||||
        return commits[key];
 | 
			
		||||
    });
 | 
			
		||||
    _.each(commitArr, function(o) { log.debug(o.id) });
 | 
			
		||||
    return _.orderBy(commitArr, ['seq'], ['desc']);
 | 
			
		||||
    }
 | 
			
		||||
exports.getCurrentBranch = function() { return curBranch; }
 | 
			
		||||
exports.getDirection = function() { return direction; }
 | 
			
		||||
exports.getHead = function() { return head; }
 | 
			
		||||
exports.getBranches = function () { return branches }
 | 
			
		||||
exports.getCommits = function () { return commits }
 | 
			
		||||
exports.getCommitsArray = function () {
 | 
			
		||||
  var commitArr = Object.keys(commits).map(function (key) {
 | 
			
		||||
    return commits[key]
 | 
			
		||||
  })
 | 
			
		||||
  _.each(commitArr, function (o) { log.debug(o.id) })
 | 
			
		||||
  return _.orderBy(commitArr, ['seq'], ['desc'])
 | 
			
		||||
}
 | 
			
		||||
exports.getCurrentBranch = function () { return curBranch }
 | 
			
		||||
exports.getDirection = function () { return direction }
 | 
			
		||||
exports.getHead = function () { return head }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,211 +1,211 @@
 | 
			
		||||
var parser = require('./parser/gitGraph').parser;
 | 
			
		||||
var ast = require('./gitGraphAst.js');
 | 
			
		||||
describe('when parsing a gitGraph',function() {
 | 
			
		||||
    'use strict';
 | 
			
		||||
    beforeEach(function () {
 | 
			
		||||
        console.log('ast',ast);
 | 
			
		||||
        console.log('parser',parser);
 | 
			
		||||
        parser.yy = ast;
 | 
			
		||||
        parser.yy.clear();
 | 
			
		||||
    });
 | 
			
		||||
    it('should handle a gitGraph defintion', function () {
 | 
			
		||||
        var str = 'gitGraph:\n' +
 | 
			
		||||
        'commit\n';
 | 
			
		||||
var parser = require('./parser/gitGraph').parser
 | 
			
		||||
var ast = require('./gitGraphAst.js')
 | 
			
		||||
describe('when parsing a gitGraph', function () {
 | 
			
		||||
  'use strict'
 | 
			
		||||
  beforeEach(function () {
 | 
			
		||||
    console.log('ast', ast)
 | 
			
		||||
    console.log('parser', parser)
 | 
			
		||||
    parser.yy = ast
 | 
			
		||||
    parser.yy.clear()
 | 
			
		||||
  })
 | 
			
		||||
  it('should handle a gitGraph defintion', function () {
 | 
			
		||||
    var str = 'gitGraph:\n' +
 | 
			
		||||
        'commit\n'
 | 
			
		||||
 | 
			
		||||
        parser.parse(str);
 | 
			
		||||
        var commits = parser.yy.getCommits();
 | 
			
		||||
        //console.log(commits);
 | 
			
		||||
    parser.parse(str)
 | 
			
		||||
    var commits = parser.yy.getCommits()
 | 
			
		||||
        // console.log(commits);
 | 
			
		||||
 | 
			
		||||
        expect(Object.keys(commits).length).toBe(1);
 | 
			
		||||
        expect(parser.yy.getCurrentBranch()).toBe('master');
 | 
			
		||||
        expect(parser.yy.getDirection()).toBe('LR');
 | 
			
		||||
        expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
 | 
			
		||||
    });
 | 
			
		||||
    expect(Object.keys(commits).length).toBe(1)
 | 
			
		||||
    expect(parser.yy.getCurrentBranch()).toBe('master')
 | 
			
		||||
    expect(parser.yy.getDirection()).toBe('LR')
 | 
			
		||||
    expect(Object.keys(parser.yy.getBranches()).length).toBe(1)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    it('should handle a gitGraph defintion with empty options', function () {
 | 
			
		||||
        var str = 'gitGraph:\n' +
 | 
			
		||||
  it('should handle a gitGraph defintion with empty options', function () {
 | 
			
		||||
    var str = 'gitGraph:\n' +
 | 
			
		||||
        'options\n' +
 | 
			
		||||
        'end\n' +
 | 
			
		||||
        'commit\n';
 | 
			
		||||
        'commit\n'
 | 
			
		||||
 | 
			
		||||
        parser.parse(str);
 | 
			
		||||
        var commits = parser.yy.getCommits();
 | 
			
		||||
        //console.log(commits);
 | 
			
		||||
    parser.parse(str)
 | 
			
		||||
    var commits = parser.yy.getCommits()
 | 
			
		||||
        // console.log(commits);
 | 
			
		||||
 | 
			
		||||
        expect(parser.yy.getOptions()).toEqual({});
 | 
			
		||||
        expect(Object.keys(commits).length).toBe(1);
 | 
			
		||||
        expect(parser.yy.getCurrentBranch()).toBe('master');
 | 
			
		||||
        expect(parser.yy.getDirection()).toBe('LR');
 | 
			
		||||
        expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
 | 
			
		||||
    });
 | 
			
		||||
    expect(parser.yy.getOptions()).toEqual({})
 | 
			
		||||
    expect(Object.keys(commits).length).toBe(1)
 | 
			
		||||
    expect(parser.yy.getCurrentBranch()).toBe('master')
 | 
			
		||||
    expect(parser.yy.getDirection()).toBe('LR')
 | 
			
		||||
    expect(Object.keys(parser.yy.getBranches()).length).toBe(1)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    it('should handle a gitGraph defintion with valid options', function () {
 | 
			
		||||
        var str = 'gitGraph:\n' +
 | 
			
		||||
  it('should handle a gitGraph defintion with valid options', function () {
 | 
			
		||||
    var str = 'gitGraph:\n' +
 | 
			
		||||
        'options\n' +
 | 
			
		||||
        '{"key": "value"}\n' +
 | 
			
		||||
        'end\n' +
 | 
			
		||||
        'commit\n';
 | 
			
		||||
        'commit\n'
 | 
			
		||||
 | 
			
		||||
        parser.parse(str);
 | 
			
		||||
        var commits = parser.yy.getCommits();
 | 
			
		||||
        //console.log(commits);
 | 
			
		||||
        //console.log('options object', parser.yy.getOptions());
 | 
			
		||||
        expect(parser.yy.getOptions()['key']).toBe('value');
 | 
			
		||||
        expect(Object.keys(commits).length).toBe(1);
 | 
			
		||||
        expect(parser.yy.getCurrentBranch()).toBe('master');
 | 
			
		||||
        expect(parser.yy.getDirection()).toBe('LR');
 | 
			
		||||
        expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
 | 
			
		||||
    });
 | 
			
		||||
    parser.parse(str)
 | 
			
		||||
    var commits = parser.yy.getCommits()
 | 
			
		||||
        // console.log(commits);
 | 
			
		||||
        // console.log('options object', parser.yy.getOptions());
 | 
			
		||||
    expect(parser.yy.getOptions()['key']).toBe('value')
 | 
			
		||||
    expect(Object.keys(commits).length).toBe(1)
 | 
			
		||||
    expect(parser.yy.getCurrentBranch()).toBe('master')
 | 
			
		||||
    expect(parser.yy.getDirection()).toBe('LR')
 | 
			
		||||
    expect(Object.keys(parser.yy.getBranches()).length).toBe(1)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    it('should not fail on a gitGraph with malformed json', function () {
 | 
			
		||||
        var str = 'gitGraph:\n' +
 | 
			
		||||
  it('should not fail on a gitGraph with malformed json', function () {
 | 
			
		||||
    var str = 'gitGraph:\n' +
 | 
			
		||||
        'options\n' +
 | 
			
		||||
        '{"key": "value"\n' +
 | 
			
		||||
        'end\n' +
 | 
			
		||||
        'commit\n';
 | 
			
		||||
        'commit\n'
 | 
			
		||||
 | 
			
		||||
        parser.parse(str);
 | 
			
		||||
        var commits = parser.yy.getCommits();
 | 
			
		||||
        //console.log(commits);
 | 
			
		||||
        expect(Object.keys(commits).length).toBe(1);
 | 
			
		||||
        expect(parser.yy.getCurrentBranch()).toBe('master');
 | 
			
		||||
        expect(parser.yy.getDirection()).toBe('LR');
 | 
			
		||||
        expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
 | 
			
		||||
    });
 | 
			
		||||
    parser.parse(str)
 | 
			
		||||
    var commits = parser.yy.getCommits()
 | 
			
		||||
        // console.log(commits);
 | 
			
		||||
    expect(Object.keys(commits).length).toBe(1)
 | 
			
		||||
    expect(parser.yy.getCurrentBranch()).toBe('master')
 | 
			
		||||
    expect(parser.yy.getDirection()).toBe('LR')
 | 
			
		||||
    expect(Object.keys(parser.yy.getBranches()).length).toBe(1)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    it('should handle set direction', function () {
 | 
			
		||||
        var str = 'gitGraph BT:\n' +
 | 
			
		||||
        'commit\n';
 | 
			
		||||
  it('should handle set direction', function () {
 | 
			
		||||
    var str = 'gitGraph BT:\n' +
 | 
			
		||||
        'commit\n'
 | 
			
		||||
 | 
			
		||||
        parser.parse(str);
 | 
			
		||||
        var commits = parser.yy.getCommits();
 | 
			
		||||
        //console.log(commits);
 | 
			
		||||
    parser.parse(str)
 | 
			
		||||
    var commits = parser.yy.getCommits()
 | 
			
		||||
        // console.log(commits);
 | 
			
		||||
 | 
			
		||||
        expect(Object.keys(commits).length).toBe(1);
 | 
			
		||||
        expect(parser.yy.getCurrentBranch()).toBe('master');
 | 
			
		||||
        expect(parser.yy.getDirection()).toBe('BT');
 | 
			
		||||
        expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
 | 
			
		||||
    });
 | 
			
		||||
    expect(Object.keys(commits).length).toBe(1)
 | 
			
		||||
    expect(parser.yy.getCurrentBranch()).toBe('master')
 | 
			
		||||
    expect(parser.yy.getDirection()).toBe('BT')
 | 
			
		||||
    expect(Object.keys(parser.yy.getBranches()).length).toBe(1)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    it('should checkout a branch', function () {
 | 
			
		||||
        var str = 'gitGraph:\n' +
 | 
			
		||||
  it('should checkout a branch', function () {
 | 
			
		||||
    var str = 'gitGraph:\n' +
 | 
			
		||||
        'branch new\n' +
 | 
			
		||||
        'checkout new\n'
 | 
			
		||||
 | 
			
		||||
        parser.parse(str);
 | 
			
		||||
        var commits = parser.yy.getCommits();
 | 
			
		||||
    parser.parse(str)
 | 
			
		||||
    var commits = parser.yy.getCommits()
 | 
			
		||||
 | 
			
		||||
        expect(Object.keys(commits).length).toBe(0);
 | 
			
		||||
        expect(parser.yy.getCurrentBranch()).toBe('new');
 | 
			
		||||
    });
 | 
			
		||||
    expect(Object.keys(commits).length).toBe(0)
 | 
			
		||||
    expect(parser.yy.getCurrentBranch()).toBe('new')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    it('should add commits to checked out branch', function () {
 | 
			
		||||
        var str = 'gitGraph:\n' +
 | 
			
		||||
  it('should add commits to checked out branch', function () {
 | 
			
		||||
    var str = 'gitGraph:\n' +
 | 
			
		||||
        'branch new\n' +
 | 
			
		||||
        'checkout new\n' +
 | 
			
		||||
        'commit\n'+
 | 
			
		||||
        'commit\n' +
 | 
			
		||||
        'commit\n'
 | 
			
		||||
 | 
			
		||||
        parser.parse(str);
 | 
			
		||||
        var commits = parser.yy.getCommits();
 | 
			
		||||
    parser.parse(str)
 | 
			
		||||
    var commits = parser.yy.getCommits()
 | 
			
		||||
 | 
			
		||||
        expect(Object.keys(commits).length).toBe(2);
 | 
			
		||||
        expect(parser.yy.getCurrentBranch()).toBe('new');
 | 
			
		||||
        var branchCommit = parser.yy.getBranches()['new'];
 | 
			
		||||
        expect(branchCommit).not.toBeNull();
 | 
			
		||||
        expect(commits[branchCommit].parent).not.toBeNull();
 | 
			
		||||
    });
 | 
			
		||||
    it('should handle commit with args', function () {
 | 
			
		||||
        var str = 'gitGraph:\n' +
 | 
			
		||||
        'commit "a commit"\n';
 | 
			
		||||
    expect(Object.keys(commits).length).toBe(2)
 | 
			
		||||
    expect(parser.yy.getCurrentBranch()).toBe('new')
 | 
			
		||||
    var branchCommit = parser.yy.getBranches()['new']
 | 
			
		||||
    expect(branchCommit).not.toBeNull()
 | 
			
		||||
    expect(commits[branchCommit].parent).not.toBeNull()
 | 
			
		||||
  })
 | 
			
		||||
  it('should handle commit with args', function () {
 | 
			
		||||
    var str = 'gitGraph:\n' +
 | 
			
		||||
        'commit "a commit"\n'
 | 
			
		||||
 | 
			
		||||
        parser.parse(str);
 | 
			
		||||
        var commits = parser.yy.getCommits();
 | 
			
		||||
        //console.log(commits);
 | 
			
		||||
    parser.parse(str)
 | 
			
		||||
    var commits = parser.yy.getCommits()
 | 
			
		||||
        // console.log(commits);
 | 
			
		||||
 | 
			
		||||
        expect(Object.keys(commits).length).toBe(1);
 | 
			
		||||
        var key = Object.keys(commits)[0];
 | 
			
		||||
        expect(commits[key].message).toBe('a commit');
 | 
			
		||||
        expect(parser.yy.getCurrentBranch()).toBe('master');
 | 
			
		||||
    });
 | 
			
		||||
    expect(Object.keys(commits).length).toBe(1)
 | 
			
		||||
    var key = Object.keys(commits)[0]
 | 
			
		||||
    expect(commits[key].message).toBe('a commit')
 | 
			
		||||
    expect(parser.yy.getCurrentBranch()).toBe('master')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    it('it should reset a branch', function () {
 | 
			
		||||
        var str = 'gitGraph:\n' +
 | 
			
		||||
  it('it should reset a branch', function () {
 | 
			
		||||
    var str = 'gitGraph:\n' +
 | 
			
		||||
        'commit\n' +
 | 
			
		||||
        'commit\n' +
 | 
			
		||||
        'branch newbranch\n' +
 | 
			
		||||
        'checkout newbranch\n' +
 | 
			
		||||
        'commit\n' +
 | 
			
		||||
        'reset master\n';
 | 
			
		||||
        'reset master\n'
 | 
			
		||||
 | 
			
		||||
        parser.parse(str);
 | 
			
		||||
    parser.parse(str)
 | 
			
		||||
 | 
			
		||||
        var commits = parser.yy.getCommits();
 | 
			
		||||
        expect(Object.keys(commits).length).toBe(3);
 | 
			
		||||
        expect(parser.yy.getCurrentBranch()).toBe('newbranch');
 | 
			
		||||
        expect(parser.yy.getBranches()['newbranch']).toEqual(parser.yy.getBranches()['master']);
 | 
			
		||||
        expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['newbranch']);
 | 
			
		||||
    });
 | 
			
		||||
    var commits = parser.yy.getCommits()
 | 
			
		||||
    expect(Object.keys(commits).length).toBe(3)
 | 
			
		||||
    expect(parser.yy.getCurrentBranch()).toBe('newbranch')
 | 
			
		||||
    expect(parser.yy.getBranches()['newbranch']).toEqual(parser.yy.getBranches()['master'])
 | 
			
		||||
    expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['newbranch'])
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    it('reset can take an argument', function () {
 | 
			
		||||
        var str = 'gitGraph:\n' +
 | 
			
		||||
  it('reset can take an argument', function () {
 | 
			
		||||
    var str = 'gitGraph:\n' +
 | 
			
		||||
        'commit\n' +
 | 
			
		||||
        'commit\n' +
 | 
			
		||||
        'branch newbranch\n' +
 | 
			
		||||
        'checkout newbranch\n' +
 | 
			
		||||
        'commit\n' +
 | 
			
		||||
        'reset master^\n';
 | 
			
		||||
        'reset master^\n'
 | 
			
		||||
 | 
			
		||||
        parser.parse(str);
 | 
			
		||||
    parser.parse(str)
 | 
			
		||||
 | 
			
		||||
        var commits = parser.yy.getCommits();
 | 
			
		||||
        expect(Object.keys(commits).length).toBe(3);
 | 
			
		||||
        expect(parser.yy.getCurrentBranch()).toBe('newbranch');
 | 
			
		||||
        var master = commits[parser.yy.getBranches()['master']];
 | 
			
		||||
        expect(parser.yy.getHead().id).toEqual(master.parent);
 | 
			
		||||
    })
 | 
			
		||||
    var commits = parser.yy.getCommits()
 | 
			
		||||
    expect(Object.keys(commits).length).toBe(3)
 | 
			
		||||
    expect(parser.yy.getCurrentBranch()).toBe('newbranch')
 | 
			
		||||
    var master = commits[parser.yy.getBranches()['master']]
 | 
			
		||||
    expect(parser.yy.getHead().id).toEqual(master.parent)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    it('it should handle fast forwardable merges', function () {
 | 
			
		||||
        var str = 'gitGraph:\n' +
 | 
			
		||||
  it('it should handle fast forwardable merges', function () {
 | 
			
		||||
    var str = 'gitGraph:\n' +
 | 
			
		||||
        'commit\n' +
 | 
			
		||||
        'branch newbranch\n' +
 | 
			
		||||
        'checkout newbranch\n' +
 | 
			
		||||
        'commit\n' +
 | 
			
		||||
        'commit\n' +
 | 
			
		||||
        'checkout master\n'+
 | 
			
		||||
        'merge newbranch\n';
 | 
			
		||||
        'checkout master\n' +
 | 
			
		||||
        'merge newbranch\n'
 | 
			
		||||
 | 
			
		||||
        parser.parse(str);
 | 
			
		||||
    parser.parse(str)
 | 
			
		||||
 | 
			
		||||
        var commits = parser.yy.getCommits();
 | 
			
		||||
        //console.log(commits);
 | 
			
		||||
        expect(Object.keys(commits).length).toBe(3);
 | 
			
		||||
        expect(parser.yy.getCurrentBranch()).toBe('master');
 | 
			
		||||
        expect(parser.yy.getBranches()['newbranch']).toEqual(parser.yy.getBranches()['master']);
 | 
			
		||||
        expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['newbranch']);
 | 
			
		||||
    });
 | 
			
		||||
    var commits = parser.yy.getCommits()
 | 
			
		||||
        // console.log(commits);
 | 
			
		||||
    expect(Object.keys(commits).length).toBe(3)
 | 
			
		||||
    expect(parser.yy.getCurrentBranch()).toBe('master')
 | 
			
		||||
    expect(parser.yy.getBranches()['newbranch']).toEqual(parser.yy.getBranches()['master'])
 | 
			
		||||
    expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['newbranch'])
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    it('it should handle cases when merge is a noop', function () {
 | 
			
		||||
        var str = 'gitGraph:\n' +
 | 
			
		||||
  it('it should handle cases when merge is a noop', function () {
 | 
			
		||||
    var str = 'gitGraph:\n' +
 | 
			
		||||
        'commit\n' +
 | 
			
		||||
        'branch newbranch\n' +
 | 
			
		||||
        'checkout newbranch\n' +
 | 
			
		||||
        'commit\n' +
 | 
			
		||||
        'commit\n' +
 | 
			
		||||
        'merge master\n';
 | 
			
		||||
        'merge master\n'
 | 
			
		||||
 | 
			
		||||
        parser.parse(str);
 | 
			
		||||
    parser.parse(str)
 | 
			
		||||
 | 
			
		||||
        var commits = parser.yy.getCommits();
 | 
			
		||||
        //console.log(commits);
 | 
			
		||||
        expect(Object.keys(commits).length).toBe(3);
 | 
			
		||||
        expect(parser.yy.getCurrentBranch()).toBe('newbranch');
 | 
			
		||||
        expect(parser.yy.getBranches()['newbranch']).not.toEqual(parser.yy.getBranches()['master']);
 | 
			
		||||
        expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['newbranch']);
 | 
			
		||||
    });
 | 
			
		||||
    var commits = parser.yy.getCommits()
 | 
			
		||||
        // console.log(commits);
 | 
			
		||||
    expect(Object.keys(commits).length).toBe(3)
 | 
			
		||||
    expect(parser.yy.getCurrentBranch()).toBe('newbranch')
 | 
			
		||||
    expect(parser.yy.getBranches()['newbranch']).not.toEqual(parser.yy.getBranches()['master'])
 | 
			
		||||
    expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['newbranch'])
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    it('it should handle merge with 2 parents', function () {
 | 
			
		||||
        var str = 'gitGraph:\n' +
 | 
			
		||||
  it('it should handle merge with 2 parents', function () {
 | 
			
		||||
    var str = 'gitGraph:\n' +
 | 
			
		||||
        'commit\n' +
 | 
			
		||||
        'branch newbranch\n' +
 | 
			
		||||
        'checkout newbranch\n' +
 | 
			
		||||
@@ -213,20 +213,20 @@ describe('when parsing a gitGraph',function() {
 | 
			
		||||
        'commit\n' +
 | 
			
		||||
        'checkout master\n' +
 | 
			
		||||
        'commit\n' +
 | 
			
		||||
        'merge newbranch\n';
 | 
			
		||||
        'merge newbranch\n'
 | 
			
		||||
 | 
			
		||||
        parser.parse(str);
 | 
			
		||||
    parser.parse(str)
 | 
			
		||||
 | 
			
		||||
        var commits = parser.yy.getCommits();
 | 
			
		||||
        //console.log(commits);
 | 
			
		||||
        expect(Object.keys(commits).length).toBe(5);
 | 
			
		||||
        expect(parser.yy.getCurrentBranch()).toBe('master');
 | 
			
		||||
        expect(parser.yy.getBranches()['newbranch']).not.toEqual(parser.yy.getBranches()['master']);
 | 
			
		||||
        expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['master']);
 | 
			
		||||
    });
 | 
			
		||||
    var commits = parser.yy.getCommits()
 | 
			
		||||
        // console.log(commits);
 | 
			
		||||
    expect(Object.keys(commits).length).toBe(5)
 | 
			
		||||
    expect(parser.yy.getCurrentBranch()).toBe('master')
 | 
			
		||||
    expect(parser.yy.getBranches()['newbranch']).not.toEqual(parser.yy.getBranches()['master'])
 | 
			
		||||
    expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['master'])
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    it('it should handle ff merge when history walk has two parents (merge commit)', function () {
 | 
			
		||||
        var str = 'gitGraph:\n' +
 | 
			
		||||
  it('it should handle ff merge when history walk has two parents (merge commit)', function () {
 | 
			
		||||
    var str = 'gitGraph:\n' +
 | 
			
		||||
        'commit\n' +
 | 
			
		||||
        'branch newbranch\n' +
 | 
			
		||||
        'checkout newbranch\n' +
 | 
			
		||||
@@ -237,17 +237,17 @@ describe('when parsing a gitGraph',function() {
 | 
			
		||||
        'merge newbranch\n' +
 | 
			
		||||
        'commit\n' +
 | 
			
		||||
        'checkout newbranch\n' +
 | 
			
		||||
        'merge master\n' ;
 | 
			
		||||
        'merge master\n'
 | 
			
		||||
 | 
			
		||||
        parser.parse(str);
 | 
			
		||||
    parser.parse(str)
 | 
			
		||||
 | 
			
		||||
        var commits = parser.yy.getCommits();
 | 
			
		||||
        //console.log(commits);
 | 
			
		||||
        expect(Object.keys(commits).length).toBe(6);
 | 
			
		||||
        expect(parser.yy.getCurrentBranch()).toBe('newbranch');
 | 
			
		||||
        expect(parser.yy.getBranches()['newbranch']).toEqual(parser.yy.getBranches()['master']);
 | 
			
		||||
        expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['master']);
 | 
			
		||||
    var commits = parser.yy.getCommits()
 | 
			
		||||
        // console.log(commits);
 | 
			
		||||
    expect(Object.keys(commits).length).toBe(6)
 | 
			
		||||
    expect(parser.yy.getCurrentBranch()).toBe('newbranch')
 | 
			
		||||
    expect(parser.yy.getBranches()['newbranch']).toEqual(parser.yy.getBranches()['master'])
 | 
			
		||||
    expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['master'])
 | 
			
		||||
 | 
			
		||||
        parser.yy.prettyPrint();
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
    parser.yy.prettyPrint()
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
 
 | 
			
		||||
@@ -1,46 +1,45 @@
 | 
			
		||||
var db = require('./gitGraphAst');
 | 
			
		||||
var _ = require('lodash');
 | 
			
		||||
var gitGraphParser = require('./parser/gitGraph');
 | 
			
		||||
var d3 = require('../../d3');
 | 
			
		||||
var Logger = require('../../logger');
 | 
			
		||||
var log = Logger.Log;
 | 
			
		||||
var db = require('./gitGraphAst')
 | 
			
		||||
var _ = require('lodash')
 | 
			
		||||
var gitGraphParser = require('./parser/gitGraph')
 | 
			
		||||
var d3 = require('../../d3')
 | 
			
		||||
var Logger = require('../../logger')
 | 
			
		||||
var log = Logger.Log
 | 
			
		||||
 | 
			
		||||
var allCommitsDict = {};
 | 
			
		||||
var branchNum;
 | 
			
		||||
var allCommitsDict = {}
 | 
			
		||||
var branchNum
 | 
			
		||||
var config = {
 | 
			
		||||
    nodeSpacing: 75,
 | 
			
		||||
    nodeFillColor: 'yellow',
 | 
			
		||||
    nodeStrokeWidth: 2,
 | 
			
		||||
    nodeStrokeColor: 'grey',
 | 
			
		||||
    lineStrokeWidth: 4,
 | 
			
		||||
    branchOffset: 50,
 | 
			
		||||
    lineColor: 'grey',
 | 
			
		||||
    leftMargin: 50,
 | 
			
		||||
    branchColors: ['#442f74', '#983351', '#609732', '#AA9A39'],
 | 
			
		||||
    nodeRadius: 15,
 | 
			
		||||
    nodeLabel: {
 | 
			
		||||
        width: 75,
 | 
			
		||||
        height: 100,
 | 
			
		||||
        x: -25,
 | 
			
		||||
        y: 15
 | 
			
		||||
    }
 | 
			
		||||
  nodeSpacing: 75,
 | 
			
		||||
  nodeFillColor: 'yellow',
 | 
			
		||||
  nodeStrokeWidth: 2,
 | 
			
		||||
  nodeStrokeColor: 'grey',
 | 
			
		||||
  lineStrokeWidth: 4,
 | 
			
		||||
  branchOffset: 50,
 | 
			
		||||
  lineColor: 'grey',
 | 
			
		||||
  leftMargin: 50,
 | 
			
		||||
  branchColors: ['#442f74', '#983351', '#609732', '#AA9A39'],
 | 
			
		||||
  nodeRadius: 15,
 | 
			
		||||
  nodeLabel: {
 | 
			
		||||
    width: 75,
 | 
			
		||||
    height: 100,
 | 
			
		||||
    x: -25,
 | 
			
		||||
    y: 15
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
var apiConfig = {};
 | 
			
		||||
exports.setConf = function(c) {
 | 
			
		||||
    apiConfig = c;
 | 
			
		||||
var apiConfig = {}
 | 
			
		||||
exports.setConf = function (c) {
 | 
			
		||||
  apiConfig = c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function svgCreateDefs(svg) {
 | 
			
		||||
    svg
 | 
			
		||||
function svgCreateDefs (svg) {
 | 
			
		||||
  svg
 | 
			
		||||
        .append('defs')
 | 
			
		||||
        .append('g')
 | 
			
		||||
        .attr('id', 'def-commit')
 | 
			
		||||
        .append('circle')
 | 
			
		||||
        .attr('r', config.nodeRadius)
 | 
			
		||||
        .attr('cx', 0)
 | 
			
		||||
        .attr('cy', 0);
 | 
			
		||||
    svg.select('#def-commit')
 | 
			
		||||
        .attr('cy', 0)
 | 
			
		||||
  svg.select('#def-commit')
 | 
			
		||||
        .append('foreignObject')
 | 
			
		||||
        .attr('width', config.nodeLabel.width)
 | 
			
		||||
        .attr('height', config.nodeLabel.height)
 | 
			
		||||
@@ -49,234 +48,233 @@ function svgCreateDefs(svg) {
 | 
			
		||||
        .attr('class', 'node-label')
 | 
			
		||||
        .attr('requiredFeatures', 'http://www.w3.org/TR/SVG11/feature#Extensibility')
 | 
			
		||||
        .append('xhtml:p')
 | 
			
		||||
        .html('');
 | 
			
		||||
        .html('')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function svgDrawLine(svg, points, colorIdx, interpolate) {
 | 
			
		||||
    interpolate = interpolate || 'basis';
 | 
			
		||||
    var color = config.branchColors[colorIdx % config.branchColors.length];
 | 
			
		||||
    var lineGen = d3.svg.line()
 | 
			
		||||
        .x(function(d) {
 | 
			
		||||
            return Math.round(d.x)
 | 
			
		||||
function svgDrawLine (svg, points, colorIdx, interpolate) {
 | 
			
		||||
  interpolate = interpolate || 'basis'
 | 
			
		||||
  var color = config.branchColors[colorIdx % config.branchColors.length]
 | 
			
		||||
  var lineGen = d3.svg.line()
 | 
			
		||||
        .x(function (d) {
 | 
			
		||||
          return Math.round(d.x)
 | 
			
		||||
        })
 | 
			
		||||
        .y(function(d) {
 | 
			
		||||
            return Math.round(d.y)
 | 
			
		||||
        .y(function (d) {
 | 
			
		||||
          return Math.round(d.y)
 | 
			
		||||
        })
 | 
			
		||||
        .interpolate(interpolate);
 | 
			
		||||
        .interpolate(interpolate)
 | 
			
		||||
 | 
			
		||||
    svg
 | 
			
		||||
  svg
 | 
			
		||||
        .append('svg:path')
 | 
			
		||||
        .attr('d', lineGen(points))
 | 
			
		||||
        .style('stroke', color)
 | 
			
		||||
        .style('stroke-width', config.lineStrokeWidth)
 | 
			
		||||
        .style('fill', 'none');
 | 
			
		||||
        .style('fill', 'none')
 | 
			
		||||
}
 | 
			
		||||
// Pass in the element and its pre-transform coords
 | 
			
		||||
function getElementCoords(element, coords) {
 | 
			
		||||
    coords = coords || element.node().getBBox();
 | 
			
		||||
    var ctm = element.node().getCTM(),
 | 
			
		||||
        xn = ctm.e + coords.x * ctm.a,
 | 
			
		||||
        yn = ctm.f + coords.y * ctm.d;
 | 
			
		||||
    //log.debug(ctm, coords);
 | 
			
		||||
    return {
 | 
			
		||||
        left: xn,
 | 
			
		||||
        top: yn,
 | 
			
		||||
        width: coords.width,
 | 
			
		||||
        height: coords.height
 | 
			
		||||
    };
 | 
			
		||||
function getElementCoords (element, coords) {
 | 
			
		||||
  coords = coords || element.node().getBBox()
 | 
			
		||||
  var ctm = element.node().getCTM(),
 | 
			
		||||
    xn = ctm.e + coords.x * ctm.a,
 | 
			
		||||
    yn = ctm.f + coords.y * ctm.d
 | 
			
		||||
    // log.debug(ctm, coords);
 | 
			
		||||
  return {
 | 
			
		||||
    left: xn,
 | 
			
		||||
    top: yn,
 | 
			
		||||
    width: coords.width,
 | 
			
		||||
    height: coords.height
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function svgDrawLineForCommits(svg, fromId, toId, direction, color) {
 | 
			
		||||
    log.debug('svgDrawLineForCommits: ', fromId, toId);
 | 
			
		||||
    var fromBbox = getElementCoords(svg.select('#node-' + fromId + ' circle'));
 | 
			
		||||
    var toBbox = getElementCoords(svg.select('#node-' + toId + ' circle'));
 | 
			
		||||
    //log.debug('svgDrawLineForCommits: ', fromBbox, toBbox);
 | 
			
		||||
    switch (direction) {
 | 
			
		||||
        case 'LR':
 | 
			
		||||
function svgDrawLineForCommits (svg, fromId, toId, direction, color) {
 | 
			
		||||
  log.debug('svgDrawLineForCommits: ', fromId, toId)
 | 
			
		||||
  var fromBbox = getElementCoords(svg.select('#node-' + fromId + ' circle'))
 | 
			
		||||
  var toBbox = getElementCoords(svg.select('#node-' + toId + ' circle'))
 | 
			
		||||
    // log.debug('svgDrawLineForCommits: ', fromBbox, toBbox);
 | 
			
		||||
  switch (direction) {
 | 
			
		||||
    case 'LR':
 | 
			
		||||
            // (toBbox)
 | 
			
		||||
            //  +--------
 | 
			
		||||
            //          + (fromBbox)
 | 
			
		||||
            if (fromBbox.left - toBbox.left > config.nodeSpacing) {
 | 
			
		||||
                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 };
 | 
			
		||||
                svgDrawLine(svg, [lineStart , lineEnd], color, 'linear')
 | 
			
		||||
                svgDrawLine(svg, [
 | 
			
		||||
                    {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: lineStart.y},
 | 
			
		||||
                lineStart], color);
 | 
			
		||||
            } else {
 | 
			
		||||
                svgDrawLine(svg, [{
 | 
			
		||||
                    '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': toBbox.top + toBbox.height / 2
 | 
			
		||||
                }, {
 | 
			
		||||
                    'x': toBbox.left + toBbox.width,
 | 
			
		||||
                    'y': toBbox.top + toBbox.height / 2
 | 
			
		||||
                }], color);
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case 'BT':
 | 
			
		||||
      if (fromBbox.left - toBbox.left > config.nodeSpacing) {
 | 
			
		||||
        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 }
 | 
			
		||||
        svgDrawLine(svg, [lineStart, lineEnd], color, 'linear')
 | 
			
		||||
        svgDrawLine(svg, [
 | 
			
		||||
                    {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: lineStart.y},
 | 
			
		||||
          lineStart], color)
 | 
			
		||||
      } else {
 | 
			
		||||
        svgDrawLine(svg, [{
 | 
			
		||||
          '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': toBbox.top + toBbox.height / 2
 | 
			
		||||
        }, {
 | 
			
		||||
          'x': toBbox.left + toBbox.width,
 | 
			
		||||
          'y': toBbox.top + toBbox.height / 2
 | 
			
		||||
        }], color)
 | 
			
		||||
      }
 | 
			
		||||
      break
 | 
			
		||||
    case 'BT':
 | 
			
		||||
            //      +           (fromBbox)
 | 
			
		||||
            //      |
 | 
			
		||||
            //      |
 | 
			
		||||
            //              +   (toBbox)
 | 
			
		||||
            if (toBbox.top - fromBbox.top > 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 };
 | 
			
		||||
                svgDrawLine(svg, [lineStart , lineEnd], color, 'linear')
 | 
			
		||||
                svgDrawLine(svg, [
 | 
			
		||||
                    {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: toBbox.left + toBbox.width/2, y: lineStart.y - config.nodeSpacing/2},
 | 
			
		||||
                lineStart], color);
 | 
			
		||||
            } else {
 | 
			
		||||
                svgDrawLine(svg, [{
 | 
			
		||||
                    'x': fromBbox.left + fromBbox.width/2,
 | 
			
		||||
                    'y': fromBbox.top + fromBbox.height
 | 
			
		||||
                }, {
 | 
			
		||||
                    'x': fromBbox.left + fromBbox.width/2,
 | 
			
		||||
                    'y': fromBbox.top + config.nodeSpacing/2
 | 
			
		||||
                }, {
 | 
			
		||||
                    'x': toBbox.left + toBbox.width/2,
 | 
			
		||||
                    'y': toBbox.top - config.nodeSpacing/2
 | 
			
		||||
                }, {
 | 
			
		||||
                    'x': toBbox.left + toBbox.width/2,
 | 
			
		||||
                    'y': toBbox.top
 | 
			
		||||
                }], color);
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
      if (toBbox.top - fromBbox.top > 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 }
 | 
			
		||||
        svgDrawLine(svg, [lineStart, lineEnd], color, 'linear')
 | 
			
		||||
        svgDrawLine(svg, [
 | 
			
		||||
                    {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: toBbox.left + toBbox.width / 2, y: lineStart.y - config.nodeSpacing / 2},
 | 
			
		||||
          lineStart], color)
 | 
			
		||||
      } else {
 | 
			
		||||
        svgDrawLine(svg, [{
 | 
			
		||||
          'x': fromBbox.left + fromBbox.width / 2,
 | 
			
		||||
          'y': fromBbox.top + fromBbox.height
 | 
			
		||||
        }, {
 | 
			
		||||
          'x': fromBbox.left + fromBbox.width / 2,
 | 
			
		||||
          'y': fromBbox.top + config.nodeSpacing / 2
 | 
			
		||||
        }, {
 | 
			
		||||
          'x': toBbox.left + toBbox.width / 2,
 | 
			
		||||
          'y': toBbox.top - config.nodeSpacing / 2
 | 
			
		||||
        }, {
 | 
			
		||||
          'x': toBbox.left + toBbox.width / 2,
 | 
			
		||||
          'y': toBbox.top
 | 
			
		||||
        }], color)
 | 
			
		||||
      }
 | 
			
		||||
      break
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function cloneNode(svg, selector) {
 | 
			
		||||
    return svg.select(selector).node().cloneNode(true);
 | 
			
		||||
function cloneNode (svg, selector) {
 | 
			
		||||
  return svg.select(selector).node().cloneNode(true)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function renderCommitHistory(svg, commitid, branches, direction) {
 | 
			
		||||
    var commit;
 | 
			
		||||
    var numCommits = Object.keys(allCommitsDict).length;
 | 
			
		||||
    if (_.isString(commitid)) {
 | 
			
		||||
        do {
 | 
			
		||||
            commit = allCommitsDict[commitid];
 | 
			
		||||
            log.debug('in renderCommitHistory', commit.id, commit.seq);
 | 
			
		||||
            if (svg.select('#node-' + commitid).size() > 0)  {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            svg
 | 
			
		||||
                .append(function() {
 | 
			
		||||
                    return cloneNode(svg, '#def-commit');
 | 
			
		||||
function renderCommitHistory (svg, commitid, branches, direction) {
 | 
			
		||||
  var commit
 | 
			
		||||
  var numCommits = Object.keys(allCommitsDict).length
 | 
			
		||||
  if (_.isString(commitid)) {
 | 
			
		||||
    do {
 | 
			
		||||
      commit = allCommitsDict[commitid]
 | 
			
		||||
      log.debug('in renderCommitHistory', commit.id, commit.seq)
 | 
			
		||||
      if (svg.select('#node-' + commitid).size() > 0) {
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
      svg
 | 
			
		||||
                .append(function () {
 | 
			
		||||
                  return cloneNode(svg, '#def-commit')
 | 
			
		||||
                })
 | 
			
		||||
                .attr('class', 'commit')
 | 
			
		||||
                .attr('id', function() {
 | 
			
		||||
                    return 'node-' + commit.id;
 | 
			
		||||
                .attr('id', function () {
 | 
			
		||||
                  return 'node-' + commit.id
 | 
			
		||||
                })
 | 
			
		||||
                .attr('transform', function() {
 | 
			
		||||
                    switch (direction) {
 | 
			
		||||
                        case 'LR':
 | 
			
		||||
                            return 'translate(' + (commit.seq * config.nodeSpacing + config.leftMargin) + ', '
 | 
			
		||||
                                + (branchNum * config.branchOffset) + ')';
 | 
			
		||||
                        case 'BT':
 | 
			
		||||
                            return 'translate(' + (branchNum * config.branchOffset + config.leftMargin) + ', '
 | 
			
		||||
                                + ((numCommits - commit.seq) * config.nodeSpacing) + ')';
 | 
			
		||||
                    }
 | 
			
		||||
                .attr('transform', function () {
 | 
			
		||||
                  switch (direction) {
 | 
			
		||||
                    case 'LR':
 | 
			
		||||
                      return 'translate(' + (commit.seq * config.nodeSpacing + config.leftMargin) + ', ' +
 | 
			
		||||
                                (branchNum * config.branchOffset) + ')'
 | 
			
		||||
                    case 'BT':
 | 
			
		||||
                      return 'translate(' + (branchNum * config.branchOffset + config.leftMargin) + ', ' +
 | 
			
		||||
                                ((numCommits - commit.seq) * config.nodeSpacing) + ')'
 | 
			
		||||
                  }
 | 
			
		||||
                })
 | 
			
		||||
                .attr('fill', config.nodeFillColor)
 | 
			
		||||
                .attr('stroke', config.nodeStrokeColor)
 | 
			
		||||
                .attr('stroke-width', config.nodeStrokeWidth);
 | 
			
		||||
                .attr('stroke-width', config.nodeStrokeWidth)
 | 
			
		||||
 | 
			
		||||
            var branch = _.find(branches, ['commit', commit]);
 | 
			
		||||
            if (branch) {
 | 
			
		||||
                log.debug('found branch ', branch.name);
 | 
			
		||||
                svg.select('#node-' + commit.id + ' p')
 | 
			
		||||
      var branch = _.find(branches, ['commit', commit])
 | 
			
		||||
      if (branch) {
 | 
			
		||||
        log.debug('found branch ', branch.name)
 | 
			
		||||
        svg.select('#node-' + commit.id + ' p')
 | 
			
		||||
                    .append('xhtml:span')
 | 
			
		||||
                    .attr('class', 'branch-label')
 | 
			
		||||
                    .text(branch.name + ', ');
 | 
			
		||||
            }
 | 
			
		||||
            svg.select('#node-' + commit.id + ' p')
 | 
			
		||||
                    .text(branch.name + ', ')
 | 
			
		||||
      }
 | 
			
		||||
      svg.select('#node-' + commit.id + ' p')
 | 
			
		||||
                .append('xhtml:span')
 | 
			
		||||
                .attr('class', 'commit-id')
 | 
			
		||||
                .text(commit.id);
 | 
			
		||||
            if (commit.message !== '' && direction === 'BT') {
 | 
			
		||||
                svg.select('#node-' + commit.id + ' p')
 | 
			
		||||
                .text(commit.id)
 | 
			
		||||
      if (commit.message !== '' && direction === 'BT') {
 | 
			
		||||
        svg.select('#node-' + commit.id + ' p')
 | 
			
		||||
                    .append('xhtml:span')
 | 
			
		||||
                    .attr('class', 'commit-msg')
 | 
			
		||||
                    .text( ', ' + commit.message);
 | 
			
		||||
            }
 | 
			
		||||
            commitid = commit.parent
 | 
			
		||||
        } while (commitid && allCommitsDict[commitid]);
 | 
			
		||||
    }
 | 
			
		||||
                    .text(', ' + commit.message)
 | 
			
		||||
      }
 | 
			
		||||
      commitid = commit.parent
 | 
			
		||||
    } while (commitid && allCommitsDict[commitid])
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    if (_.isArray(commitid)) {
 | 
			
		||||
        log.debug('found merge commmit', commitid);
 | 
			
		||||
        renderCommitHistory(svg, commitid[0], branches, direction);
 | 
			
		||||
        branchNum++;
 | 
			
		||||
        renderCommitHistory(svg, commitid[1], branches, direction);
 | 
			
		||||
        branchNum--;
 | 
			
		||||
    }
 | 
			
		||||
  if (_.isArray(commitid)) {
 | 
			
		||||
    log.debug('found merge commmit', commitid)
 | 
			
		||||
    renderCommitHistory(svg, commitid[0], branches, direction)
 | 
			
		||||
    branchNum++
 | 
			
		||||
    renderCommitHistory(svg, commitid[1], branches, direction)
 | 
			
		||||
    branchNum--
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function renderLines(svg, commit, direction, branchColor) {
 | 
			
		||||
    branchColor = branchColor || 0;
 | 
			
		||||
    while (commit.seq > 0 && !commit.lineDrawn) {
 | 
			
		||||
        if (_.isString(commit.parent)) {
 | 
			
		||||
            svgDrawLineForCommits(svg, commit.id, commit.parent, direction, branchColor);
 | 
			
		||||
            commit.lineDrawn = true;
 | 
			
		||||
            commit = allCommitsDict[commit.parent];
 | 
			
		||||
        } else if (_.isArray(commit.parent)) {
 | 
			
		||||
            svgDrawLineForCommits(svg, commit.id, commit.parent[0], direction, branchColor)
 | 
			
		||||
            svgDrawLineForCommits(svg, commit.id, commit.parent[1], direction, branchColor + 1)
 | 
			
		||||
            renderLines(svg, allCommitsDict[commit.parent[1]], direction, branchColor + 1);
 | 
			
		||||
            commit.lineDrawn = true;
 | 
			
		||||
            commit = allCommitsDict[commit.parent[0]];
 | 
			
		||||
        }
 | 
			
		||||
function renderLines (svg, commit, direction, branchColor) {
 | 
			
		||||
  branchColor = branchColor || 0
 | 
			
		||||
  while (commit.seq > 0 && !commit.lineDrawn) {
 | 
			
		||||
    if (_.isString(commit.parent)) {
 | 
			
		||||
      svgDrawLineForCommits(svg, commit.id, commit.parent, direction, branchColor)
 | 
			
		||||
      commit.lineDrawn = true
 | 
			
		||||
      commit = allCommitsDict[commit.parent]
 | 
			
		||||
    } else if (_.isArray(commit.parent)) {
 | 
			
		||||
      svgDrawLineForCommits(svg, commit.id, commit.parent[0], direction, branchColor)
 | 
			
		||||
      svgDrawLineForCommits(svg, commit.id, commit.parent[1], direction, branchColor + 1)
 | 
			
		||||
      renderLines(svg, allCommitsDict[commit.parent[1]], direction, branchColor + 1)
 | 
			
		||||
      commit.lineDrawn = true
 | 
			
		||||
      commit = allCommitsDict[commit.parent[0]]
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.draw = function(txt, id, ver) {
 | 
			
		||||
    try {
 | 
			
		||||
        var parser;
 | 
			
		||||
        parser = gitGraphParser.parser;
 | 
			
		||||
        parser.yy = db;
 | 
			
		||||
exports.draw = function (txt, id, ver) {
 | 
			
		||||
  try {
 | 
			
		||||
    var parser
 | 
			
		||||
    parser = gitGraphParser.parser
 | 
			
		||||
    parser.yy = db
 | 
			
		||||
 | 
			
		||||
        log.debug('in gitgraph renderer', txt, id, ver);
 | 
			
		||||
    log.debug('in gitgraph renderer', txt, id, ver)
 | 
			
		||||
        // Parse the graph definition
 | 
			
		||||
        parser.parse(txt + '\n');
 | 
			
		||||
    parser.parse(txt + '\n')
 | 
			
		||||
 | 
			
		||||
        config = _.extend(config, apiConfig, db.getOptions());
 | 
			
		||||
        log.debug('effective options', config);
 | 
			
		||||
        var direction = db.getDirection();
 | 
			
		||||
        allCommitsDict = db.getCommits();
 | 
			
		||||
        var branches = db.getBranchesAsObjArray();
 | 
			
		||||
        if (direction === 'BT') {
 | 
			
		||||
            config.nodeLabel.x =  branches.length * config.branchOffset;
 | 
			
		||||
            config.nodeLabel.width =  '100%';
 | 
			
		||||
            config.nodeLabel.y = -1 * 2* config.nodeRadius;
 | 
			
		||||
        }
 | 
			
		||||
        var svg = d3.select('#' + id);
 | 
			
		||||
        svgCreateDefs(svg);
 | 
			
		||||
        branchNum = 1;
 | 
			
		||||
        _.each(branches, function(v) {
 | 
			
		||||
            renderCommitHistory(svg, v.commit.id, branches, direction);
 | 
			
		||||
            renderLines(svg, v.commit, direction);
 | 
			
		||||
            branchNum++;
 | 
			
		||||
        });
 | 
			
		||||
        svg.attr('height', function() {
 | 
			
		||||
            if (direction === 'BT') return Object.keys(allCommitsDict).length * config.nodeSpacing;
 | 
			
		||||
            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) {
 | 
			
		||||
        log.error('Error while rendering gitgraph');
 | 
			
		||||
        log.error(e.message);
 | 
			
		||||
    config = _.extend(config, apiConfig, db.getOptions())
 | 
			
		||||
    log.debug('effective options', config)
 | 
			
		||||
    var direction = db.getDirection()
 | 
			
		||||
    allCommitsDict = db.getCommits()
 | 
			
		||||
    var branches = db.getBranchesAsObjArray()
 | 
			
		||||
    if (direction === 'BT') {
 | 
			
		||||
      config.nodeLabel.x = branches.length * config.branchOffset
 | 
			
		||||
      config.nodeLabel.width = '100%'
 | 
			
		||||
      config.nodeLabel.y = -1 * 2 * config.nodeRadius
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
    var svg = d3.select('#' + id)
 | 
			
		||||
    svgCreateDefs(svg)
 | 
			
		||||
    branchNum = 1
 | 
			
		||||
    _.each(branches, function (v) {
 | 
			
		||||
      renderCommitHistory(svg, v.commit.id, branches, direction)
 | 
			
		||||
      renderLines(svg, v.commit, direction)
 | 
			
		||||
      branchNum++
 | 
			
		||||
    })
 | 
			
		||||
    svg.attr('height', function () {
 | 
			
		||||
      if (direction === 'BT') return Object.keys(allCommitsDict).length * config.nodeSpacing
 | 
			
		||||
      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) {
 | 
			
		||||
    log.error('Error while rendering gitgraph')
 | 
			
		||||
    log.error(e.message)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,174 +1,171 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Created by knut on 14-11-19.
 | 
			
		||||
 */
 | 
			
		||||
var actors    = {};
 | 
			
		||||
var messages  = [];
 | 
			
		||||
var notes     = [];
 | 
			
		||||
var title = '';
 | 
			
		||||
var Logger = require('../../logger');
 | 
			
		||||
var log = Logger.Log;
 | 
			
		||||
var actors = {}
 | 
			
		||||
var messages = []
 | 
			
		||||
var notes = []
 | 
			
		||||
var title = ''
 | 
			
		||||
var Logger = require('../../logger')
 | 
			
		||||
var log = Logger.Log
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
exports.addActor = function(id,name,description){
 | 
			
		||||
exports.addActor = function (id, name, description) {
 | 
			
		||||
    // Don't allow description nulling
 | 
			
		||||
    var old = actors[id];
 | 
			
		||||
    if ( old && name === old.name && description == null ) return;
 | 
			
		||||
  var old = actors[id]
 | 
			
		||||
  if (old && name === old.name && description == null) return
 | 
			
		||||
 | 
			
		||||
    // 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){
 | 
			
		||||
    messages.push({from:idFrom, to:idTo, message:message, answer:answer});
 | 
			
		||||
};
 | 
			
		||||
exports.addMessage = function (idFrom, idTo, message, answer) {
 | 
			
		||||
  messages.push({from: idFrom, to: idTo, message: message, answer: answer})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
exports.addSignal = function(idFrom, idTo, message,  messageType){
 | 
			
		||||
    log.debug('Adding message from='+idFrom+' to='+idTo+' message='+message+' type='+messageType);
 | 
			
		||||
    messages.push({from:idFrom, to:idTo, message:message, type:messageType});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
exports.getMessages = function(){
 | 
			
		||||
    return messages;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
exports.getActors = function(){
 | 
			
		||||
    return actors;
 | 
			
		||||
};
 | 
			
		||||
exports.getActor = function(id){
 | 
			
		||||
    return actors[id];
 | 
			
		||||
};
 | 
			
		||||
exports.getActorKeys = function(){
 | 
			
		||||
    return Object.keys(actors);
 | 
			
		||||
};
 | 
			
		||||
exports.getTitle = function() {
 | 
			
		||||
  return title;
 | 
			
		||||
exports.addSignal = function (idFrom, idTo, message, messageType) {
 | 
			
		||||
  log.debug('Adding message from=' + idFrom + ' to=' + idTo + ' message=' + message + ' type=' + messageType)
 | 
			
		||||
  messages.push({from: idFrom, to: idTo, message: message, type: messageType})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.clear = function(){
 | 
			
		||||
    actors   = {};
 | 
			
		||||
    messages = [];
 | 
			
		||||
};
 | 
			
		||||
exports.getMessages = function () {
 | 
			
		||||
  return messages
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.getActors = function () {
 | 
			
		||||
  return actors
 | 
			
		||||
}
 | 
			
		||||
exports.getActor = function (id) {
 | 
			
		||||
  return actors[id]
 | 
			
		||||
}
 | 
			
		||||
exports.getActorKeys = function () {
 | 
			
		||||
  return Object.keys(actors)
 | 
			
		||||
}
 | 
			
		||||
exports.getTitle = function () {
 | 
			
		||||
  return title
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.clear = function () {
 | 
			
		||||
  actors = {}
 | 
			
		||||
  messages = []
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.LINETYPE = {
 | 
			
		||||
    SOLID        : 0  ,
 | 
			
		||||
    DOTTED       : 1  ,
 | 
			
		||||
    NOTE         : 2  ,
 | 
			
		||||
    SOLID_CROSS  : 3  ,
 | 
			
		||||
    DOTTED_CROSS : 4  ,
 | 
			
		||||
    SOLID_OPEN   : 5  ,
 | 
			
		||||
    DOTTED_OPEN  : 6  ,
 | 
			
		||||
    LOOP_START   : 10 ,
 | 
			
		||||
    LOOP_END     : 11 ,
 | 
			
		||||
    ALT_START    : 12 ,
 | 
			
		||||
    ALT_ELSE     : 13 ,
 | 
			
		||||
    ALT_END      : 14 ,
 | 
			
		||||
    OPT_START    : 15 ,
 | 
			
		||||
    OPT_END      : 16 ,
 | 
			
		||||
    ACTIVE_START : 17 ,
 | 
			
		||||
    ACTIVE_END   : 18 ,
 | 
			
		||||
    PAR_START    : 19 ,
 | 
			
		||||
    PAR_AND      : 20 ,
 | 
			
		||||
    PAR_END      : 21
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
exports.ARROWTYPE = {
 | 
			
		||||
    FILLED       : 0,
 | 
			
		||||
    OPEN         : 1
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
exports.PLACEMENT = {
 | 
			
		||||
    LEFTOF       : 0,
 | 
			
		||||
    RIGHTOF      : 1,
 | 
			
		||||
    OVER         : 2
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
exports.addNote = function (actor, placement, message){
 | 
			
		||||
    var note = {actor:actor, placement: placement, message:message};
 | 
			
		||||
 | 
			
		||||
    // Coerce actor into a [to, from, ...] array
 | 
			
		||||
    var actors = [].concat(actor, actor);
 | 
			
		||||
 | 
			
		||||
    notes.push(note);
 | 
			
		||||
    messages.push({from:actors[0], to:actors[1], message:message, type:exports.LINETYPE.NOTE, placement: placement});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
exports.setTitle = function(titleText){
 | 
			
		||||
  title = titleText;
 | 
			
		||||
  SOLID: 0,
 | 
			
		||||
  DOTTED: 1,
 | 
			
		||||
  NOTE: 2,
 | 
			
		||||
  SOLID_CROSS: 3,
 | 
			
		||||
  DOTTED_CROSS: 4,
 | 
			
		||||
  SOLID_OPEN: 5,
 | 
			
		||||
  DOTTED_OPEN: 6,
 | 
			
		||||
  LOOP_START: 10,
 | 
			
		||||
  LOOP_END: 11,
 | 
			
		||||
  ALT_START: 12,
 | 
			
		||||
  ALT_ELSE: 13,
 | 
			
		||||
  ALT_END: 14,
 | 
			
		||||
  OPT_START: 15,
 | 
			
		||||
  OPT_END: 16,
 | 
			
		||||
  ACTIVE_START: 17,
 | 
			
		||||
  ACTIVE_END: 18,
 | 
			
		||||
  PAR_START: 19,
 | 
			
		||||
  PAR_AND: 20,
 | 
			
		||||
  PAR_END: 21
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.ARROWTYPE = {
 | 
			
		||||
  FILLED: 0,
 | 
			
		||||
  OPEN: 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.parseError = function(err,hash){
 | 
			
		||||
    global.mermaidAPI.parseError(err,hash);
 | 
			
		||||
};
 | 
			
		||||
exports.PLACEMENT = {
 | 
			
		||||
  LEFTOF: 0,
 | 
			
		||||
  RIGHTOF: 1,
 | 
			
		||||
  OVER: 2
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.apply = function(param){
 | 
			
		||||
    if(param instanceof Array ){
 | 
			
		||||
        param.forEach(function(item){
 | 
			
		||||
            exports.apply(item);
 | 
			
		||||
        });
 | 
			
		||||
    } else {
 | 
			
		||||
exports.addNote = function (actor, placement, message) {
 | 
			
		||||
  var note = {actor: actor, placement: placement, message: message}
 | 
			
		||||
 | 
			
		||||
    // Coerce actor into a [to, from, ...] array
 | 
			
		||||
  var actors = [].concat(actor, actor)
 | 
			
		||||
 | 
			
		||||
  notes.push(note)
 | 
			
		||||
  messages.push({from: actors[0], to: actors[1], message: message, type: exports.LINETYPE.NOTE, placement: placement})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.setTitle = function (titleText) {
 | 
			
		||||
  title = titleText
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.parseError = function (err, hash) {
 | 
			
		||||
  global.mermaidAPI.parseError(err, hash)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.apply = function (param) {
 | 
			
		||||
  if (param instanceof Array) {
 | 
			
		||||
    param.forEach(function (item) {
 | 
			
		||||
      exports.apply(item)
 | 
			
		||||
    })
 | 
			
		||||
  } else {
 | 
			
		||||
        // console.info(param);
 | 
			
		||||
        switch(param.type){
 | 
			
		||||
            case 'addActor':
 | 
			
		||||
                exports.addActor(param.actor, param.actor, param.description);
 | 
			
		||||
                break;
 | 
			
		||||
            case 'activeStart':
 | 
			
		||||
                exports.addSignal(param.actor, undefined, undefined, param.signalType);
 | 
			
		||||
                break;
 | 
			
		||||
            case 'activeEnd':
 | 
			
		||||
                exports.addSignal(param.actor, undefined, undefined, param.signalType);
 | 
			
		||||
                break;
 | 
			
		||||
            case 'addNote':
 | 
			
		||||
                exports.addNote(param.actor,param.placement, param.text);
 | 
			
		||||
                break;
 | 
			
		||||
            case 'addMessage':
 | 
			
		||||
                exports.addSignal(param.from, param.to, param.msg, param.signalType);
 | 
			
		||||
                break;
 | 
			
		||||
            case 'loopStart':
 | 
			
		||||
                //log.debug('Loop text: ',param.loopText);
 | 
			
		||||
                exports.addSignal(undefined, undefined, param.loopText, param.signalType);
 | 
			
		||||
                //yy.addSignal(undefined, undefined, $2, yy.LINETYPE.LOOP_START);
 | 
			
		||||
                break;
 | 
			
		||||
            case 'loopEnd':
 | 
			
		||||
                exports.addSignal(undefined, undefined, undefined, param.signalType);
 | 
			
		||||
                break;
 | 
			
		||||
            case 'optStart':
 | 
			
		||||
                //log.debug('Loop text: ',param.loopText);
 | 
			
		||||
                exports.addSignal(undefined, undefined, param.optText, param.signalType);
 | 
			
		||||
                //yy.addSignal(undefined, undefined, $2, yy.LINETYPE.LOOP_START);
 | 
			
		||||
                break;
 | 
			
		||||
            case 'optEnd':
 | 
			
		||||
                exports.addSignal(undefined, undefined, undefined, param.signalType);
 | 
			
		||||
                break;
 | 
			
		||||
            case 'altStart':
 | 
			
		||||
                //log.debug('Loop text: ',param.loopText);
 | 
			
		||||
                exports.addSignal(undefined, undefined, param.altText, param.signalType);
 | 
			
		||||
                //yy.addSignal(undefined, undefined, $2, yy.LINETYPE.LOOP_START);
 | 
			
		||||
                break;
 | 
			
		||||
            case 'else':
 | 
			
		||||
                exports.addSignal(undefined, undefined, param.altText, param.signalType);
 | 
			
		||||
                break;
 | 
			
		||||
            case 'altEnd':
 | 
			
		||||
                exports.addSignal(undefined, undefined, undefined, param.signalType);
 | 
			
		||||
                break;
 | 
			
		||||
            case 'setTitle': 
 | 
			
		||||
                exports.setTitle(param.text);
 | 
			
		||||
                break;
 | 
			
		||||
            case 'parStart':
 | 
			
		||||
                exports.addSignal(undefined, undefined, param.parText, param.signalType);
 | 
			
		||||
                break;
 | 
			
		||||
            case 'and':
 | 
			
		||||
                exports.addSignal(undefined, undefined, param.parText, param.signalType);
 | 
			
		||||
                break;
 | 
			
		||||
            case 'parEnd':
 | 
			
		||||
                exports.addSignal(undefined, undefined, undefined, param.signalType);
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    switch (param.type) {
 | 
			
		||||
      case 'addActor':
 | 
			
		||||
        exports.addActor(param.actor, param.actor, param.description)
 | 
			
		||||
        break
 | 
			
		||||
      case 'activeStart':
 | 
			
		||||
        exports.addSignal(param.actor, undefined, undefined, param.signalType)
 | 
			
		||||
        break
 | 
			
		||||
      case 'activeEnd':
 | 
			
		||||
        exports.addSignal(param.actor, undefined, undefined, param.signalType)
 | 
			
		||||
        break
 | 
			
		||||
      case 'addNote':
 | 
			
		||||
        exports.addNote(param.actor, param.placement, param.text)
 | 
			
		||||
        break
 | 
			
		||||
      case 'addMessage':
 | 
			
		||||
        exports.addSignal(param.from, param.to, param.msg, param.signalType)
 | 
			
		||||
        break
 | 
			
		||||
      case 'loopStart':
 | 
			
		||||
                // log.debug('Loop text: ',param.loopText);
 | 
			
		||||
        exports.addSignal(undefined, undefined, param.loopText, param.signalType)
 | 
			
		||||
                // yy.addSignal(undefined, undefined, $2, yy.LINETYPE.LOOP_START);
 | 
			
		||||
        break
 | 
			
		||||
      case 'loopEnd':
 | 
			
		||||
        exports.addSignal(undefined, undefined, undefined, param.signalType)
 | 
			
		||||
        break
 | 
			
		||||
      case 'optStart':
 | 
			
		||||
                // log.debug('Loop text: ',param.loopText);
 | 
			
		||||
        exports.addSignal(undefined, undefined, param.optText, param.signalType)
 | 
			
		||||
                // yy.addSignal(undefined, undefined, $2, yy.LINETYPE.LOOP_START);
 | 
			
		||||
        break
 | 
			
		||||
      case 'optEnd':
 | 
			
		||||
        exports.addSignal(undefined, undefined, undefined, param.signalType)
 | 
			
		||||
        break
 | 
			
		||||
      case 'altStart':
 | 
			
		||||
                // log.debug('Loop text: ',param.loopText);
 | 
			
		||||
        exports.addSignal(undefined, undefined, param.altText, param.signalType)
 | 
			
		||||
                // yy.addSignal(undefined, undefined, $2, yy.LINETYPE.LOOP_START);
 | 
			
		||||
        break
 | 
			
		||||
      case 'else':
 | 
			
		||||
        exports.addSignal(undefined, undefined, param.altText, param.signalType)
 | 
			
		||||
        break
 | 
			
		||||
      case 'altEnd':
 | 
			
		||||
        exports.addSignal(undefined, undefined, undefined, param.signalType)
 | 
			
		||||
        break
 | 
			
		||||
      case 'setTitle':
 | 
			
		||||
        exports.setTitle(param.text)
 | 
			
		||||
        break
 | 
			
		||||
      case 'parStart':
 | 
			
		||||
        exports.addSignal(undefined, undefined, param.parText, param.signalType)
 | 
			
		||||
        break
 | 
			
		||||
      case 'and':
 | 
			
		||||
        exports.addSignal(undefined, undefined, param.parText, param.signalType)
 | 
			
		||||
        break
 | 
			
		||||
      case 'parEnd':
 | 
			
		||||
        exports.addSignal(undefined, undefined, undefined, param.signalType)
 | 
			
		||||
        break
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -2,157 +2,160 @@
 | 
			
		||||
 * Created by knut on 14-11-23.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
var sq = require('./parser/sequenceDiagram').parser;
 | 
			
		||||
sq.yy = require('./sequenceDb');
 | 
			
		||||
var svgDraw = require('./svgDraw');
 | 
			
		||||
var d3 = require('../../d3');
 | 
			
		||||
var Logger = require('../../logger');
 | 
			
		||||
var log = Logger.Log;
 | 
			
		||||
var sq = require('./parser/sequenceDiagram').parser
 | 
			
		||||
sq.yy = require('./sequenceDb')
 | 
			
		||||
var svgDraw = require('./svgDraw')
 | 
			
		||||
var d3 = require('../../d3')
 | 
			
		||||
var Logger = require('../../logger')
 | 
			
		||||
var log = Logger.Log
 | 
			
		||||
 | 
			
		||||
var conf = {
 | 
			
		||||
 | 
			
		||||
    diagramMarginX:50,
 | 
			
		||||
    diagramMarginY:30,
 | 
			
		||||
  diagramMarginX: 50,
 | 
			
		||||
  diagramMarginY: 30,
 | 
			
		||||
    // Margin between actors
 | 
			
		||||
    actorMargin:50,
 | 
			
		||||
  actorMargin: 50,
 | 
			
		||||
    // Width of actor boxes
 | 
			
		||||
    width:150,
 | 
			
		||||
  width: 150,
 | 
			
		||||
    // Height of actor boxes
 | 
			
		||||
    height:65,
 | 
			
		||||
  height: 65,
 | 
			
		||||
    // Margin around loop boxes
 | 
			
		||||
    boxMargin:10,
 | 
			
		||||
    boxTextMargin:5,
 | 
			
		||||
    noteMargin:10,
 | 
			
		||||
  boxMargin: 10,
 | 
			
		||||
  boxTextMargin: 5,
 | 
			
		||||
  noteMargin: 10,
 | 
			
		||||
    // Space between messages
 | 
			
		||||
    messageMargin:35,
 | 
			
		||||
    //mirror actors under diagram
 | 
			
		||||
    mirrorActors:false,
 | 
			
		||||
  messageMargin: 35,
 | 
			
		||||
    // mirror actors under diagram
 | 
			
		||||
  mirrorActors: false,
 | 
			
		||||
    // Depending on css styling this might need adjustment
 | 
			
		||||
    // Prolongs the edge of the diagram downwards
 | 
			
		||||
    bottomMarginAdj:1,
 | 
			
		||||
  bottomMarginAdj: 1,
 | 
			
		||||
 | 
			
		||||
    // width of activation box
 | 
			
		||||
    activationWidth:10,
 | 
			
		||||
  activationWidth: 10,
 | 
			
		||||
 | 
			
		||||
    //text placement as: tspan | fo | old only text as before 
 | 
			
		||||
    textPlacement: 'tspan', 
 | 
			
		||||
};
 | 
			
		||||
    // text placement as: tspan | fo | old only text as before
 | 
			
		||||
  textPlacement: 'tspan'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.bounds = {
 | 
			
		||||
    data:{
 | 
			
		||||
        startx:undefined,
 | 
			
		||||
        stopx :undefined,
 | 
			
		||||
        starty:undefined,
 | 
			
		||||
        stopy :undefined
 | 
			
		||||
    },
 | 
			
		||||
    verticalPos:0,
 | 
			
		||||
  data: {
 | 
			
		||||
    startx: undefined,
 | 
			
		||||
    stopx: undefined,
 | 
			
		||||
    starty: undefined,
 | 
			
		||||
    stopy: undefined
 | 
			
		||||
  },
 | 
			
		||||
  verticalPos: 0,
 | 
			
		||||
 | 
			
		||||
    sequenceItems: [],
 | 
			
		||||
    activations: [],
 | 
			
		||||
    init    : function(){
 | 
			
		||||
        this.sequenceItems = [];
 | 
			
		||||
        this.activations = [];
 | 
			
		||||
        this.data = {
 | 
			
		||||
            startx:undefined,
 | 
			
		||||
                stopx :undefined,
 | 
			
		||||
                starty:undefined,
 | 
			
		||||
                stopy :undefined
 | 
			
		||||
        };
 | 
			
		||||
        this.verticalPos =0;
 | 
			
		||||
    },
 | 
			
		||||
    updateVal : function (obj,key,val,fun){
 | 
			
		||||
        if(typeof obj[key] === 'undefined'){
 | 
			
		||||
            obj[key] = val;
 | 
			
		||||
        }else{
 | 
			
		||||
            obj[key] = fun(val,obj[key]);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    updateBounds:function(startx,starty,stopx,stopy){
 | 
			
		||||
        var _self = this;
 | 
			
		||||
        var cnt = 0;
 | 
			
		||||
        function updateFn(type) { return function updateItemBounds(item) {
 | 
			
		||||
            cnt++;
 | 
			
		||||
            // The loop sequenceItems is a stack so the biggest margins in the beginning of the sequenceItems
 | 
			
		||||
            var n = _self.sequenceItems.length-cnt+1;
 | 
			
		||||
 | 
			
		||||
            _self.updateVal(item, 'starty',starty - n*conf.boxMargin, Math.min);
 | 
			
		||||
            _self.updateVal(item, 'stopy' ,stopy  + n*conf.boxMargin, Math.max);
 | 
			
		||||
 | 
			
		||||
            _self.updateVal(exports.bounds.data, 'startx', startx - n * conf.boxMargin, Math.min);
 | 
			
		||||
            _self.updateVal(exports.bounds.data, 'stopx', stopx + n * conf.boxMargin, Math.max);
 | 
			
		||||
 | 
			
		||||
            if (!(type == 'activation')) {
 | 
			
		||||
                _self.updateVal(item, 'startx',startx - n*conf.boxMargin, Math.min);
 | 
			
		||||
                _self.updateVal(item, 'stopx' ,stopx  + n*conf.boxMargin, Math.max);
 | 
			
		||||
 | 
			
		||||
                _self.updateVal(exports.bounds.data, 'starty', starty - n * conf.boxMargin, Math.min);
 | 
			
		||||
                _self.updateVal(exports.bounds.data, 'stopy', stopy + n * conf.boxMargin, Math.max);
 | 
			
		||||
            }
 | 
			
		||||
        }}
 | 
			
		||||
 | 
			
		||||
        this.sequenceItems.forEach(updateFn());
 | 
			
		||||
        this.activations.forEach(updateFn('activation'));
 | 
			
		||||
    },
 | 
			
		||||
    insert:function(startx,starty,stopx,stopy){
 | 
			
		||||
 | 
			
		||||
        var _startx, _starty, _stopx, _stopy;
 | 
			
		||||
 | 
			
		||||
        _startx = Math.min(startx,stopx);
 | 
			
		||||
        _stopx  = Math.max(startx,stopx);
 | 
			
		||||
        _starty = Math.min(starty,stopy);
 | 
			
		||||
        _stopy  = Math.max(starty,stopy);
 | 
			
		||||
 | 
			
		||||
        this.updateVal(exports.bounds.data,'startx',_startx,Math.min);
 | 
			
		||||
        this.updateVal(exports.bounds.data,'starty',_starty,Math.min);
 | 
			
		||||
        this.updateVal(exports.bounds.data,'stopx' ,_stopx ,Math.max);
 | 
			
		||||
        this.updateVal(exports.bounds.data,'stopy' ,_stopy ,Math.max);
 | 
			
		||||
 | 
			
		||||
        this.updateBounds(_startx,_starty,_stopx,_stopy);
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
    newActivation:function(message, diagram){
 | 
			
		||||
        var actorRect = sq.yy.getActors()[message.from.actor];
 | 
			
		||||
        var stackedSize = actorActivations(message.from.actor).length;
 | 
			
		||||
        var x = actorRect.x + conf.width/2 + (stackedSize-1)*conf.activationWidth/2;
 | 
			
		||||
        this.activations.push({startx:x,starty:this.verticalPos+2,stopx:x+conf.activationWidth,stopy:undefined,
 | 
			
		||||
            actor: message.from.actor,
 | 
			
		||||
            anchored: svgDraw.anchorElement(diagram)
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
    endActivation:function(message){
 | 
			
		||||
        // find most recent activation for given actor
 | 
			
		||||
        var lastActorActivationIdx = this.activations
 | 
			
		||||
          .map(function(activation) { return activation.actor })
 | 
			
		||||
          .lastIndexOf(message.from.actor);
 | 
			
		||||
        var activation = this.activations.splice(lastActorActivationIdx, 1)[0];
 | 
			
		||||
        return activation;
 | 
			
		||||
    },
 | 
			
		||||
    newLoop:function(title){
 | 
			
		||||
        this.sequenceItems.push({startx:undefined,starty:this.verticalPos,stopx:undefined,stopy:undefined, title:title});
 | 
			
		||||
    },
 | 
			
		||||
    endLoop:function(){
 | 
			
		||||
        var loop = this.sequenceItems.pop();
 | 
			
		||||
        return loop;
 | 
			
		||||
    },
 | 
			
		||||
    addSectionToLoop: function(message) {
 | 
			
		||||
        var loop = this.sequenceItems.pop();
 | 
			
		||||
        loop.sections = loop.sections || [];
 | 
			
		||||
        loop.sectionTitles = loop.sectionTitles || [];
 | 
			
		||||
        loop.sections.push(exports.bounds.getVerticalPos());
 | 
			
		||||
        loop.sectionTitles.push(message);
 | 
			
		||||
        this.sequenceItems.push(loop);
 | 
			
		||||
    },
 | 
			
		||||
    bumpVerticalPos:function(bump){
 | 
			
		||||
        this.verticalPos = this.verticalPos + bump;
 | 
			
		||||
        this.data.stopy = this.verticalPos;
 | 
			
		||||
    },
 | 
			
		||||
    getVerticalPos:function(){
 | 
			
		||||
        return this.verticalPos;
 | 
			
		||||
    },
 | 
			
		||||
    getBounds:function(){
 | 
			
		||||
        return this.data;
 | 
			
		||||
  sequenceItems: [],
 | 
			
		||||
  activations: [],
 | 
			
		||||
  init: function () {
 | 
			
		||||
    this.sequenceItems = []
 | 
			
		||||
    this.activations = []
 | 
			
		||||
    this.data = {
 | 
			
		||||
      startx: undefined,
 | 
			
		||||
      stopx: undefined,
 | 
			
		||||
      starty: undefined,
 | 
			
		||||
      stopy: undefined
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
    this.verticalPos = 0
 | 
			
		||||
  },
 | 
			
		||||
  updateVal: function (obj, key, val, fun) {
 | 
			
		||||
    if (typeof obj[key] === 'undefined') {
 | 
			
		||||
      obj[key] = val
 | 
			
		||||
    } else {
 | 
			
		||||
      obj[key] = fun(val, obj[key])
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  updateBounds: function (startx, starty, stopx, stopy) {
 | 
			
		||||
    var _self = this
 | 
			
		||||
    var cnt = 0
 | 
			
		||||
    function updateFn (type) {
 | 
			
		||||
      return function updateItemBounds (item) {
 | 
			
		||||
        cnt++
 | 
			
		||||
            // The loop sequenceItems is a stack so the biggest margins in the beginning of the sequenceItems
 | 
			
		||||
        var n = _self.sequenceItems.length - cnt + 1
 | 
			
		||||
 | 
			
		||||
        _self.updateVal(item, 'starty', starty - n * conf.boxMargin, Math.min)
 | 
			
		||||
        _self.updateVal(item, 'stopy', stopy + n * conf.boxMargin, Math.max)
 | 
			
		||||
 | 
			
		||||
        _self.updateVal(exports.bounds.data, 'startx', startx - n * conf.boxMargin, Math.min)
 | 
			
		||||
        _self.updateVal(exports.bounds.data, 'stopx', stopx + n * conf.boxMargin, Math.max)
 | 
			
		||||
 | 
			
		||||
        if (!(type == 'activation')) {
 | 
			
		||||
          _self.updateVal(item, 'startx', startx - n * conf.boxMargin, Math.min)
 | 
			
		||||
          _self.updateVal(item, 'stopx', stopx + n * conf.boxMargin, Math.max)
 | 
			
		||||
 | 
			
		||||
          _self.updateVal(exports.bounds.data, 'starty', starty - n * conf.boxMargin, Math.min)
 | 
			
		||||
          _self.updateVal(exports.bounds.data, 'stopy', stopy + n * conf.boxMargin, Math.max)
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.sequenceItems.forEach(updateFn())
 | 
			
		||||
    this.activations.forEach(updateFn('activation'))
 | 
			
		||||
  },
 | 
			
		||||
  insert: function (startx, starty, stopx, stopy) {
 | 
			
		||||
    var _startx, _starty, _stopx, _stopy
 | 
			
		||||
 | 
			
		||||
    _startx = Math.min(startx, stopx)
 | 
			
		||||
    _stopx = Math.max(startx, stopx)
 | 
			
		||||
    _starty = Math.min(starty, stopy)
 | 
			
		||||
    _stopy = Math.max(starty, stopy)
 | 
			
		||||
 | 
			
		||||
    this.updateVal(exports.bounds.data, 'startx', _startx, Math.min)
 | 
			
		||||
    this.updateVal(exports.bounds.data, 'starty', _starty, Math.min)
 | 
			
		||||
    this.updateVal(exports.bounds.data, 'stopx', _stopx, Math.max)
 | 
			
		||||
    this.updateVal(exports.bounds.data, 'stopy', _stopy, Math.max)
 | 
			
		||||
 | 
			
		||||
    this.updateBounds(_startx, _starty, _stopx, _stopy)
 | 
			
		||||
  },
 | 
			
		||||
  newActivation: function (message, diagram) {
 | 
			
		||||
    var actorRect = sq.yy.getActors()[message.from.actor]
 | 
			
		||||
    var stackedSize = actorActivations(message.from.actor).length
 | 
			
		||||
    var x = actorRect.x + conf.width / 2 + (stackedSize - 1) * conf.activationWidth / 2
 | 
			
		||||
    this.activations.push({startx: x,
 | 
			
		||||
      starty: this.verticalPos + 2,
 | 
			
		||||
      stopx: x + conf.activationWidth,
 | 
			
		||||
      stopy: undefined,
 | 
			
		||||
      actor: message.from.actor,
 | 
			
		||||
      anchored: svgDraw.anchorElement(diagram)
 | 
			
		||||
    })
 | 
			
		||||
  },
 | 
			
		||||
  endActivation: function (message) {
 | 
			
		||||
        // find most recent activation for given actor
 | 
			
		||||
    var lastActorActivationIdx = this.activations
 | 
			
		||||
          .map(function (activation) { return activation.actor })
 | 
			
		||||
          .lastIndexOf(message.from.actor)
 | 
			
		||||
    var activation = this.activations.splice(lastActorActivationIdx, 1)[0]
 | 
			
		||||
    return activation
 | 
			
		||||
  },
 | 
			
		||||
  newLoop: function (title) {
 | 
			
		||||
    this.sequenceItems.push({startx: undefined, starty: this.verticalPos, stopx: undefined, stopy: undefined, title: title})
 | 
			
		||||
  },
 | 
			
		||||
  endLoop: function () {
 | 
			
		||||
    var loop = this.sequenceItems.pop()
 | 
			
		||||
    return loop
 | 
			
		||||
  },
 | 
			
		||||
  addSectionToLoop: function (message) {
 | 
			
		||||
    var loop = this.sequenceItems.pop()
 | 
			
		||||
    loop.sections = loop.sections || []
 | 
			
		||||
    loop.sectionTitles = loop.sectionTitles || []
 | 
			
		||||
    loop.sections.push(exports.bounds.getVerticalPos())
 | 
			
		||||
    loop.sectionTitles.push(message)
 | 
			
		||||
    this.sequenceItems.push(loop)
 | 
			
		||||
  },
 | 
			
		||||
  bumpVerticalPos: function (bump) {
 | 
			
		||||
    this.verticalPos = this.verticalPos + bump
 | 
			
		||||
    this.data.stopy = this.verticalPos
 | 
			
		||||
  },
 | 
			
		||||
  getVerticalPos: function () {
 | 
			
		||||
    return this.verticalPos
 | 
			
		||||
  },
 | 
			
		||||
  getBounds: function () {
 | 
			
		||||
    return this.data
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Draws an actor in the diagram with the attaced line
 | 
			
		||||
@@ -160,43 +163,42 @@ exports.bounds = {
 | 
			
		||||
 * @param pos The position if the actor in the liost of actors
 | 
			
		||||
 * @param description The text in the box
 | 
			
		||||
 */
 | 
			
		||||
var drawNote = function(elem, startx, verticalPos, msg, forceWidth){
 | 
			
		||||
    var rect = svgDraw.getNoteRect();
 | 
			
		||||
    rect.x = startx;
 | 
			
		||||
    rect.y = verticalPos;
 | 
			
		||||
    rect.width = forceWidth || conf.width;
 | 
			
		||||
    rect.class = 'note';
 | 
			
		||||
var drawNote = function (elem, startx, verticalPos, msg, forceWidth) {
 | 
			
		||||
  var rect = svgDraw.getNoteRect()
 | 
			
		||||
  rect.x = startx
 | 
			
		||||
  rect.y = verticalPos
 | 
			
		||||
  rect.width = forceWidth || conf.width
 | 
			
		||||
  rect.class = 'note'
 | 
			
		||||
 | 
			
		||||
    var g = elem.append('g');
 | 
			
		||||
    var rectElem = svgDraw.drawRect(g, rect);
 | 
			
		||||
  var g = elem.append('g')
 | 
			
		||||
  var rectElem = svgDraw.drawRect(g, rect)
 | 
			
		||||
 | 
			
		||||
    var textObj = svgDraw.getTextObj();
 | 
			
		||||
    textObj.x = startx-4;
 | 
			
		||||
    textObj.y = verticalPos-13;
 | 
			
		||||
    textObj.textMargin = conf.noteMargin;
 | 
			
		||||
    textObj.dy = '1em';
 | 
			
		||||
    textObj.text = msg.message;
 | 
			
		||||
    textObj.class = 'noteText';
 | 
			
		||||
  var textObj = svgDraw.getTextObj()
 | 
			
		||||
  textObj.x = startx - 4
 | 
			
		||||
  textObj.y = verticalPos - 13
 | 
			
		||||
  textObj.textMargin = conf.noteMargin
 | 
			
		||||
  textObj.dy = '1em'
 | 
			
		||||
  textObj.text = msg.message
 | 
			
		||||
  textObj.class = 'noteText'
 | 
			
		||||
 | 
			
		||||
    var textElem = svgDraw.drawText(g,textObj, rect.width-conf.noteMargin);
 | 
			
		||||
  var textElem = svgDraw.drawText(g, textObj, rect.width - conf.noteMargin)
 | 
			
		||||
 | 
			
		||||
    var textHeight = textElem[0][0].getBBox().height;
 | 
			
		||||
    if(!forceWidth && textHeight > conf.width){
 | 
			
		||||
        textElem.remove();
 | 
			
		||||
        g = elem.append('g');
 | 
			
		||||
  var textHeight = textElem[0][0].getBBox().height
 | 
			
		||||
  if (!forceWidth && textHeight > conf.width) {
 | 
			
		||||
    textElem.remove()
 | 
			
		||||
    g = elem.append('g')
 | 
			
		||||
 | 
			
		||||
        textElem = svgDraw.drawText(g,textObj, 2*rect.width-conf.noteMargin);
 | 
			
		||||
        textHeight = textElem[0][0].getBBox().height;
 | 
			
		||||
        rectElem.attr('width',2*rect.width);
 | 
			
		||||
        exports.bounds.insert(startx, verticalPos, startx + 2*rect.width,  verticalPos + 2*conf.noteMargin + textHeight);
 | 
			
		||||
    }else{
 | 
			
		||||
        exports.bounds.insert(startx, verticalPos, startx + rect.width,  verticalPos + 2*conf.noteMargin + textHeight);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    rectElem.attr('height',textHeight+ 2*conf.noteMargin);
 | 
			
		||||
    exports.bounds.bumpVerticalPos(textHeight+ 2*conf.noteMargin);
 | 
			
		||||
};
 | 
			
		||||
    textElem = svgDraw.drawText(g, textObj, 2 * rect.width - conf.noteMargin)
 | 
			
		||||
    textHeight = textElem[0][0].getBBox().height
 | 
			
		||||
    rectElem.attr('width', 2 * rect.width)
 | 
			
		||||
    exports.bounds.insert(startx, verticalPos, startx + 2 * rect.width, verticalPos + 2 * conf.noteMargin + textHeight)
 | 
			
		||||
  } else {
 | 
			
		||||
    exports.bounds.insert(startx, verticalPos, startx + rect.width, verticalPos + 2 * conf.noteMargin + textHeight)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  rectElem.attr('height', textHeight + 2 * conf.noteMargin)
 | 
			
		||||
  exports.bounds.bumpVerticalPos(textHeight + 2 * conf.noteMargin)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Draws a message
 | 
			
		||||
@@ -207,124 +209,118 @@ var drawNote = function(elem, startx, verticalPos, msg, forceWidth){
 | 
			
		||||
 * @param txtCenter
 | 
			
		||||
 * @param msg
 | 
			
		||||
 */
 | 
			
		||||
var drawMessage = function(elem, startx, stopx, verticalPos, msg){
 | 
			
		||||
    var g = elem.append('g');
 | 
			
		||||
    var txtCenter = startx + (stopx-startx)/2;
 | 
			
		||||
var drawMessage = function (elem, startx, stopx, verticalPos, msg) {
 | 
			
		||||
  var g = elem.append('g')
 | 
			
		||||
  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('y', verticalPos - 7)
 | 
			
		||||
        .style('text-anchor', 'middle')
 | 
			
		||||
        .attr('class', 'messageText')
 | 
			
		||||
        .text(msg.message);
 | 
			
		||||
        .text(msg.message)
 | 
			
		||||
 | 
			
		||||
    var textWidth;
 | 
			
		||||
  var textWidth
 | 
			
		||||
 | 
			
		||||
    if(typeof textElem[0][0].getBBox !== 'undefined'){
 | 
			
		||||
        textWidth = textElem[0][0].getBBox().width;
 | 
			
		||||
    }
 | 
			
		||||
    else{
 | 
			
		||||
        //textWidth = getBBox(textElem).width; //.getComputedTextLength()
 | 
			
		||||
        textWidth = textElem[0][0].getBoundingClientRect();
 | 
			
		||||
        //textWidth = textElem[0][0].getComputedTextLength();
 | 
			
		||||
    }
 | 
			
		||||
  if (typeof textElem[0][0].getBBox !== 'undefined') {
 | 
			
		||||
    textWidth = textElem[0][0].getBBox().width
 | 
			
		||||
  } else {
 | 
			
		||||
        // textWidth = getBBox(textElem).width; //.getComputedTextLength()
 | 
			
		||||
    textWidth = textElem[0][0].getBoundingClientRect()
 | 
			
		||||
        // textWidth = textElem[0][0].getComputedTextLength();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    var line;
 | 
			
		||||
  var line
 | 
			
		||||
 | 
			
		||||
    if(startx===stopx){
 | 
			
		||||
        line  = g.append('path')
 | 
			
		||||
            .attr('d', 'M ' +startx+ ','+verticalPos+' C ' +(startx+60)+ ','+(verticalPos-10)+' ' +(startx+60)+ ',' +
 | 
			
		||||
            (verticalPos+30)+' ' +startx+ ','+(verticalPos+20));
 | 
			
		||||
  if (startx === stopx) {
 | 
			
		||||
    line = g.append('path')
 | 
			
		||||
            .attr('d', 'M ' + startx + ',' + verticalPos + ' C ' + (startx + 60) + ',' + (verticalPos - 10) + ' ' + (startx + 60) + ',' +
 | 
			
		||||
            (verticalPos + 30) + ' ' + startx + ',' + (verticalPos + 20))
 | 
			
		||||
 | 
			
		||||
        exports.bounds.bumpVerticalPos(30);
 | 
			
		||||
        var dx = Math.max(textWidth/2,100);
 | 
			
		||||
        exports.bounds.insert(startx-dx, exports.bounds.getVerticalPos() -10, stopx+dx,  exports.bounds.getVerticalPos());
 | 
			
		||||
    }else{
 | 
			
		||||
        line = g.append('line');
 | 
			
		||||
        line.attr('x1', startx);
 | 
			
		||||
        line.attr('y1', verticalPos);
 | 
			
		||||
        line.attr('x2', stopx);
 | 
			
		||||
        line.attr('y2', verticalPos);
 | 
			
		||||
        exports.bounds.insert(startx, exports.bounds.getVerticalPos() -10, stopx,  exports.bounds.getVerticalPos());
 | 
			
		||||
    }
 | 
			
		||||
    //Make an SVG Container
 | 
			
		||||
    //Draw the line
 | 
			
		||||
    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.attr('class', 'messageLine1');
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        line.attr('class', 'messageLine0');
 | 
			
		||||
    }
 | 
			
		||||
    exports.bounds.bumpVerticalPos(30)
 | 
			
		||||
    var dx = Math.max(textWidth / 2, 100)
 | 
			
		||||
    exports.bounds.insert(startx - dx, exports.bounds.getVerticalPos() - 10, stopx + dx, exports.bounds.getVerticalPos())
 | 
			
		||||
  } else {
 | 
			
		||||
    line = g.append('line')
 | 
			
		||||
    line.attr('x1', startx)
 | 
			
		||||
    line.attr('y1', verticalPos)
 | 
			
		||||
    line.attr('x2', stopx)
 | 
			
		||||
    line.attr('y2', verticalPos)
 | 
			
		||||
    exports.bounds.insert(startx, exports.bounds.getVerticalPos() - 10, stopx, exports.bounds.getVerticalPos())
 | 
			
		||||
  }
 | 
			
		||||
    // Make an SVG Container
 | 
			
		||||
    // Draw the line
 | 
			
		||||
  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.attr('class', 'messageLine1')
 | 
			
		||||
  } else {
 | 
			
		||||
    line.attr('class', 'messageLine0')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    var url =  '';
 | 
			
		||||
    if(conf.arrowMarkerAbsolute){
 | 
			
		||||
        url =  window.location.protocol+'//'+window.location.host+window.location.pathname +window.location.search;
 | 
			
		||||
        url = url.replace(/\(/g,'\\(');
 | 
			
		||||
        url = url.replace(/\)/g,'\\)');
 | 
			
		||||
    }
 | 
			
		||||
  var url = ''
 | 
			
		||||
  if (conf.arrowMarkerAbsolute) {
 | 
			
		||||
    url = window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.search
 | 
			
		||||
    url = url.replace(/\(/g, '\\(')
 | 
			
		||||
    url = url.replace(/\)/g, '\\)')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    line.attr('stroke-width', 2);
 | 
			
		||||
    line.attr('stroke', 'black');
 | 
			
		||||
    line.style('fill', 'none');     // remove any fill colour
 | 
			
		||||
    if (msg.type === sq.yy.LINETYPE.SOLID || msg.type === sq.yy.LINETYPE.DOTTED){
 | 
			
		||||
        line.attr('marker-end', 'url(' + url + '#arrowhead)');
 | 
			
		||||
    }
 | 
			
		||||
  line.attr('stroke-width', 2)
 | 
			
		||||
  line.attr('stroke', 'black')
 | 
			
		||||
  line.style('fill', 'none')     // remove any fill colour
 | 
			
		||||
  if (msg.type === sq.yy.LINETYPE.SOLID || msg.type === sq.yy.LINETYPE.DOTTED) {
 | 
			
		||||
    line.attr('marker-end', 'url(' + url + '#arrowhead)')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    if (msg.type === sq.yy.LINETYPE.SOLID_CROSS || msg.type === sq.yy.LINETYPE.DOTTED_CROSS){
 | 
			
		||||
        line.attr('marker-end', 'url(' + url + '#crosshead)');
 | 
			
		||||
    }
 | 
			
		||||
  if (msg.type === sq.yy.LINETYPE.SOLID_CROSS || msg.type === sq.yy.LINETYPE.DOTTED_CROSS) {
 | 
			
		||||
    line.attr('marker-end', 'url(' + url + '#crosshead)')
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
module.exports.drawActors = function(diagram, actors, actorKeys,verticalPos){
 | 
			
		||||
    var i;
 | 
			
		||||
module.exports.drawActors = function (diagram, actors, actorKeys, verticalPos) {
 | 
			
		||||
  var i
 | 
			
		||||
    // Draw the actors
 | 
			
		||||
    for(i=0;i<actorKeys.length;i++){
 | 
			
		||||
        var key = actorKeys[i];
 | 
			
		||||
  for (i = 0; i < actorKeys.length; i++) {
 | 
			
		||||
    var key = actorKeys[i]
 | 
			
		||||
 | 
			
		||||
        // Add some rendering data to the object
 | 
			
		||||
        actors[key].x = i*conf.actorMargin +i*conf.width;
 | 
			
		||||
        actors[key].y = verticalPos;
 | 
			
		||||
        actors[key].width = conf.diagramMarginX;
 | 
			
		||||
        actors[key].height = conf.diagramMarginY;
 | 
			
		||||
    actors[key].x = i * conf.actorMargin + i * conf.width
 | 
			
		||||
    actors[key].y = verticalPos
 | 
			
		||||
    actors[key].width = conf.diagramMarginX
 | 
			
		||||
    actors[key].height = conf.diagramMarginY
 | 
			
		||||
 | 
			
		||||
        // Draw the box with the attached line
 | 
			
		||||
        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);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    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)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    // 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+conf.messageMargin);
 | 
			
		||||
  exports.bounds.bumpVerticalPos(conf.height)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports.setConf = function (cnf) {
 | 
			
		||||
  var keys = Object.keys(cnf)
 | 
			
		||||
 | 
			
		||||
module.exports.setConf = function(cnf){
 | 
			
		||||
    var keys = Object.keys(cnf);
 | 
			
		||||
  keys.forEach(function (key) {
 | 
			
		||||
    conf[key] = cnf[key]
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    keys.forEach(function(key){
 | 
			
		||||
        conf[key] = cnf[key];
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
var actorActivations = function (actor) {
 | 
			
		||||
  return module.exports.bounds.activations.filter(function (activation) {
 | 
			
		||||
    return activation.actor == actor
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var actorActivations = function(actor) {
 | 
			
		||||
    return module.exports.bounds.activations.filter(function(activation) {
 | 
			
		||||
        return activation.actor == actor;
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var actorFlowVerticaBounds = function(actor) {
 | 
			
		||||
var actorFlowVerticaBounds = function (actor) {
 | 
			
		||||
    // handle multiple stacked activations for same actor
 | 
			
		||||
    var actors = sq.yy.getActors();
 | 
			
		||||
    var activations = actorActivations(actor);
 | 
			
		||||
  var actors = sq.yy.getActors()
 | 
			
		||||
  var activations = actorActivations(actor)
 | 
			
		||||
 | 
			
		||||
    var left = activations.reduce(function(acc,activation) { return Math.min(acc,activation.startx)}, actors[actor].x + conf.width/2);
 | 
			
		||||
    var right = activations.reduce(function(acc,activation) { return Math.max(acc,activation.stopx)}, actors[actor].x + conf.width/2);
 | 
			
		||||
    return [left,right];
 | 
			
		||||
};
 | 
			
		||||
  var left = activations.reduce(function (acc, activation) { return Math.min(acc, activation.startx) }, actors[actor].x + conf.width / 2)
 | 
			
		||||
  var right = activations.reduce(function (acc, activation) { return Math.max(acc, activation.stopx) }, actors[actor].x + conf.width / 2)
 | 
			
		||||
  return [left, right]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Draws a flowchart in the tag with id: id based on the graph definition in text.
 | 
			
		||||
@@ -332,184 +328,181 @@ var actorFlowVerticaBounds = function(actor) {
 | 
			
		||||
 * @param id
 | 
			
		||||
 */
 | 
			
		||||
module.exports.draw = function (text, id) {
 | 
			
		||||
    sq.yy.clear();
 | 
			
		||||
    sq.parse(text+'\n');
 | 
			
		||||
  sq.yy.clear()
 | 
			
		||||
  sq.parse(text + '\n')
 | 
			
		||||
 | 
			
		||||
    exports.bounds.init();
 | 
			
		||||
    var diagram = d3.select('#'+id);
 | 
			
		||||
  exports.bounds.init()
 | 
			
		||||
  var diagram = d3.select('#' + id)
 | 
			
		||||
 | 
			
		||||
    var startx;
 | 
			
		||||
    var stopx;
 | 
			
		||||
    var forceWidth;
 | 
			
		||||
  var startx
 | 
			
		||||
  var stopx
 | 
			
		||||
  var forceWidth
 | 
			
		||||
 | 
			
		||||
    // Fetch data from the parsing
 | 
			
		||||
    var actors = sq.yy.getActors();
 | 
			
		||||
    var actorKeys = sq.yy.getActorKeys();
 | 
			
		||||
    var messages = sq.yy.getMessages();
 | 
			
		||||
    var title = sq.yy.getTitle();
 | 
			
		||||
    module.exports.drawActors(diagram, actors, actorKeys, 0);
 | 
			
		||||
  var actors = sq.yy.getActors()
 | 
			
		||||
  var actorKeys = sq.yy.getActorKeys()
 | 
			
		||||
  var messages = sq.yy.getMessages()
 | 
			
		||||
  var title = sq.yy.getTitle()
 | 
			
		||||
  module.exports.drawActors(diagram, actors, actorKeys, 0)
 | 
			
		||||
 | 
			
		||||
    // The arrow head definition is attached to the svg once
 | 
			
		||||
    svgDraw.insertArrowHead(diagram);
 | 
			
		||||
    svgDraw.insertArrowCrossHead(diagram);
 | 
			
		||||
  svgDraw.insertArrowHead(diagram)
 | 
			
		||||
  svgDraw.insertArrowCrossHead(diagram)
 | 
			
		||||
 | 
			
		||||
    function activeEnd(msg, verticalPos) {
 | 
			
		||||
        var activationData = exports.bounds.endActivation(msg);
 | 
			
		||||
        if(activationData.starty + 18 > verticalPos) {
 | 
			
		||||
            activationData.starty = verticalPos - 6;
 | 
			
		||||
            verticalPos += 12;
 | 
			
		||||
        }
 | 
			
		||||
        svgDraw.drawActivation(diagram, activationData, verticalPos, conf);
 | 
			
		||||
 | 
			
		||||
        exports.bounds.insert(activationData.startx, verticalPos -10, activationData.stopx,  verticalPos);
 | 
			
		||||
  function activeEnd (msg, verticalPos) {
 | 
			
		||||
    var activationData = exports.bounds.endActivation(msg)
 | 
			
		||||
    if (activationData.starty + 18 > verticalPos) {
 | 
			
		||||
      activationData.starty = verticalPos - 6
 | 
			
		||||
      verticalPos += 12
 | 
			
		||||
    }
 | 
			
		||||
    svgDraw.drawActivation(diagram, activationData, verticalPos, conf)
 | 
			
		||||
 | 
			
		||||
    var lastMsg;
 | 
			
		||||
    exports.bounds.insert(activationData.startx, verticalPos - 10, activationData.stopx, verticalPos)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  var lastMsg
 | 
			
		||||
 | 
			
		||||
    // Draw the messages/signals
 | 
			
		||||
    messages.forEach(function(msg){
 | 
			
		||||
        var loopData;
 | 
			
		||||
  messages.forEach(function (msg) {
 | 
			
		||||
    var loopData
 | 
			
		||||
 | 
			
		||||
        switch(msg.type){
 | 
			
		||||
            case sq.yy.LINETYPE.NOTE:
 | 
			
		||||
                exports.bounds.bumpVerticalPos(conf.boxMargin);
 | 
			
		||||
    switch (msg.type) {
 | 
			
		||||
      case sq.yy.LINETYPE.NOTE:
 | 
			
		||||
        exports.bounds.bumpVerticalPos(conf.boxMargin)
 | 
			
		||||
 | 
			
		||||
                startx = actors[msg.from].x;
 | 
			
		||||
                stopx = actors[msg.to].x;
 | 
			
		||||
        startx = actors[msg.from].x
 | 
			
		||||
        stopx = actors[msg.to].x
 | 
			
		||||
 | 
			
		||||
                if(msg.placement === sq.yy.PLACEMENT.RIGHTOF){
 | 
			
		||||
                    drawNote(diagram, startx + (conf.width + conf.actorMargin)/2, exports.bounds.getVerticalPos(), msg);
 | 
			
		||||
 | 
			
		||||
                }else if(msg.placement === sq.yy.PLACEMENT.LEFTOF){
 | 
			
		||||
                    drawNote(diagram, startx - (conf.width + conf.actorMargin)/2, exports.bounds.getVerticalPos(), msg);
 | 
			
		||||
                }else if(msg.to === msg.from) {
 | 
			
		||||
        if (msg.placement === sq.yy.PLACEMENT.RIGHTOF) {
 | 
			
		||||
          drawNote(diagram, startx + (conf.width + conf.actorMargin) / 2, exports.bounds.getVerticalPos(), msg)
 | 
			
		||||
        } else if (msg.placement === sq.yy.PLACEMENT.LEFTOF) {
 | 
			
		||||
          drawNote(diagram, startx - (conf.width + conf.actorMargin) / 2, exports.bounds.getVerticalPos(), msg)
 | 
			
		||||
        } else if (msg.to === msg.from) {
 | 
			
		||||
                    // Single-actor over
 | 
			
		||||
                    drawNote(diagram, startx, exports.bounds.getVerticalPos(), msg);
 | 
			
		||||
                }else{
 | 
			
		||||
          drawNote(diagram, startx, exports.bounds.getVerticalPos(), msg)
 | 
			
		||||
        } else {
 | 
			
		||||
                    // Multi-actor over
 | 
			
		||||
                    forceWidth = Math.abs(startx - stopx) + conf.actorMargin;
 | 
			
		||||
                    drawNote(diagram, (startx + stopx + conf.width - forceWidth)/2, exports.bounds.getVerticalPos(), msg,
 | 
			
		||||
                        forceWidth);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case sq.yy.LINETYPE.ACTIVE_START:
 | 
			
		||||
                exports.bounds.newActivation(msg, diagram);
 | 
			
		||||
                break;
 | 
			
		||||
            case sq.yy.LINETYPE.ACTIVE_END:
 | 
			
		||||
                activeEnd(msg, exports.bounds.getVerticalPos());
 | 
			
		||||
                break;
 | 
			
		||||
            case sq.yy.LINETYPE.LOOP_START:
 | 
			
		||||
                exports.bounds.bumpVerticalPos(conf.boxMargin);
 | 
			
		||||
                exports.bounds.newLoop(msg.message);
 | 
			
		||||
                exports.bounds.bumpVerticalPos(conf.boxMargin + conf.boxTextMargin);
 | 
			
		||||
                break;
 | 
			
		||||
            case sq.yy.LINETYPE.LOOP_END:
 | 
			
		||||
                loopData = exports.bounds.endLoop();
 | 
			
		||||
 | 
			
		||||
                svgDraw.drawLoop(diagram, loopData,'loop', conf);
 | 
			
		||||
                exports.bounds.bumpVerticalPos(conf.boxMargin);
 | 
			
		||||
                break;
 | 
			
		||||
            case sq.yy.LINETYPE.OPT_START:
 | 
			
		||||
                exports.bounds.bumpVerticalPos(conf.boxMargin);
 | 
			
		||||
                exports.bounds.newLoop(msg.message);
 | 
			
		||||
                exports.bounds.bumpVerticalPos(conf.boxMargin + conf.boxTextMargin);
 | 
			
		||||
                break;
 | 
			
		||||
            case sq.yy.LINETYPE.OPT_END:
 | 
			
		||||
                loopData = exports.bounds.endLoop();
 | 
			
		||||
 | 
			
		||||
                svgDraw.drawLoop(diagram, loopData, 'opt', conf);
 | 
			
		||||
                exports.bounds.bumpVerticalPos(conf.boxMargin);
 | 
			
		||||
                break;
 | 
			
		||||
            case sq.yy.LINETYPE.ALT_START:
 | 
			
		||||
                exports.bounds.bumpVerticalPos(conf.boxMargin);
 | 
			
		||||
                exports.bounds.newLoop(msg.message);
 | 
			
		||||
                exports.bounds.bumpVerticalPos(conf.boxMargin + conf.boxTextMargin);
 | 
			
		||||
                break;
 | 
			
		||||
            case sq.yy.LINETYPE.ALT_ELSE:
 | 
			
		||||
                exports.bounds.bumpVerticalPos(conf.boxMargin);
 | 
			
		||||
                loopData = exports.bounds.addSectionToLoop(msg.message);
 | 
			
		||||
                exports.bounds.bumpVerticalPos(conf.boxMargin);
 | 
			
		||||
                break;
 | 
			
		||||
            case sq.yy.LINETYPE.ALT_END:
 | 
			
		||||
                loopData = exports.bounds.endLoop();
 | 
			
		||||
 | 
			
		||||
                svgDraw.drawLoop(diagram, loopData,'alt', conf);
 | 
			
		||||
                exports.bounds.bumpVerticalPos(conf.boxMargin);
 | 
			
		||||
                break;
 | 
			
		||||
            case sq.yy.LINETYPE.PAR_START:
 | 
			
		||||
                exports.bounds.bumpVerticalPos(conf.boxMargin);
 | 
			
		||||
                exports.bounds.newLoop(msg.message);
 | 
			
		||||
                exports.bounds.bumpVerticalPos(conf.boxMargin + conf.boxTextMargin);
 | 
			
		||||
                break;
 | 
			
		||||
            case sq.yy.LINETYPE.PAR_AND:
 | 
			
		||||
                exports.bounds.bumpVerticalPos(conf.boxMargin);
 | 
			
		||||
                loopData = exports.bounds.addSectionToLoop(msg.message);
 | 
			
		||||
                exports.bounds.bumpVerticalPos(conf.boxMargin);
 | 
			
		||||
                break;
 | 
			
		||||
            case sq.yy.LINETYPE.PAR_END:
 | 
			
		||||
                loopData = exports.bounds.endLoop();
 | 
			
		||||
                svgDraw.drawLoop(diagram, loopData, 'par', conf);
 | 
			
		||||
                exports.bounds.bumpVerticalPos(conf.boxMargin);
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
              try {
 | 
			
		||||
                lastMsg = msg;
 | 
			
		||||
                exports.bounds.bumpVerticalPos(conf.messageMargin);
 | 
			
		||||
                var fromBounds = actorFlowVerticaBounds(msg.from);
 | 
			
		||||
                var toBounds = actorFlowVerticaBounds(msg.to);
 | 
			
		||||
                var fromIdx = fromBounds[0] <= toBounds[0]?1:0;
 | 
			
		||||
                var toIdx = fromBounds[0] < toBounds[0]?0:1;
 | 
			
		||||
                startx = fromBounds[fromIdx];
 | 
			
		||||
                stopx = toBounds[toIdx];
 | 
			
		||||
 | 
			
		||||
                var verticalPos = exports.bounds.getVerticalPos();
 | 
			
		||||
                drawMessage(diagram, startx, stopx, verticalPos, msg);
 | 
			
		||||
                var allBounds = fromBounds.concat(toBounds);
 | 
			
		||||
                exports.bounds.insert(Math.min.apply(null, allBounds), verticalPos, Math.max.apply(null, allBounds), verticalPos);
 | 
			
		||||
              } catch (e) {
 | 
			
		||||
                  console.error('error while drawing message', e);
 | 
			
		||||
              }
 | 
			
		||||
          forceWidth = Math.abs(startx - stopx) + conf.actorMargin
 | 
			
		||||
          drawNote(diagram, (startx + stopx + conf.width - forceWidth) / 2, exports.bounds.getVerticalPos(), msg,
 | 
			
		||||
                        forceWidth)
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
        break
 | 
			
		||||
      case sq.yy.LINETYPE.ACTIVE_START:
 | 
			
		||||
        exports.bounds.newActivation(msg, diagram)
 | 
			
		||||
        break
 | 
			
		||||
      case sq.yy.LINETYPE.ACTIVE_END:
 | 
			
		||||
        activeEnd(msg, exports.bounds.getVerticalPos())
 | 
			
		||||
        break
 | 
			
		||||
      case sq.yy.LINETYPE.LOOP_START:
 | 
			
		||||
        exports.bounds.bumpVerticalPos(conf.boxMargin)
 | 
			
		||||
        exports.bounds.newLoop(msg.message)
 | 
			
		||||
        exports.bounds.bumpVerticalPos(conf.boxMargin + conf.boxTextMargin)
 | 
			
		||||
        break
 | 
			
		||||
      case sq.yy.LINETYPE.LOOP_END:
 | 
			
		||||
        loopData = exports.bounds.endLoop()
 | 
			
		||||
 | 
			
		||||
        svgDraw.drawLoop(diagram, loopData, 'loop', conf)
 | 
			
		||||
        exports.bounds.bumpVerticalPos(conf.boxMargin)
 | 
			
		||||
        break
 | 
			
		||||
      case sq.yy.LINETYPE.OPT_START:
 | 
			
		||||
        exports.bounds.bumpVerticalPos(conf.boxMargin)
 | 
			
		||||
        exports.bounds.newLoop(msg.message)
 | 
			
		||||
        exports.bounds.bumpVerticalPos(conf.boxMargin + conf.boxTextMargin)
 | 
			
		||||
        break
 | 
			
		||||
      case sq.yy.LINETYPE.OPT_END:
 | 
			
		||||
        loopData = exports.bounds.endLoop()
 | 
			
		||||
 | 
			
		||||
    if(conf.mirrorActors){
 | 
			
		||||
        // Draw actors below diagram
 | 
			
		||||
        exports.bounds.bumpVerticalPos(conf.boxMargin*2);
 | 
			
		||||
        module.exports.drawActors(diagram, actors, actorKeys, exports.bounds.getVerticalPos());
 | 
			
		||||
        svgDraw.drawLoop(diagram, loopData, 'opt', conf)
 | 
			
		||||
        exports.bounds.bumpVerticalPos(conf.boxMargin)
 | 
			
		||||
        break
 | 
			
		||||
      case sq.yy.LINETYPE.ALT_START:
 | 
			
		||||
        exports.bounds.bumpVerticalPos(conf.boxMargin)
 | 
			
		||||
        exports.bounds.newLoop(msg.message)
 | 
			
		||||
        exports.bounds.bumpVerticalPos(conf.boxMargin + conf.boxTextMargin)
 | 
			
		||||
        break
 | 
			
		||||
      case sq.yy.LINETYPE.ALT_ELSE:
 | 
			
		||||
        exports.bounds.bumpVerticalPos(conf.boxMargin)
 | 
			
		||||
        loopData = exports.bounds.addSectionToLoop(msg.message)
 | 
			
		||||
        exports.bounds.bumpVerticalPos(conf.boxMargin)
 | 
			
		||||
        break
 | 
			
		||||
      case sq.yy.LINETYPE.ALT_END:
 | 
			
		||||
        loopData = exports.bounds.endLoop()
 | 
			
		||||
 | 
			
		||||
        svgDraw.drawLoop(diagram, loopData, 'alt', conf)
 | 
			
		||||
        exports.bounds.bumpVerticalPos(conf.boxMargin)
 | 
			
		||||
        break
 | 
			
		||||
      case sq.yy.LINETYPE.PAR_START:
 | 
			
		||||
        exports.bounds.bumpVerticalPos(conf.boxMargin)
 | 
			
		||||
        exports.bounds.newLoop(msg.message)
 | 
			
		||||
        exports.bounds.bumpVerticalPos(conf.boxMargin + conf.boxTextMargin)
 | 
			
		||||
        break
 | 
			
		||||
      case sq.yy.LINETYPE.PAR_AND:
 | 
			
		||||
        exports.bounds.bumpVerticalPos(conf.boxMargin)
 | 
			
		||||
        loopData = exports.bounds.addSectionToLoop(msg.message)
 | 
			
		||||
        exports.bounds.bumpVerticalPos(conf.boxMargin)
 | 
			
		||||
        break
 | 
			
		||||
      case sq.yy.LINETYPE.PAR_END:
 | 
			
		||||
        loopData = exports.bounds.endLoop()
 | 
			
		||||
        svgDraw.drawLoop(diagram, loopData, 'par', conf)
 | 
			
		||||
        exports.bounds.bumpVerticalPos(conf.boxMargin)
 | 
			
		||||
        break
 | 
			
		||||
      default:
 | 
			
		||||
        try {
 | 
			
		||||
          lastMsg = msg
 | 
			
		||||
          exports.bounds.bumpVerticalPos(conf.messageMargin)
 | 
			
		||||
          var fromBounds = actorFlowVerticaBounds(msg.from)
 | 
			
		||||
          var toBounds = actorFlowVerticaBounds(msg.to)
 | 
			
		||||
          var fromIdx = fromBounds[0] <= toBounds[0] ? 1 : 0
 | 
			
		||||
          var toIdx = fromBounds[0] < toBounds[0] ? 0 : 1
 | 
			
		||||
          startx = fromBounds[fromIdx]
 | 
			
		||||
          stopx = toBounds[toIdx]
 | 
			
		||||
 | 
			
		||||
          var verticalPos = exports.bounds.getVerticalPos()
 | 
			
		||||
          drawMessage(diagram, startx, stopx, verticalPos, msg)
 | 
			
		||||
          var allBounds = fromBounds.concat(toBounds)
 | 
			
		||||
          exports.bounds.insert(Math.min.apply(null, allBounds), verticalPos, Math.max.apply(null, allBounds), verticalPos)
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
          console.error('error while drawing message', e)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
    var box = exports.bounds.getBounds();
 | 
			
		||||
  if (conf.mirrorActors) {
 | 
			
		||||
        // Draw actors below diagram
 | 
			
		||||
    exports.bounds.bumpVerticalPos(conf.boxMargin * 2)
 | 
			
		||||
    module.exports.drawActors(diagram, actors, actorKeys, exports.bounds.getVerticalPos())
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  var box = exports.bounds.getBounds()
 | 
			
		||||
 | 
			
		||||
    // 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');
 | 
			
		||||
    var actorLines = d3.selectAll('#' + id + ' .actor-line');
 | 
			
		||||
    actorLines.attr('y2',box.stopy);
 | 
			
		||||
  log.debug('For line height fix Querying: #' + id + ' .actor-line')
 | 
			
		||||
  var actorLines = d3.selectAll('#' + id + ' .actor-line')
 | 
			
		||||
  actorLines.attr('y2', box.stopy)
 | 
			
		||||
 | 
			
		||||
  var height = box.stopy - box.starty + 2 * conf.diagramMarginY
 | 
			
		||||
 | 
			
		||||
    var height = box.stopy - box.starty + 2*conf.diagramMarginY;
 | 
			
		||||
  if (conf.mirrorActors) {
 | 
			
		||||
    height = height - conf.boxMargin + conf.bottomMarginAdj
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    if(conf.mirrorActors){
 | 
			
		||||
        height = height - conf.boxMargin + conf.bottomMarginAdj;
 | 
			
		||||
    }
 | 
			
		||||
  var width = (box.stopx - box.startx) + (2 * conf.diagramMarginX)
 | 
			
		||||
 | 
			
		||||
    var width = (box.stopx - box.startx) + (2 * conf.diagramMarginX);
 | 
			
		||||
 | 
			
		||||
    if(title) {
 | 
			
		||||
      diagram.append('text')
 | 
			
		||||
  if (title) {
 | 
			
		||||
    diagram.append('text')
 | 
			
		||||
        .text(title)
 | 
			
		||||
        .attr('x', ( ( box.stopx-box.startx) / 2 ) - ( 2 * conf.diagramMarginX ) )
 | 
			
		||||
        .attr('y', -25);
 | 
			
		||||
    }
 | 
			
		||||
        .attr('x', ((box.stopx - box.startx) / 2) - (2 * conf.diagramMarginX))
 | 
			
		||||
        .attr('y', -25)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    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 );
 | 
			
		||||
    }
 | 
			
		||||
    var extraVertForTitle = title ? 40 : 0;
 | 
			
		||||
    diagram.attr('viewBox', (box.startx - conf.diagramMarginX) + ' -' + (conf.diagramMarginY + extraVertForTitle) + ' ' + width + ' ' + (height + extraVertForTitle));
 | 
			
		||||
};
 | 
			
		||||
  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)
 | 
			
		||||
  }
 | 
			
		||||
  var extraVertForTitle = title ? 40 : 0
 | 
			
		||||
  diagram.attr('viewBox', (box.startx - conf.diagramMarginX) + ' -' + (conf.diagramMarginY + extraVertForTitle) + ' ' + width + ' ' + (height + extraVertForTitle))
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,140 +1,138 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Created by knut on 14-12-20.
 | 
			
		||||
 */
 | 
			
		||||
//var log = require('../../logger').create();
 | 
			
		||||
exports.drawRect = function(elem , rectData){
 | 
			
		||||
    var rectElem = elem.append('rect');
 | 
			
		||||
    rectElem.attr('x', rectData.x);
 | 
			
		||||
    rectElem.attr('y', rectData.y);
 | 
			
		||||
    rectElem.attr('fill', rectData.fill);
 | 
			
		||||
    rectElem.attr('stroke', rectData.stroke);
 | 
			
		||||
    rectElem.attr('width', rectData.width);
 | 
			
		||||
    rectElem.attr('height', rectData.height);
 | 
			
		||||
    rectElem.attr('rx', rectData.rx);
 | 
			
		||||
    rectElem.attr('ry', rectData.ry);
 | 
			
		||||
// var log = require('../../logger').create();
 | 
			
		||||
exports.drawRect = function (elem, rectData) {
 | 
			
		||||
  var rectElem = elem.append('rect')
 | 
			
		||||
  rectElem.attr('x', rectData.x)
 | 
			
		||||
  rectElem.attr('y', rectData.y)
 | 
			
		||||
  rectElem.attr('fill', rectData.fill)
 | 
			
		||||
  rectElem.attr('stroke', rectData.stroke)
 | 
			
		||||
  rectElem.attr('width', rectData.width)
 | 
			
		||||
  rectElem.attr('height', rectData.height)
 | 
			
		||||
  rectElem.attr('rx', rectData.rx)
 | 
			
		||||
  rectElem.attr('ry', rectData.ry)
 | 
			
		||||
 | 
			
		||||
    if(typeof rectData.class !== 'undefined'){
 | 
			
		||||
        rectElem.attr('class', rectData.class);
 | 
			
		||||
    }
 | 
			
		||||
  if (typeof rectData.class !== 'undefined') {
 | 
			
		||||
    rectElem.attr('class', rectData.class)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    return rectElem;
 | 
			
		||||
};
 | 
			
		||||
  return rectElem
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.drawText = function(elem, textData, width) {
 | 
			
		||||
exports.drawText = function (elem, textData, width) {
 | 
			
		||||
    // Remove and ignore br:s
 | 
			
		||||
    var nText = textData.text.replace(/<br\/?>/ig,' ');
 | 
			
		||||
  var nText = textData.text.replace(/<br\/?>/ig, ' ')
 | 
			
		||||
 | 
			
		||||
    var textElem = elem.append('text');
 | 
			
		||||
    textElem.attr('x', textData.x);
 | 
			
		||||
    textElem.attr('y', textData.y);
 | 
			
		||||
    textElem.style('text-anchor', textData.anchor);
 | 
			
		||||
    textElem.attr('fill', textData.fill);
 | 
			
		||||
    if (typeof textData.class !== 'undefined') {
 | 
			
		||||
        textElem.attr('class', textData.class);
 | 
			
		||||
    }
 | 
			
		||||
  var textElem = elem.append('text')
 | 
			
		||||
  textElem.attr('x', textData.x)
 | 
			
		||||
  textElem.attr('y', textData.y)
 | 
			
		||||
  textElem.style('text-anchor', textData.anchor)
 | 
			
		||||
  textElem.attr('fill', textData.fill)
 | 
			
		||||
  if (typeof textData.class !== 'undefined') {
 | 
			
		||||
    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')
 | 
			
		||||
    // span.attr('x', textData.x);
 | 
			
		||||
  span.attr('x', textData.x + textData.textMargin * 2)
 | 
			
		||||
    // span.attr('dy', textData.dy);
 | 
			
		||||
  span.attr('fill', textData.fill)
 | 
			
		||||
  span.text(nText)
 | 
			
		||||
  if (typeof textElem.textwrap !== 'undefined') {
 | 
			
		||||
    textElem.textwrap({
 | 
			
		||||
      x: textData.x, // bounding box is 300 pixels from the left
 | 
			
		||||
      y: textData.y, // bounding box is 400 pixels from the top
 | 
			
		||||
      width: width, // bounding box is 500 pixels across
 | 
			
		||||
      height: 1800 // bounding box is 600 pixels tall
 | 
			
		||||
    }, textData.textMargin)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    var span = textElem.append('tspan');
 | 
			
		||||
    //span.attr('x', textData.x);
 | 
			
		||||
    span.attr('x', textData.x+textData.textMargin*2);
 | 
			
		||||
    //span.attr('dy', textData.dy);
 | 
			
		||||
    span.attr("fill", textData.fill);
 | 
			
		||||
    span.text(nText);
 | 
			
		||||
    if(typeof textElem.textwrap !== 'undefined'){
 | 
			
		||||
 | 
			
		||||
        textElem.textwrap({
 | 
			
		||||
            x: textData.x, // bounding box is 300 pixels from the left
 | 
			
		||||
            y: textData.y, // bounding box is 400 pixels from the top
 | 
			
		||||
            width: width, // bounding box is 500 pixels across
 | 
			
		||||
            height: 1800 // bounding box is 600 pixels tall
 | 
			
		||||
        }, textData.textMargin);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return textElem;
 | 
			
		||||
};
 | 
			
		||||
  return textElem
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.drawLabel = function (elem, txtObject) {
 | 
			
		||||
    function genPoints(x, y, width, height, cut) {
 | 
			
		||||
        return x + "," + y + " " +
 | 
			
		||||
            (x + width) + "," + y + " " +
 | 
			
		||||
            (x + width) + "," + (y + height - cut) + " " +
 | 
			
		||||
            (x + width - cut * 1.2) + "," + (y + height) + " " +
 | 
			
		||||
            (x) + "," + (y + height);
 | 
			
		||||
    }
 | 
			
		||||
    var polygon = elem.append("polygon");
 | 
			
		||||
    polygon.attr("points" , genPoints(txtObject.x, txtObject.y, 50, 20, 7));
 | 
			
		||||
    polygon.attr("style", "fill:#526e52;stroke:none");
 | 
			
		||||
  function genPoints (x, y, width, height, cut) {
 | 
			
		||||
    return x + ',' + y + ' ' +
 | 
			
		||||
            (x + width) + ',' + y + ' ' +
 | 
			
		||||
            (x + width) + ',' + (y + height - cut) + ' ' +
 | 
			
		||||
            (x + width - cut * 1.2) + ',' + (y + height) + ' ' +
 | 
			
		||||
            (x) + ',' + (y + height)
 | 
			
		||||
  }
 | 
			
		||||
  var polygon = elem.append('polygon')
 | 
			
		||||
  polygon.attr('points', genPoints(txtObject.x, txtObject.y, 50, 20, 7))
 | 
			
		||||
  polygon.attr('style', 'fill:#526e52;stroke:none')
 | 
			
		||||
 | 
			
		||||
    txtObject.y = txtObject.y + txtObject.labelMargin;
 | 
			
		||||
    txtObject.x = txtObject.x + 0.5 * txtObject.labelMargin;
 | 
			
		||||
    txtObject.fill = 'white';
 | 
			
		||||
    exports.drawText(elem, txtObject);
 | 
			
		||||
  txtObject.y = txtObject.y + txtObject.labelMargin
 | 
			
		||||
  txtObject.x = txtObject.x + 0.5 * txtObject.labelMargin
 | 
			
		||||
  txtObject.fill = 'white'
 | 
			
		||||
  exports.drawText(elem, txtObject)
 | 
			
		||||
 | 
			
		||||
    //return textElem;
 | 
			
		||||
};
 | 
			
		||||
var actorCnt  = -1;
 | 
			
		||||
    // return textElem;
 | 
			
		||||
}
 | 
			
		||||
var actorCnt = -1
 | 
			
		||||
/**
 | 
			
		||||
 * Draws an actor in the diagram with the attaced line
 | 
			
		||||
 * @param center - The center of the the actor
 | 
			
		||||
 * @param pos The position if the actor in the liost of actors
 | 
			
		||||
 * @param description The text in the box
 | 
			
		||||
 */
 | 
			
		||||
exports.drawActor = function(elem, left, verticalPos, description,conf){
 | 
			
		||||
    var center = left + (conf.width/2);
 | 
			
		||||
    var g = elem.append('g');
 | 
			
		||||
    if(verticalPos === 0) {
 | 
			
		||||
        actorCnt++;
 | 
			
		||||
        g.append('line')
 | 
			
		||||
            .attr('id', 'actor'+actorCnt)
 | 
			
		||||
exports.drawActor = function (elem, left, verticalPos, description, conf) {
 | 
			
		||||
  var center = left + (conf.width / 2)
 | 
			
		||||
  var g = elem.append('g')
 | 
			
		||||
  if (verticalPos === 0) {
 | 
			
		||||
    actorCnt++
 | 
			
		||||
    g.append('line')
 | 
			
		||||
            .attr('id', 'actor' + actorCnt)
 | 
			
		||||
            .attr('x1', center)
 | 
			
		||||
            .attr('y1', 5)
 | 
			
		||||
            .attr('x2', center)
 | 
			
		||||
            .attr('y2', 2000)
 | 
			
		||||
            .attr('class', 'actor-line')
 | 
			
		||||
            .attr('stroke-width', '0.5px')
 | 
			
		||||
            .attr('stroke', '#999');
 | 
			
		||||
    }
 | 
			
		||||
            .attr('stroke', '#999')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    var rect = exports.getNoteRect();
 | 
			
		||||
    rect.x = left;
 | 
			
		||||
    rect.y = verticalPos;
 | 
			
		||||
    rect.fill = '#eaeaea';
 | 
			
		||||
    rect.width = conf.width;
 | 
			
		||||
    rect.height = conf.height;
 | 
			
		||||
    rect.class = 'actor';
 | 
			
		||||
    rect.rx = 3;
 | 
			
		||||
    rect.ry = 3;
 | 
			
		||||
    exports.drawRect(g, rect);
 | 
			
		||||
  var rect = exports.getNoteRect()
 | 
			
		||||
  rect.x = left
 | 
			
		||||
  rect.y = verticalPos
 | 
			
		||||
  rect.fill = '#eaeaea'
 | 
			
		||||
  rect.width = conf.width
 | 
			
		||||
  rect.height = conf.height
 | 
			
		||||
  rect.class = 'actor'
 | 
			
		||||
  rect.rx = 3
 | 
			
		||||
  rect.ry = 3
 | 
			
		||||
  exports.drawRect(g, rect)
 | 
			
		||||
 | 
			
		||||
    _drawTextCandidateFunc(conf)(description, g, 
 | 
			
		||||
        rect.x, rect.y, rect.width, rect.height, {'class':'actor'});
 | 
			
		||||
};
 | 
			
		||||
  _drawTextCandidateFunc(conf)(description, g,
 | 
			
		||||
        rect.x, rect.y, rect.width, rect.height, {'class': 'actor'})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.anchorElement = function(elem) {
 | 
			
		||||
    return elem.append('g');
 | 
			
		||||
};
 | 
			
		||||
exports.anchorElement = function (elem) {
 | 
			
		||||
  return elem.append('g')
 | 
			
		||||
}
 | 
			
		||||
/**
 | 
			
		||||
 * Draws an actor in the diagram with the attaced line
 | 
			
		||||
 * @param elem - element to append activation rect
 | 
			
		||||
 * @param bounds - activation box bounds
 | 
			
		||||
 * @param verticalPos - precise y cooridnate of bottom activation box edge
 | 
			
		||||
 */
 | 
			
		||||
exports.drawActivation = function(elem,bounds,verticalPos){
 | 
			
		||||
    var rect = exports.getNoteRect();
 | 
			
		||||
    var g = bounds.anchored;
 | 
			
		||||
    rect.x = bounds.startx;
 | 
			
		||||
    rect.y = bounds.starty;
 | 
			
		||||
    rect.fill = '#f4f4f4';
 | 
			
		||||
    rect.width = bounds.stopx - bounds.startx;
 | 
			
		||||
    rect.height = verticalPos - bounds.starty;
 | 
			
		||||
    exports.drawRect(g, rect);
 | 
			
		||||
};
 | 
			
		||||
exports.drawActivation = function (elem, bounds, verticalPos) {
 | 
			
		||||
  var rect = exports.getNoteRect()
 | 
			
		||||
  var g = bounds.anchored
 | 
			
		||||
  rect.x = bounds.startx
 | 
			
		||||
  rect.y = bounds.starty
 | 
			
		||||
  rect.fill = '#f4f4f4'
 | 
			
		||||
  rect.width = bounds.stopx - bounds.startx
 | 
			
		||||
  rect.height = verticalPos - bounds.starty
 | 
			
		||||
  exports.drawRect(g, rect)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Draws an actor in the diagram with the attaced line
 | 
			
		||||
@@ -142,63 +140,63 @@ exports.drawActivation = function(elem,bounds,verticalPos){
 | 
			
		||||
 * @param pos The position if the actor in the list of actors
 | 
			
		||||
 * @param description The text in the box
 | 
			
		||||
 */
 | 
			
		||||
exports.drawLoop = function(elem,bounds,labelText, conf){
 | 
			
		||||
    var g = elem.append('g');
 | 
			
		||||
    var drawLoopLine = function(startx,starty,stopx,stopy){
 | 
			
		||||
        return g.append('line')
 | 
			
		||||
exports.drawLoop = function (elem, bounds, labelText, conf) {
 | 
			
		||||
  var g = elem.append('g')
 | 
			
		||||
  var drawLoopLine = function (startx, starty, stopx, stopy) {
 | 
			
		||||
    return g.append('line')
 | 
			
		||||
            .attr('x1', startx)
 | 
			
		||||
            .attr('y1', starty)
 | 
			
		||||
            .attr('x2', stopx )
 | 
			
		||||
            .attr('y2', stopy )
 | 
			
		||||
            .attr('x2', stopx)
 | 
			
		||||
            .attr('y2', stopy)
 | 
			
		||||
            .attr('stroke-width', 2)
 | 
			
		||||
            .attr('stroke', '#526e52')
 | 
			
		||||
            .attr('class','loopLine');
 | 
			
		||||
    };
 | 
			
		||||
    drawLoopLine(bounds.startx, bounds.starty, bounds.stopx , bounds.starty);
 | 
			
		||||
    drawLoopLine(bounds.stopx , bounds.starty, bounds.stopx , bounds.stopy );
 | 
			
		||||
    drawLoopLine(bounds.startx, bounds.stopy , bounds.stopx , bounds.stopy );
 | 
			
		||||
    drawLoopLine(bounds.startx, bounds.starty, bounds.startx, bounds.stopy );
 | 
			
		||||
    if (typeof bounds.sections !== 'undefined') {
 | 
			
		||||
        bounds.sections.forEach(function(item) {
 | 
			
		||||
            drawLoopLine(bounds.startx, item, bounds.stopx, item).style('stroke-dasharray', '3, 3');
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
            .attr('class', 'loopLine')
 | 
			
		||||
  }
 | 
			
		||||
  drawLoopLine(bounds.startx, bounds.starty, bounds.stopx, bounds.starty)
 | 
			
		||||
  drawLoopLine(bounds.stopx, bounds.starty, bounds.stopx, bounds.stopy)
 | 
			
		||||
  drawLoopLine(bounds.startx, bounds.stopy, bounds.stopx, bounds.stopy)
 | 
			
		||||
  drawLoopLine(bounds.startx, bounds.starty, bounds.startx, bounds.stopy)
 | 
			
		||||
  if (typeof bounds.sections !== 'undefined') {
 | 
			
		||||
    bounds.sections.forEach(function (item) {
 | 
			
		||||
      drawLoopLine(bounds.startx, item, bounds.stopx, item).style('stroke-dasharray', '3, 3')
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    var txt = exports.getTextObj();
 | 
			
		||||
    txt.text = labelText;
 | 
			
		||||
    txt.x = bounds.startx;
 | 
			
		||||
    txt.y = bounds.starty;
 | 
			
		||||
    txt.labelMargin =  1.5 * 10; // This is the small box that says "loop"
 | 
			
		||||
    txt.class =  'labelText';    // Its size & position are fixed.
 | 
			
		||||
    txt.fill =  'white';
 | 
			
		||||
  var txt = exports.getTextObj()
 | 
			
		||||
  txt.text = labelText
 | 
			
		||||
  txt.x = bounds.startx
 | 
			
		||||
  txt.y = bounds.starty
 | 
			
		||||
  txt.labelMargin = 1.5 * 10 // This is the small box that says "loop"
 | 
			
		||||
  txt.class = 'labelText'    // Its size & position are fixed.
 | 
			
		||||
  txt.fill = 'white'
 | 
			
		||||
 | 
			
		||||
    exports.drawLabel(g,txt);
 | 
			
		||||
  exports.drawLabel(g, txt)
 | 
			
		||||
 | 
			
		||||
    txt = exports.getTextObj();
 | 
			
		||||
    txt.text = '[ ' + bounds.title + ' ]';
 | 
			
		||||
    txt.x = bounds.startx + (bounds.stopx - bounds.startx)/2;
 | 
			
		||||
    txt.y = bounds.starty + 1.5 * conf.boxMargin;
 | 
			
		||||
    txt.anchor = 'middle';
 | 
			
		||||
    txt.class = 'loopText';
 | 
			
		||||
  txt = exports.getTextObj()
 | 
			
		||||
  txt.text = '[ ' + bounds.title + ' ]'
 | 
			
		||||
  txt.x = bounds.startx + (bounds.stopx - bounds.startx) / 2
 | 
			
		||||
  txt.y = bounds.starty + 1.5 * conf.boxMargin
 | 
			
		||||
  txt.anchor = 'middle'
 | 
			
		||||
  txt.class = 'loopText'
 | 
			
		||||
 | 
			
		||||
    exports.drawText(g,txt);
 | 
			
		||||
  exports.drawText(g, txt)
 | 
			
		||||
 | 
			
		||||
    if (typeof bounds.sectionTitles !== 'undefined') {
 | 
			
		||||
        bounds.sectionTitles.forEach(function(item, idx) {
 | 
			
		||||
            if (item !== '') {
 | 
			
		||||
                txt.text = '[ ' + item + ' ]';
 | 
			
		||||
                txt.y = bounds.sections[idx] + 1.5 * conf.boxMargin;
 | 
			
		||||
                exports.drawText(g, txt);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
  if (typeof bounds.sectionTitles !== 'undefined') {
 | 
			
		||||
    bounds.sectionTitles.forEach(function (item, idx) {
 | 
			
		||||
      if (item !== '') {
 | 
			
		||||
        txt.text = '[ ' + item + ' ]'
 | 
			
		||||
        txt.y = bounds.sections[idx] + 1.5 * conf.boxMargin
 | 
			
		||||
        exports.drawText(g, txt)
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Setup arrow head and define the marker. The result is appended to the svg.
 | 
			
		||||
 */
 | 
			
		||||
exports.insertArrowHead = function(elem){
 | 
			
		||||
    elem.append('defs').append('marker')
 | 
			
		||||
exports.insertArrowHead = function (elem) {
 | 
			
		||||
  elem.append('defs').append('marker')
 | 
			
		||||
        .attr('id', 'arrowhead')
 | 
			
		||||
        .attr('refX', 5)
 | 
			
		||||
        .attr('refY', 2)
 | 
			
		||||
@@ -206,132 +204,131 @@ exports.insertArrowHead = function(elem){
 | 
			
		||||
        .attr('markerHeight', 4)
 | 
			
		||||
        .attr('orient', 'auto')
 | 
			
		||||
        .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.
 | 
			
		||||
 */
 | 
			
		||||
exports.insertArrowCrossHead = function(elem){
 | 
			
		||||
    var defs = elem.append('defs');
 | 
			
		||||
    var marker = defs.append('marker')
 | 
			
		||||
exports.insertArrowCrossHead = function (elem) {
 | 
			
		||||
  var defs = elem.append('defs')
 | 
			
		||||
  var marker = defs.append('marker')
 | 
			
		||||
        .attr('id', 'crosshead')
 | 
			
		||||
        .attr('markerWidth', 15)
 | 
			
		||||
        .attr('markerHeight', 8)
 | 
			
		||||
        .attr('orient', 'auto')
 | 
			
		||||
        .attr('refX', 16)
 | 
			
		||||
        .attr('refY', 4);
 | 
			
		||||
        .attr('refY', 4)
 | 
			
		||||
 | 
			
		||||
    // The arrow
 | 
			
		||||
    marker.append('path')
 | 
			
		||||
            .attr('fill','black')
 | 
			
		||||
            .attr('stroke','#000000')
 | 
			
		||||
  marker.append('path')
 | 
			
		||||
            .attr('fill', 'black')
 | 
			
		||||
            .attr('stroke', '#000000')
 | 
			
		||||
            .style('stroke-dasharray', ('0, 0'))
 | 
			
		||||
            .attr('stroke-width','1px')
 | 
			
		||||
            .attr('d', 'M 9,2 V 6 L16,4 Z');
 | 
			
		||||
            .attr('stroke-width', '1px')
 | 
			
		||||
            .attr('d', 'M 9,2 V 6 L16,4 Z')
 | 
			
		||||
 | 
			
		||||
    // The cross
 | 
			
		||||
    marker.append('path')
 | 
			
		||||
            .attr('fill','none')
 | 
			
		||||
            .attr('stroke','#000000')
 | 
			
		||||
  marker.append('path')
 | 
			
		||||
            .attr('fill', 'none')
 | 
			
		||||
            .attr('stroke', '#000000')
 | 
			
		||||
            .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')
 | 
			
		||||
        ; //this is actual shape for arrowhead
 | 
			
		||||
         // this is actual shape for arrowhead
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
exports.getTextObj = function () {
 | 
			
		||||
  var txt = {
 | 
			
		||||
    x: 0,
 | 
			
		||||
    y: 0,
 | 
			
		||||
    'fill': 'black',
 | 
			
		||||
    'text-anchor': 'start',
 | 
			
		||||
    style: '#666',
 | 
			
		||||
    width: 100,
 | 
			
		||||
    height: 100,
 | 
			
		||||
    textMargin: 0,
 | 
			
		||||
    rx: 0,
 | 
			
		||||
    ry: 0
 | 
			
		||||
  }
 | 
			
		||||
  return txt
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.getTextObj = function(){
 | 
			
		||||
    var txt = {
 | 
			
		||||
        x: 0,
 | 
			
		||||
        y: 0,
 | 
			
		||||
        'fill':'black',
 | 
			
		||||
        'text-anchor': 'start',
 | 
			
		||||
        style: '#666',
 | 
			
		||||
        width: 100,
 | 
			
		||||
        height: 100,
 | 
			
		||||
        textMargin:0,
 | 
			
		||||
        rx: 0,
 | 
			
		||||
        ry: 0
 | 
			
		||||
    };
 | 
			
		||||
    return txt;
 | 
			
		||||
};
 | 
			
		||||
exports.getNoteRect = function () {
 | 
			
		||||
  var rect = {
 | 
			
		||||
    x: 0,
 | 
			
		||||
    y: 0,
 | 
			
		||||
    fill: '#EDF2AE',
 | 
			
		||||
    stroke: '#666',
 | 
			
		||||
    width: 100,
 | 
			
		||||
    anchor: 'start',
 | 
			
		||||
    height: 100,
 | 
			
		||||
    rx: 0,
 | 
			
		||||
    ry: 0
 | 
			
		||||
  }
 | 
			
		||||
  return rect
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.getNoteRect = function(){
 | 
			
		||||
    var rect = {
 | 
			
		||||
        x      : 0,
 | 
			
		||||
        y      : 0,
 | 
			
		||||
        fill   : '#EDF2AE',
 | 
			
		||||
        stroke : '#666',
 | 
			
		||||
        width  : 100,
 | 
			
		||||
        anchor : 'start',
 | 
			
		||||
        height : 100,
 | 
			
		||||
        rx     : 0,
 | 
			
		||||
        ry     : 0
 | 
			
		||||
    };
 | 
			
		||||
    return rect;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var _drawTextCandidateFunc = (function() {
 | 
			
		||||
    function byText(content, g, x, y, width, height, textAttrs) {
 | 
			
		||||
      var text = g.append('text')
 | 
			
		||||
var _drawTextCandidateFunc = (function () {
 | 
			
		||||
  function byText (content, g, x, y, width, height, textAttrs) {
 | 
			
		||||
    var text = g.append('text')
 | 
			
		||||
        .attr('x', x + width / 2).attr('y', y + height / 2 + 5)
 | 
			
		||||
        .style('text-anchor', 'middle')
 | 
			
		||||
        .text(content);
 | 
			
		||||
      _setTextAttrs(text, textAttrs);
 | 
			
		||||
    }
 | 
			
		||||
        .text(content)
 | 
			
		||||
    _setTextAttrs(text, textAttrs)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    function byTspan(content, g, x, y, width, height, textAttrs) {
 | 
			
		||||
      var text = g.append('text')
 | 
			
		||||
        .attr('x', x + width / 2).attr('y', y) 
 | 
			
		||||
        .style('text-anchor', 'middle');
 | 
			
		||||
      text.append('tspan')
 | 
			
		||||
        .attr('x', x + width / 2).attr('dy', '0') 
 | 
			
		||||
        .text(content);
 | 
			
		||||
  function byTspan (content, g, x, y, width, height, textAttrs) {
 | 
			
		||||
    var text = g.append('text')
 | 
			
		||||
        .attr('x', x + width / 2).attr('y', y)
 | 
			
		||||
        .style('text-anchor', 'middle')
 | 
			
		||||
    text.append('tspan')
 | 
			
		||||
        .attr('x', x + width / 2).attr('dy', '0')
 | 
			
		||||
        .text(content)
 | 
			
		||||
 | 
			
		||||
      if(typeof(text.textwrap) !== 'undefined'){
 | 
			
		||||
        text.textwrap({ //d3textwrap
 | 
			
		||||
              x: x + width / 2, y: y, width: width, height: height
 | 
			
		||||
        }, 0);
 | 
			
		||||
        //vertical aligment after d3textwrap expans tspan to multiple tspans
 | 
			
		||||
        var tspans = text.selectAll('tspan');
 | 
			
		||||
        if (tspans.length > 0 && tspans[0].length > 0) {
 | 
			
		||||
          tspans = tspans[0];
 | 
			
		||||
          //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))
 | 
			
		||||
            .attr("dominant-baseline", "central")
 | 
			
		||||
            .attr("alignment-baseline", "central");
 | 
			
		||||
        }
 | 
			
		||||
      } 
 | 
			
		||||
      _setTextAttrs(text, textAttrs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function byFo(content, g, x, y, width, height, textAttrs) {
 | 
			
		||||
        var s = g.append('switch');
 | 
			
		||||
        var f = s.append("foreignObject")
 | 
			
		||||
                  .attr('x', x).attr('y', y)
 | 
			
		||||
                  .attr('width', width).attr('height', height);
 | 
			
		||||
 | 
			
		||||
        var text = f.append('div').style('display', 'table')
 | 
			
		||||
          .style('height', '100%').style('width', '100%');
 | 
			
		||||
 | 
			
		||||
        text.append('div').style('display', 'table-cell')
 | 
			
		||||
           .style('text-align', 'center').style('vertical-align', 'middle')
 | 
			
		||||
           .text(content);
 | 
			
		||||
 | 
			
		||||
        byTspan(content, s, x, y, width, height, textAttrs);
 | 
			
		||||
        _setTextAttrs(text, textAttrs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _setTextAttrs(toText, fromTextAttrsDict) {
 | 
			
		||||
      for (var key in fromTextAttrsDict) {
 | 
			
		||||
        if (fromTextAttrsDict.hasOwnProperty(key)) {
 | 
			
		||||
          toText.attr(key, fromTextAttrsDict[key]);
 | 
			
		||||
        }
 | 
			
		||||
    if (typeof (text.textwrap) !== 'undefined') {
 | 
			
		||||
      text.textwrap({ // d3textwrap
 | 
			
		||||
        x: x + width / 2, y: y, width: width, height: height
 | 
			
		||||
      }, 0)
 | 
			
		||||
        // vertical aligment after d3textwrap expans tspan to multiple tspans
 | 
			
		||||
      var tspans = text.selectAll('tspan')
 | 
			
		||||
      if (tspans.length > 0 && tspans[0].length > 0) {
 | 
			
		||||
        tspans = tspans[0]
 | 
			
		||||
          // 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))
 | 
			
		||||
            .attr('dominant-baseline', 'central')
 | 
			
		||||
            .attr('alignment-baseline', 'central')
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    _setTextAttrs(text, textAttrs)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    return function(conf) {
 | 
			
		||||
      return conf.textPlacement==='fo' ? byFo : (
 | 
			
		||||
          conf.textPlacement==='old' ? byText: byTspan);
 | 
			
		||||
    };
 | 
			
		||||
})();
 | 
			
		||||
  function byFo (content, g, x, y, width, height, textAttrs) {
 | 
			
		||||
    var s = g.append('switch')
 | 
			
		||||
    var f = s.append('foreignObject')
 | 
			
		||||
                  .attr('x', x).attr('y', y)
 | 
			
		||||
                  .attr('width', width).attr('height', height)
 | 
			
		||||
 | 
			
		||||
    var text = f.append('div').style('display', 'table')
 | 
			
		||||
          .style('height', '100%').style('width', '100%')
 | 
			
		||||
 | 
			
		||||
    text.append('div').style('display', 'table-cell')
 | 
			
		||||
           .style('text-align', 'center').style('vertical-align', 'middle')
 | 
			
		||||
           .text(content)
 | 
			
		||||
 | 
			
		||||
    byTspan(content, s, x, y, width, height, textAttrs)
 | 
			
		||||
    _setTextAttrs(text, textAttrs)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function _setTextAttrs (toText, fromTextAttrsDict) {
 | 
			
		||||
    for (var key in fromTextAttrsDict) {
 | 
			
		||||
      if (fromTextAttrsDict.hasOwnProperty(key)) {
 | 
			
		||||
        toText.attr(key, fromTextAttrsDict[key])
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return function (conf) {
 | 
			
		||||
    return conf.textPlacement === 'fo' ? byFo : (
 | 
			
		||||
          conf.textPlacement === 'old' ? byText : byTspan)
 | 
			
		||||
  }
 | 
			
		||||
})()
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user