From 8365fcc2f9276b371bedff570321007083167ee8 Mon Sep 17 00:00:00 2001 From: knsv Date: Sat, 17 Oct 2015 10:38:05 +0200 Subject: [PATCH] Modernization, better linting, adjustment after stricter static rules --- src/diagrams/example/example.spec.js | 1 + src/diagrams/example/parser/example.js | 4 +- src/diagrams/flowchart/flowRenderer.js | 21 +- src/diagrams/flowchart/parser/dot.js | 4 +- src/diagrams/flowchart/parser/flow.js | 4 +- src/diagrams/gantt/ganttDb.spec.js | 2 +- src/diagrams/gantt/parser/gantt.js | 4 +- .../sequenceDiagram/parser/sequenceDiagram.js | 4 +- .../sequenceDiagram/sequenceRenderer.js | 8 +- src/mermaid.js | 30 ++- src/mermaid.spec.js | 10 +- src/mermaidAPI.js | 8 +- src/utils.js | 131 ------------- src/utils.spec.js | 181 ------------------ 14 files changed, 48 insertions(+), 364 deletions(-) delete mode 100644 src/utils.js delete mode 100644 src/utils.spec.js diff --git a/src/diagrams/example/example.spec.js b/src/diagrams/example/example.spec.js index 0eb72c0c2..e938fedda 100644 --- a/src/diagrams/example/example.spec.js +++ b/src/diagrams/example/example.spec.js @@ -3,6 +3,7 @@ */ describe('when parsing an info graph it',function() { var parseError; + var ex; beforeEach(function () { ex = require('./parser/example').parser; ex.yy = require('./exampleDb'); diff --git a/src/diagrams/example/parser/example.js b/src/diagrams/example/parser/example.js index 73cd7d45f..b25ee6648 100644 --- a/src/diagrams/example/parser/example.js +++ b/src/diagrams/example/parser/example.js @@ -139,14 +139,14 @@ parse: function parse(input) { lstack.length = lstack.length - n; } _token_stack: - function lex() { + 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]; diff --git a/src/diagrams/flowchart/flowRenderer.js b/src/diagrams/flowchart/flowRenderer.js index 5a70ea9a8..39ab5e157 100644 --- a/src/diagrams/flowchart/flowRenderer.js +++ b/src/diagrams/flowchart/flowRenderer.js @@ -43,8 +43,6 @@ exports.addVertices = function (vert, g) { var vertice = vert[id]; var verticeText; - var i; - /** * Variable for storing the classes for the vertice * @type {string} @@ -78,7 +76,7 @@ exports.addVertices = function (vert, g) { var labelTypeStr = ''; if(conf.htmlLabels) { labelTypeStr = 'html'; - verticeText = verticeText.replace(/fa:fa[\w\-]+/g,function(s,t,u){ + verticeText = verticeText.replace(/fa:fa[\w\-]+/g,function(s){ return ''; }); @@ -119,7 +117,7 @@ exports.addVertices = function (vert, g) { _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}); }); }; @@ -257,7 +255,7 @@ exports.draw = function (text, id,isDot) { parser.parse(text); } catch(err){ - + log.debug('Parsing failed'); } // Fetch the default direction, use TD if none was found @@ -347,7 +345,7 @@ exports.draw = function (text, id,isDot) { {x: w, y: 0}, {x: w, y: -h}, {x: -h/2, y: -h}, - {x: 0, y: -h/2}, + {x: 0, y: -h/2} ]; var shapeSvg = parent.insert('polygon', ':first-child') .attr('points', points.map(function (d) { @@ -369,7 +367,7 @@ exports.draw = function (text, id,isDot) { {x: w+h/2, y: 0}, {x: w, y: -h/2}, {x: w+h/2, y: -h}, - {x: 0, y: -h}, + {x: 0, y: -h} ]; var shapeSvg = parent.insert('polygon', ':first-child') .attr('points', points.map(function (d) { @@ -401,7 +399,7 @@ exports.draw = function (text, id,isDot) { // Set up an SVG group so that we can translate the final graph. var svg = d3.select('#' + id); - svgGroup = d3.select('#' + id + ' g'); + //svgGroup = d3.select('#' + id + ' g'); // Run the renderer. This is what draws the final graph. var element = d3.select('#' + id + ' g'); @@ -413,12 +411,6 @@ exports.draw = function (text, id,isDot) { return graph.getTooltip(this.id); }); - // - //element.selectAll('g.node') - // .attr('title', function(v) { return styleTooltip(v, g.node(v).description) }) - // .each(function(v) { $(this).tipsy({ gravity: 'w', opacity: 1, html: true }); }); - var svgb = document.querySelector('#' + id); - /* var xPos = document.querySelectorAll('.clusters rect')[0].x.baseVal.value; var width = document.querySelectorAll('.clusters rect')[0].width.baseVal.value; @@ -455,7 +447,6 @@ exports.draw = function (text, id,isDot) { graph.indexNodes('subGraph'+i); for(i=0;i= 2){ /*! sequence config was passed as #1 */ if(typeof arguments[0] !== 'undefined'){ - mermaid.sequenceConfig = arguments[0]; + global.mermaid.sequenceConfig = arguments[0]; } nodes = arguments[1]; @@ -84,18 +84,18 @@ var init = function () { var i; if(typeof mermaid_config !== 'undefined'){ - mermaidAPI.initialize(mermaid_config); + mermaidAPI.initialize(global.mermaid_config); } - log.debug('Start On Load before: '+mermaid.startOnLoad); - if(typeof mermaid.startOnLoad !== 'undefined'){ - log.debug('Start On Load inner: '+mermaid.startOnLoad); - mermaidAPI.initialize({startOnLoad:mermaid.startOnLoad}); + log.debug('Start On Load before: '+global.mermaid.startOnLoad); + if(typeof global.mermaid.startOnLoad !== 'undefined'){ + log.debug('Start On Load inner: '+global.mermaid.startOnLoad); + mermaidAPI.initialize({startOnLoad:global.mermaid.startOnLoad}); } - if(typeof mermaid.ganttConfig !== 'undefined'){ - mermaidAPI.initialize({gantt:mermaid.ganttConfig}); + if(typeof global.mermaid.ganttConfig !== 'undefined'){ + mermaidAPI.initialize({gantt:global.mermaid.ganttConfig}); } var txt; @@ -119,7 +119,6 @@ var init = function () { var id = 'mermaidChart' + nextId++; - var he = require('he'); // Fetch the graph definition including tags txt = element.innerHTML; @@ -133,7 +132,6 @@ var init = function () { mermaidAPI.render(id,txt,insertSvg, element); } - }; exports.init = init; @@ -188,7 +186,7 @@ global.mermaid = { startOnLoad: true, htmlLabels: true, - init: function(sequenceConfig, nodes) { + init: function() { init.apply(null, arguments); }, initialize: function(config) { @@ -200,7 +198,7 @@ global.mermaid = { parse: function(text) { return mermaidAPI.parse(text); }, - parseError: function(err, hash) { + parseError: function(err) { log.debug('Mermaid Syntax error:'); log.debug(err); }, @@ -225,16 +223,16 @@ exports.contentLoaded = function(){ var config; // Check state of start config mermaid namespace if (typeof mermaid_config !== 'undefined') { - if (equals(false, mermaid_config.htmlLabels)) { + if (equals(false, global.mermaid_config.htmlLabels)) { global.mermaid.htmlLabels = false; } } if(global.mermaid.startOnLoad) { // For backwards compatability reasons also check mermaid_config variable - if (typeof mermaid_config !== 'undefined') { + if (typeof global.mermaid_config !== 'undefined') { // Check if property startOnLoad is set - if (equals(true, mermaid_config.startOnLoad)) { + if (equals(true, global.mermaid_config.startOnLoad)) { global.mermaid.init(); } } diff --git a/src/mermaid.spec.js b/src/mermaid.spec.js index 83a0cf082..703344589 100644 --- a/src/mermaid.spec.js +++ b/src/mermaid.spec.js @@ -23,13 +23,13 @@ describe('when using mermaid and ',function() { // and in the run-code inside some object global.document = mock.getDocument(); - window = mock.getWindow(); + global.window = mock.getWindow(); }); it('should not start rendering with mermaid_config.startOnLoad set to false', function () { mermaid = rewire('./mermaid'); - mermaid_config ={startOnLoad : false}; + global.mermaid_config ={startOnLoad : false}; document.body.innerHTML = '
graph TD;\na;
'; spyOn(global.mermaid,'init'); @@ -41,7 +41,7 @@ describe('when using mermaid and ',function() { it('should not start rendering with mermaid.startOnLoad set to false', function () { mermaid = rewire('./mermaid'); global.mermaid.startOnLoad = false; - mermaid_config ={startOnLoad : true}; + global.mermaid_config ={startOnLoad : true}; document.body.innerHTML = '
graph TD;\na;
'; spyOn(global.mermaid,'init'); @@ -52,7 +52,7 @@ describe('when using mermaid and ',function() { it('should start rendering with both startOnLoad set', function () { mermaid = rewire('./mermaid'); global.mermaid.startOnLoad = true; - mermaid_config ={startOnLoad : true}; + global.mermaid_config ={startOnLoad : true}; document.body.innerHTML = '
graph TD;\na;
'; spyOn(global.mermaid,'init'); mermaid.contentLoaded(); @@ -85,7 +85,7 @@ describe('when using mermaid and ',function() { var flowRend = require('./diagrams/flowchart/flowRenderer'); beforeEach(function () { - mermaid_config ={startOnLoad : false}; + global.mermaid_config ={startOnLoad : false}; var MockBrowser = require('mock-browser').mocks.MockBrowser; var mock = new MockBrowser(); flow.parser.yy =graph; diff --git a/src/mermaidAPI.js b/src/mermaidAPI.js index 905f50fb5..8b9002ae9 100644 --- a/src/mermaidAPI.js +++ b/src/mermaidAPI.js @@ -14,7 +14,7 @@ var graph = require('./diagrams/flowchart/graphDb'); var flow = require('./diagrams/flowchart/parser/flow'); -var utils = require('./utils'); +var utils = require('./utils-es6'); var flowRenderer = require('./diagrams/flowchart/flowRenderer'); var seq = require('./diagrams/sequenceDiagram/sequenceRenderer'); var info = require('./diagrams/example/exampleRenderer'); @@ -418,9 +418,11 @@ var render = function(id, txt, cb, container){ d3.select('#d'+id).selectAll('foreignobject div').attr('xmlns','http://www.w3.org/1999/xhtml'); - + var url = window.location.protocol+'//'+window.location.host+window.location.pathname +window.location.search; + url = url.replace(/\(/g,'\\('); + url = url.replace(/\)/g,'\\)'); // Fix for when the base tag is used - var svgCode = d3.select('#d'+id).node().innerHTML.replace(/url\(#arrowhead/g,'url('+ window.location.protocol+'//'+location.host+location.pathname +'#arrowhead','g'); + var svgCode = d3.select('#d'+id).node().innerHTML.replace(/url\(#arrowhead/g,'url('+url +'#arrowhead','g'); svgCode = exports.decodeEntities(svgCode); //console.warn('mermaid decode: '); diff --git a/src/utils.js b/src/utils.js deleted file mode 100644 index f44df13f3..000000000 --- a/src/utils.js +++ /dev/null @@ -1,131 +0,0 @@ -/** - * Created by knut on 14-11-23. - */ -var log = require('./logger').create(); -/** - * @function detectType - * Detects the type of the graph text. - * ```mermaid - * graph LR - * a-->b - * b-->c - * c-->d - * d-->e - * e-->f - * f-->g - * g-->h - * ``` - * - * @param {string} text The text defining the graph - * @param {string} text The second text defining the graph - * @returns {string} A graph definition key - */ -module.exports.detectType = function(text,a){ - text = text.replace(/^\s*%%.*\n/g,'\n'); - if(text.match(/^\s*sequenceDiagram/)){ - return 'sequenceDiagram'; - } - - if(text.match(/^\s*digraph/)) { - //log.debug('Detected dot syntax'); - return 'dotGraph'; - } - - if(text.match(/^\s*info/)) { - //log.debug('Detected info syntax'); - return 'info'; - } - - if(text.match(/^\s*gantt/)) { - //log.debug('Detected info syntax'); - return 'gantt'; - } - - return 'graph'; -}; - -/** - * Copies all relevant CSS content into the graph SVG. - * This allows the SVG to be copied as is while keeping class based styling - * @param {element} svg The root element of the SVG - * @param {object} Hash table of class definitions from the graph definition - */ -module.exports.cloneCssStyles = function(svg, classes){ - var usedStyles = ''; - var sheets = document.styleSheets; - for (var i = 0; i < sheets.length; i++) { - // Avoid multiple inclusion on pages with multiple graphs - if (sheets[i].title !== 'mermaid-svg-internal-css') { - try { - - var rules = sheets[i].cssRules; - if (rules !== null) { - for (var j = 0; j < rules.length; j++) { - var rule = rules[j]; - if (typeof(rule.style) !== 'undefined') { - var elems; - elems = svg.querySelectorAll(rule.selectorText); - if (elems.length > 0) { - usedStyles += rule.selectorText + ' { ' + rule.style.cssText + ' }\n'; - } - } - } - } - } - catch(err) { - if(typeof console !== 'undefined'){ - if(console.warn !== 'undefined'){ - if(rule !== 'undefined'){ - console.warn('Invalid CSS selector "' + rule.selectorText + '"', err); - } - } - } - } - } - } - - var defaultStyles = ''; - var embeddedStyles = ''; - - for (var className in classes) { - if (classes.hasOwnProperty(className) && typeof(className) != 'undefined') { - if (className === 'default') { - if (classes.default.styles instanceof Array) { - defaultStyles += '#' + svg.id.trim() + ' .node' + '>rect { ' + classes[className].styles.join('; ') + '; }\n'; - } - if (classes.default.nodeLabelStyles instanceof Array) { - defaultStyles += '#' + svg.id.trim() + ' .node text ' + ' { ' + classes[className].nodeLabelStyles.join('; ') + '; }\n'; - } - if (classes.default.edgeLabelStyles instanceof Array) { - defaultStyles += '#' + svg.id.trim() + ' .edgeLabel text ' + ' { ' + classes[className].edgeLabelStyles.join('; ') + '; }\n'; - } - if (classes.default.clusterStyles instanceof Array) { - defaultStyles += '#' + svg.id.trim() + ' .cluster rect ' + ' { ' + classes[className].clusterStyles.join('; ') + '; }\n'; - } - } else { - if (classes[className].styles instanceof Array) { - embeddedStyles += '#' + svg.id.trim() + ' .' + className + '>rect { ' + classes[className].styles.join('; ') + '; }\n'; - } - } - } - } - - if (usedStyles !== '' || defaultStyles !== '' || embeddedStyles !== '') { - var s = document.createElement('style'); - s.setAttribute('type', 'text/css'); - s.setAttribute('title', 'mermaid-svg-internal-css'); - s.innerHTML = '/* */\n'; - svg.insertBefore(s, svg.firstChild); - } -}; diff --git a/src/utils.spec.js b/src/utils.spec.js deleted file mode 100644 index 0d7037690..000000000 --- a/src/utils.spec.js +++ /dev/null @@ -1,181 +0,0 @@ -/** - * Created by knut on 14-11-23. - */ -var log = require('./logger').create(); -describe('when detecting chart type ',function() { - var utils = require('./utils'); - beforeEach(function () { - - }); - - it('should handle a graph defintion', function () { - str = 'graph TB\nbfs1:queue'; - - var type = utils.detectType(str); - expect(type).toBe('graph'); - }); - it('should handle a graph defintion with leading spaces', function () { - str = ' graph TB\nbfs1:queue'; - - var type = utils.detectType(str); - expect(type).toBe('graph'); - }); - - it('should handle a graph defintion with leading spaces and newline', function () { - str = ' \n graph TB\nbfs1:queue'; - - var type = utils.detectType(str); - expect(type).toBe('graph'); - }); -}); - -describe('when cloning CSS ',function() { - var utils = require('./utils'); - - beforeEach(function () { - var MockBrowser = require('mock-browser').mocks.MockBrowser; - var mock = new MockBrowser(); - - // and in the run-code inside some object - document = mock.getDocument(); - //document.body.innerHTML = ''; - //document.body.innerHTML = ''; - }); - - function stylesToArray(svg) { - var styleSheets = svg.getElementsByTagName('style'); - expect(styleSheets.length).toBe(1); - var styleSheet = styleSheets[0]; - - var innerStyle = styleSheet.innerHTML; - var styleArr = innerStyle.split('\n'); - - // Remove first and last two lines to remove the CDATA - expect(styleArr.length).toBeGreaterThan(2); - var styleArrTrim = styleArr.slice(1,-2); - - // Remove all empty lines - for (var i = 0; i < styleArrTrim.length; i++) { - if (styleArrTrim[i].trim() === '') { - styleArrTrim.splice(i,1); - i--; - } - } - - return styleArrTrim; - } - - function addStyleToDocument() { - var styleSheetCount = document.styleSheets.length; - var s = document.createElement('style'); - s.innerHTML = '.node { stroke:#eee; }\n.node-square { stroke:#bbb; }\n'; - document.body.appendChild(s); - } - - function addSecondStyleToDocument() { - var styleSheetCount = document.styleSheets.length; - var s = document.createElement('style'); - s.innerHTML = '.node2 { stroke:#eee; }\n.node-square { stroke:#beb; }\n'; - document.body.appendChild(s); - } - - function generateSVG() { - var svg = document.createElement('svg'); - svg.setAttribute('id', 'mermaid-01'); - var g1 = document.createElement('g'); - g1.setAttribute('class', 'node'); - svg.appendChild(g1); - var g2 = document.createElement('g'); - g2.setAttribute('class', 'node-square'); - svg.appendChild(g2); - return svg; - } - - function addMermaidSVGwithStyleToDocument() { - var styleSheetCount = document.styleSheets.length; - var svg = document.createElement('svg'); - svg.setAttribute('id', 'mermaid-03'); - var s = document.createElement('style'); - s.setAttribute('type', 'text/css'); - s.setAttribute('title', 'mermaid-svg-internal-css'); - s.innerHTML = '#mermaid-05 .node2 { stroke:#eee; }\n.node-square { stroke:#bfe; }\n'; - svg.appendChild(s); - document.body.appendChild(svg); - document.styleSheets[styleSheetCount].title = 'mermaid-svg-internal-css'; - } - - it('should handle an empty set of classes', function () { - var svg = document.createElement('svg'); - svg.setAttribute('id', 'mermaid-01'); - - utils.cloneCssStyles(svg, {}); - // Should not create style element if not needed - expect(svg.innerHTML).toBe(''); - }); - - it('should handle a default class', function () { - var svg = document.createElement('svg'); - svg.setAttribute('id', 'mermaid-01'); - - utils.cloneCssStyles(svg, { 'default': { 'styles': ['stroke:#fff','stroke-width:1.5px'] } }); - expect(stylesToArray(svg)).toEqual([ '#mermaid-01 .node>rect { stroke:#fff; stroke-width:1.5px; }' ]); - // Also verify the elements around the styling - expect(svg.innerHTML).toBe(''); - }); - - it('should handle stylesheet in document with no classes in SVG', function () { - var svg = document.createElement('svg'); - svg.setAttribute('id', 'mermaid-01'); - - addStyleToDocument('mermaid'); - utils.cloneCssStyles(svg, {}); - // Should not create style element if not needed - expect(svg.innerHTML).toBe(''); - }); - - it('should handle stylesheet in document with classes in SVG', function () { - var svg = generateSVG(); - addStyleToDocument(); - utils.cloneCssStyles(svg, {}); - expect(stylesToArray(svg)).toEqual([ '.node { stroke: #eee; }', '.node-square { stroke: #bbb; }']); - }); - - it('should handle multiple stylesheets in document with classes in SVG', function () { - var svg = generateSVG(); - addStyleToDocument(); - addSecondStyleToDocument(); - utils.cloneCssStyles(svg, {}); - expect(stylesToArray(svg)).toEqual([ '.node { stroke: #eee; }', '.node-square { stroke: #bbb; }', '.node-square { stroke: #beb; }']); - }); - - it('should handle multiple stylesheets + ignore styles in other mermaid SVG', function () { - var svg = generateSVG(); - addStyleToDocument(); - addSecondStyleToDocument(); - addMermaidSVGwithStyleToDocument(); - utils.cloneCssStyles(svg, {}); - expect(stylesToArray(svg)).toEqual([ '.node { stroke: #eee; }', '.node-square { stroke: #bbb; }', '.node-square { stroke: #beb; }']); - }); - - it('should handle a default class together with stylesheet in document with classes in SVG', function () { - var svg = generateSVG(); - addStyleToDocument(); - utils.cloneCssStyles(svg, { 'default': { 'styles': ['stroke:#fff','stroke-width:1.5px'] } }); - expect(stylesToArray(svg)).toEqual([ '#mermaid-01 .node>rect { stroke:#fff; stroke-width:1.5px; }', '.node { stroke: #eee; }', '.node-square { stroke: #bbb; }']); - }); - - it('should handle a default class together with stylesheet in document and classDefs', function () { - var svg = generateSVG(); - addStyleToDocument(); - utils.cloneCssStyles(svg, { 'default': { 'styles': ['stroke:#fff','stroke-width:1.5px'] }, - 'node-square': { 'styles': ['fill:#eee', 'stroke:#aaa'] }, - 'node-circle': { 'styles': ['fill:#444', 'stroke:#111'] } }); - expect(stylesToArray(svg)).toEqual([ '#mermaid-01 .node>rect { stroke:#fff; stroke-width:1.5px; }', - '.node { stroke: #eee; }', - '.node-square { stroke: #bbb; }', - '#mermaid-01 .node-square>rect { fill:#eee; stroke:#aaa; }', - '#mermaid-01 .node-circle>rect { fill:#444; stroke:#111; }' - ]); - }); -}); -