mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-11 11:29:42 +02:00
#931 Last code standard fixes
This commit is contained in:
128
src/mermaid.js
128
src/mermaid.js
@@ -2,10 +2,10 @@
|
|||||||
* Web page integration module for the mermaid framework. It uses the mermaidAPI for mermaid functionality and to render
|
* Web page integration module for the mermaid framework. It uses the mermaidAPI for mermaid functionality and to render
|
||||||
* the diagrams to svg code.
|
* the diagrams to svg code.
|
||||||
*/
|
*/
|
||||||
import he from 'he'
|
import he from 'he';
|
||||||
|
|
||||||
import mermaidAPI from './mermaidAPI'
|
import mermaidAPI from './mermaidAPI';
|
||||||
import { logger } from './logger'
|
import { logger } from './logger';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ## init
|
* ## init
|
||||||
@@ -28,126 +28,142 @@ import { logger } from './logger'
|
|||||||
* Renders the mermaid diagrams
|
* Renders the mermaid diagrams
|
||||||
* @param nodes a css selector or an array of nodes
|
* @param nodes a css selector or an array of nodes
|
||||||
*/
|
*/
|
||||||
const init = function () {
|
const init = function() {
|
||||||
const conf = mermaidAPI.getConfig()
|
const conf = mermaidAPI.getConfig();
|
||||||
logger.debug('Starting rendering diagrams')
|
logger.debug('Starting rendering diagrams');
|
||||||
let nodes
|
let nodes;
|
||||||
if (arguments.length >= 2) {
|
if (arguments.length >= 2) {
|
||||||
/*! sequence config was passed as #1 */
|
/*! sequence config was passed as #1 */
|
||||||
if (typeof arguments[0] !== 'undefined') {
|
if (typeof arguments[0] !== 'undefined') {
|
||||||
mermaid.sequenceConfig = arguments[0]
|
mermaid.sequenceConfig = arguments[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes = arguments[1]
|
nodes = arguments[1];
|
||||||
} else {
|
} else {
|
||||||
nodes = arguments[0]
|
nodes = arguments[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// if last argument is a function this is the callback function
|
// if last argument is a function this is the callback function
|
||||||
let callback
|
let callback;
|
||||||
if (typeof arguments[arguments.length - 1] === 'function') {
|
if (typeof arguments[arguments.length - 1] === 'function') {
|
||||||
callback = arguments[arguments.length - 1]
|
callback = arguments[arguments.length - 1];
|
||||||
logger.debug('Callback function found')
|
logger.debug('Callback function found');
|
||||||
} else {
|
} else {
|
||||||
if (typeof conf.mermaid !== 'undefined') {
|
if (typeof conf.mermaid !== 'undefined') {
|
||||||
if (typeof conf.mermaid.callback === 'function') {
|
if (typeof conf.mermaid.callback === 'function') {
|
||||||
callback = conf.mermaid.callback
|
callback = conf.mermaid.callback;
|
||||||
logger.debug('Callback function found')
|
logger.debug('Callback function found');
|
||||||
} else {
|
} else {
|
||||||
logger.debug('No Callback function found')
|
logger.debug('No Callback function found');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nodes = nodes === undefined ? document.querySelectorAll('.mermaid')
|
nodes =
|
||||||
: typeof nodes === 'string' ? document.querySelectorAll(nodes)
|
nodes === undefined
|
||||||
: nodes instanceof window.Node ? [nodes]
|
? document.querySelectorAll('.mermaid')
|
||||||
: nodes // Last case - sequence config was passed pick next
|
: typeof nodes === 'string'
|
||||||
|
? document.querySelectorAll(nodes)
|
||||||
|
: nodes instanceof window.Node
|
||||||
|
? [nodes]
|
||||||
|
: nodes; // Last case - sequence config was passed pick next
|
||||||
|
|
||||||
logger.debug('Start On Load before: ' + mermaid.startOnLoad)
|
logger.debug('Start On Load before: ' + mermaid.startOnLoad);
|
||||||
if (typeof mermaid.startOnLoad !== 'undefined') {
|
if (typeof mermaid.startOnLoad !== 'undefined') {
|
||||||
logger.debug('Start On Load inner: ' + mermaid.startOnLoad)
|
logger.debug('Start On Load inner: ' + mermaid.startOnLoad);
|
||||||
mermaidAPI.initialize({ startOnLoad: mermaid.startOnLoad })
|
mermaidAPI.initialize({ startOnLoad: mermaid.startOnLoad });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof mermaid.ganttConfig !== 'undefined') {
|
if (typeof mermaid.ganttConfig !== 'undefined') {
|
||||||
mermaidAPI.initialize({ gantt: mermaid.ganttConfig })
|
mermaidAPI.initialize({ gantt: mermaid.ganttConfig });
|
||||||
}
|
}
|
||||||
|
|
||||||
let txt
|
let txt;
|
||||||
|
|
||||||
for (let i = 0; i < nodes.length; i++) {
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
const element = nodes[i]
|
const element = nodes[i];
|
||||||
|
|
||||||
/*! Check if previously processed */
|
/*! Check if previously processed */
|
||||||
if (!element.getAttribute('data-processed')) {
|
if (!element.getAttribute('data-processed')) {
|
||||||
element.setAttribute('data-processed', true)
|
element.setAttribute('data-processed', true);
|
||||||
} else {
|
} else {
|
||||||
continue
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const id = `mermaid-${Date.now()}`
|
const id = `mermaid-${Date.now()}`;
|
||||||
|
|
||||||
// Fetch the graph definition including tags
|
// Fetch the graph definition including tags
|
||||||
txt = element.innerHTML
|
txt = element.innerHTML;
|
||||||
|
|
||||||
// transforms the html to pure text
|
// transforms the html to pure text
|
||||||
txt = he.decode(txt).trim().replace(/<br>/ig, '<br/>')
|
txt = he
|
||||||
|
.decode(txt)
|
||||||
|
.trim()
|
||||||
|
.replace(/<br>/gi, '<br/>');
|
||||||
|
|
||||||
mermaidAPI.render(id, txt, (svgCode, bindFunctions) => {
|
mermaidAPI.render(
|
||||||
element.innerHTML = svgCode
|
id,
|
||||||
|
txt,
|
||||||
|
(svgCode, bindFunctions) => {
|
||||||
|
element.innerHTML = svgCode;
|
||||||
if (typeof callback !== 'undefined') {
|
if (typeof callback !== 'undefined') {
|
||||||
callback(id)
|
callback(id);
|
||||||
}
|
}
|
||||||
if (bindFunctions) bindFunctions(element)
|
if (bindFunctions) bindFunctions(element);
|
||||||
}, element)
|
},
|
||||||
|
element
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const initialize = function (config) {
|
const initialize = function(config) {
|
||||||
logger.debug('Initializing mermaid ')
|
logger.debug('Initializing mermaid ');
|
||||||
if (typeof config.mermaid !== 'undefined') {
|
if (typeof config.mermaid !== 'undefined') {
|
||||||
if (typeof config.mermaid.startOnLoad !== 'undefined') {
|
if (typeof config.mermaid.startOnLoad !== 'undefined') {
|
||||||
mermaid.startOnLoad = config.mermaid.startOnLoad
|
mermaid.startOnLoad = config.mermaid.startOnLoad;
|
||||||
}
|
}
|
||||||
if (typeof config.mermaid.htmlLabels !== 'undefined') {
|
if (typeof config.mermaid.htmlLabels !== 'undefined') {
|
||||||
mermaid.htmlLabels = config.mermaid.htmlLabels
|
mermaid.htmlLabels = config.mermaid.htmlLabels;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mermaidAPI.initialize(config)
|
mermaidAPI.initialize(config);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ##contentLoaded
|
* ##contentLoaded
|
||||||
* Callback function that is called when page is loaded. This functions fetches configuration for mermaid rendering and
|
* Callback function that is called when page is loaded. This functions fetches configuration for mermaid rendering and
|
||||||
* calls init for rendering the mermaid diagrams on the page.
|
* calls init for rendering the mermaid diagrams on the page.
|
||||||
*/
|
*/
|
||||||
const contentLoaded = function () {
|
const contentLoaded = function() {
|
||||||
let config
|
let config;
|
||||||
|
|
||||||
if (mermaid.startOnLoad) {
|
if (mermaid.startOnLoad) {
|
||||||
// No config found, do check API config
|
// No config found, do check API config
|
||||||
config = mermaidAPI.getConfig()
|
config = mermaidAPI.getConfig();
|
||||||
if (config.startOnLoad) {
|
if (config.startOnLoad) {
|
||||||
mermaid.init()
|
mermaid.init();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (typeof mermaid.startOnLoad === 'undefined') {
|
if (typeof mermaid.startOnLoad === 'undefined') {
|
||||||
logger.debug('In start, no config')
|
logger.debug('In start, no config');
|
||||||
config = mermaidAPI.getConfig()
|
config = mermaidAPI.getConfig();
|
||||||
if (config.startOnLoad) {
|
if (config.startOnLoad) {
|
||||||
mermaid.init()
|
mermaid.init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
if (typeof document !== 'undefined') {
|
if (typeof document !== 'undefined') {
|
||||||
/*!
|
/*!
|
||||||
* Wait for document loaded before starting the execution
|
* Wait for document loaded before starting the execution
|
||||||
*/
|
*/
|
||||||
window.addEventListener('load', function () {
|
window.addEventListener(
|
||||||
contentLoaded()
|
'load',
|
||||||
}, false)
|
function() {
|
||||||
|
contentLoaded();
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const mermaid = {
|
const mermaid = {
|
||||||
@@ -162,6 +178,6 @@ const mermaid = {
|
|||||||
initialize,
|
initialize,
|
||||||
|
|
||||||
contentLoaded
|
contentLoaded
|
||||||
}
|
};
|
||||||
|
|
||||||
export default mermaid
|
export default mermaid;
|
||||||
|
@@ -1,195 +1,200 @@
|
|||||||
/* eslint-env jasmine */
|
/* eslint-env jasmine */
|
||||||
import mermaid from './mermaid'
|
import mermaid from './mermaid';
|
||||||
import flowDb from './diagrams/flowchart/flowDb'
|
import flowDb from './diagrams/flowchart/flowDb';
|
||||||
import flowParser from './diagrams/flowchart/parser/flow'
|
import flowParser from './diagrams/flowchart/parser/flow';
|
||||||
import flowRenderer from './diagrams/flowchart/flowRenderer'
|
import flowRenderer from './diagrams/flowchart/flowRenderer';
|
||||||
|
|
||||||
describe('when using mermaid and ', function () {
|
describe('when using mermaid and ', function() {
|
||||||
describe('when detecting chart type ', function () {
|
describe('when detecting chart type ', function() {
|
||||||
it('should not start rendering with mermaid.startOnLoad set to false', function () {
|
it('should not start rendering with mermaid.startOnLoad set to false', function() {
|
||||||
mermaid.startOnLoad = false
|
mermaid.startOnLoad = false;
|
||||||
document.body.innerHTML = '<div class="mermaid">graph TD;\na;</div>'
|
document.body.innerHTML = '<div class="mermaid">graph TD;\na;</div>';
|
||||||
spyOn(mermaid, 'init')
|
spyOn(mermaid, 'init');
|
||||||
mermaid.contentLoaded()
|
mermaid.contentLoaded();
|
||||||
expect(mermaid.init).not.toHaveBeenCalled()
|
expect(mermaid.init).not.toHaveBeenCalled();
|
||||||
})
|
});
|
||||||
|
|
||||||
it('should start rendering with both startOnLoad set', function () {
|
it('should start rendering with both startOnLoad set', function() {
|
||||||
mermaid.startOnLoad = true
|
mermaid.startOnLoad = true;
|
||||||
document.body.innerHTML = '<div class="mermaid">graph TD;\na;</div>'
|
document.body.innerHTML = '<div class="mermaid">graph TD;\na;</div>';
|
||||||
spyOn(mermaid, 'init')
|
spyOn(mermaid, 'init');
|
||||||
mermaid.contentLoaded()
|
mermaid.contentLoaded();
|
||||||
expect(mermaid.init).toHaveBeenCalled()
|
expect(mermaid.init).toHaveBeenCalled();
|
||||||
})
|
});
|
||||||
|
|
||||||
it('should start rendering with mermaid.startOnLoad', function () {
|
it('should start rendering with mermaid.startOnLoad', function() {
|
||||||
mermaid.startOnLoad = true
|
mermaid.startOnLoad = true;
|
||||||
document.body.innerHTML = '<div class="mermaid">graph TD;\na;</div>'
|
document.body.innerHTML = '<div class="mermaid">graph TD;\na;</div>';
|
||||||
spyOn(mermaid, 'init')
|
spyOn(mermaid, 'init');
|
||||||
mermaid.contentLoaded()
|
mermaid.contentLoaded();
|
||||||
expect(mermaid.init).toHaveBeenCalled()
|
expect(mermaid.init).toHaveBeenCalled();
|
||||||
})
|
});
|
||||||
|
|
||||||
it('should start rendering as a default with no changes performed', function () {
|
it('should start rendering as a default with no changes performed', function() {
|
||||||
document.body.innerHTML = '<div class="mermaid">graph TD;\na;</div>'
|
document.body.innerHTML = '<div class="mermaid">graph TD;\na;</div>';
|
||||||
spyOn(mermaid, 'init')
|
spyOn(mermaid, 'init');
|
||||||
mermaid.contentLoaded()
|
mermaid.contentLoaded();
|
||||||
expect(mermaid.init).toHaveBeenCalled()
|
expect(mermaid.init).toHaveBeenCalled();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
describe('when calling addEdges ', function () {
|
describe('when calling addEdges ', function() {
|
||||||
beforeEach(function () {
|
beforeEach(function() {
|
||||||
flowParser.parser.yy = flowDb
|
flowParser.parser.yy = flowDb;
|
||||||
flowDb.clear()
|
flowDb.clear();
|
||||||
})
|
});
|
||||||
it('it should handle edges with text', function () {
|
it('it should handle edges with text', function() {
|
||||||
flowParser.parser.parse('graph TD;A-->|text ex|B;')
|
flowParser.parser.parse('graph TD;A-->|text ex|B;');
|
||||||
flowParser.parser.yy.getVertices()
|
flowParser.parser.yy.getVertices();
|
||||||
const edges = flowParser.parser.yy.getEdges()
|
const edges = flowParser.parser.yy.getEdges();
|
||||||
|
|
||||||
const mockG = {
|
const mockG = {
|
||||||
setEdge: function (start, end, options) {
|
setEdge: function(start, end, options) {
|
||||||
expect(start).toBe('A')
|
expect(start).toBe('A');
|
||||||
expect(end).toBe('B')
|
expect(end).toBe('B');
|
||||||
expect(options.arrowhead).toBe('normal')
|
expect(options.arrowhead).toBe('normal');
|
||||||
expect(options.label.match('text ex')).toBeTruthy()
|
expect(options.label.match('text ex')).toBeTruthy();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
flowRenderer.addEdges(edges, mockG)
|
flowRenderer.addEdges(edges, mockG);
|
||||||
})
|
});
|
||||||
|
|
||||||
it('should handle edges without text', function () {
|
it('should handle edges without text', function() {
|
||||||
flowParser.parser.parse('graph TD;A-->B;')
|
flowParser.parser.parse('graph TD;A-->B;');
|
||||||
flowParser.parser.yy.getVertices()
|
flowParser.parser.yy.getVertices();
|
||||||
const edges = flowParser.parser.yy.getEdges()
|
const edges = flowParser.parser.yy.getEdges();
|
||||||
|
|
||||||
const mockG = {
|
const mockG = {
|
||||||
setEdge: function (start, end, options) {
|
setEdge: function(start, end, options) {
|
||||||
expect(start).toBe('A')
|
expect(start).toBe('A');
|
||||||
expect(end).toBe('B')
|
expect(end).toBe('B');
|
||||||
expect(options.arrowhead).toBe('normal')
|
expect(options.arrowhead).toBe('normal');
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
flowRenderer.addEdges(edges, mockG)
|
flowRenderer.addEdges(edges, mockG);
|
||||||
})
|
});
|
||||||
|
|
||||||
it('should handle open-ended edges', function () {
|
it('should handle open-ended edges', function() {
|
||||||
flowParser.parser.parse('graph TD;A---B;')
|
flowParser.parser.parse('graph TD;A---B;');
|
||||||
flowParser.parser.yy.getVertices()
|
flowParser.parser.yy.getVertices();
|
||||||
const edges = flowParser.parser.yy.getEdges()
|
const edges = flowParser.parser.yy.getEdges();
|
||||||
|
|
||||||
const mockG = {
|
const mockG = {
|
||||||
setEdge: function (start, end, options) {
|
setEdge: function(start, end, options) {
|
||||||
expect(start).toBe('A')
|
expect(start).toBe('A');
|
||||||
expect(end).toBe('B')
|
expect(end).toBe('B');
|
||||||
expect(options.arrowhead).toBe('none')
|
expect(options.arrowhead).toBe('none');
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
flowRenderer.addEdges(edges, mockG)
|
flowRenderer.addEdges(edges, mockG);
|
||||||
})
|
});
|
||||||
|
|
||||||
it('should handle edges with styles defined', function () {
|
it('should handle edges with styles defined', function() {
|
||||||
flowParser.parser.parse('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;')
|
flowParser.parser.parse('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;');
|
||||||
flowParser.parser.yy.getVertices()
|
flowParser.parser.yy.getVertices();
|
||||||
const edges = flowParser.parser.yy.getEdges()
|
const edges = flowParser.parser.yy.getEdges();
|
||||||
|
|
||||||
const mockG = {
|
const mockG = {
|
||||||
setEdge: function (start, end, options) {
|
setEdge: function(start, end, options) {
|
||||||
expect(start).toBe('A')
|
expect(start).toBe('A');
|
||||||
expect(end).toBe('B')
|
expect(end).toBe('B');
|
||||||
expect(options.arrowhead).toBe('none')
|
expect(options.arrowhead).toBe('none');
|
||||||
expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;')
|
expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;');
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
flowRenderer.addEdges(edges, mockG)
|
flowRenderer.addEdges(edges, mockG);
|
||||||
})
|
});
|
||||||
it('should handle edges with interpolation defined', function () {
|
it('should handle edges with interpolation defined', function() {
|
||||||
flowParser.parser.parse('graph TD;A---B; linkStyle 0 interpolate basis')
|
flowParser.parser.parse('graph TD;A---B; linkStyle 0 interpolate basis');
|
||||||
flowParser.parser.yy.getVertices()
|
flowParser.parser.yy.getVertices();
|
||||||
const edges = flowParser.parser.yy.getEdges()
|
const edges = flowParser.parser.yy.getEdges();
|
||||||
|
|
||||||
const mockG = {
|
const mockG = {
|
||||||
setEdge: function (start, end, options) {
|
setEdge: function(start, end, options) {
|
||||||
expect(start).toBe('A')
|
expect(start).toBe('A');
|
||||||
expect(end).toBe('B')
|
expect(end).toBe('B');
|
||||||
expect(options.arrowhead).toBe('none')
|
expect(options.arrowhead).toBe('none');
|
||||||
expect(options.curve).toBe('basis') // mocked as string
|
expect(options.curve).toBe('basis'); // mocked as string
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
flowRenderer.addEdges(edges, mockG)
|
flowRenderer.addEdges(edges, mockG);
|
||||||
})
|
});
|
||||||
it('should handle edges with text and styles defined', function () {
|
it('should handle edges with text and styles defined', function() {
|
||||||
flowParser.parser.parse('graph TD;A---|the text|B; linkStyle 0 stroke:val1,stroke-width:val2;')
|
flowParser.parser.parse(
|
||||||
flowParser.parser.yy.getVertices()
|
'graph TD;A---|the text|B; linkStyle 0 stroke:val1,stroke-width:val2;'
|
||||||
const edges = flowParser.parser.yy.getEdges()
|
);
|
||||||
|
flowParser.parser.yy.getVertices();
|
||||||
|
const edges = flowParser.parser.yy.getEdges();
|
||||||
|
|
||||||
const mockG = {
|
const mockG = {
|
||||||
setEdge: function (start, end, options) {
|
setEdge: function(start, end, options) {
|
||||||
expect(start).toBe('A')
|
expect(start).toBe('A');
|
||||||
expect(end).toBe('B')
|
expect(end).toBe('B');
|
||||||
expect(options.arrowhead).toBe('none')
|
expect(options.arrowhead).toBe('none');
|
||||||
expect(options.label.match('the text')).toBeTruthy()
|
expect(options.label.match('the text')).toBeTruthy();
|
||||||
expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;')
|
expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;');
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
flowRenderer.addEdges(edges, mockG)
|
flowRenderer.addEdges(edges, mockG);
|
||||||
})
|
});
|
||||||
|
|
||||||
it('should set fill to "none" by default when handling edges', function () {
|
it('should set fill to "none" by default when handling edges', function() {
|
||||||
flowParser.parser.parse('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;')
|
flowParser.parser.parse('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;');
|
||||||
flowParser.parser.yy.getVertices()
|
flowParser.parser.yy.getVertices();
|
||||||
const edges = flowParser.parser.yy.getEdges()
|
const edges = flowParser.parser.yy.getEdges();
|
||||||
|
|
||||||
const mockG = {
|
const mockG = {
|
||||||
setEdge: function (start, end, options) {
|
setEdge: function(start, end, options) {
|
||||||
expect(start).toBe('A')
|
expect(start).toBe('A');
|
||||||
expect(end).toBe('B')
|
expect(end).toBe('B');
|
||||||
expect(options.arrowhead).toBe('none')
|
expect(options.arrowhead).toBe('none');
|
||||||
expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;')
|
expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;');
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
flowRenderer.addEdges(edges, mockG)
|
flowRenderer.addEdges(edges, mockG);
|
||||||
})
|
});
|
||||||
|
|
||||||
it('should not set fill to none if fill is set in linkStyle', function () {
|
it('should not set fill to none if fill is set in linkStyle', function() {
|
||||||
flowParser.parser.parse('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2,fill:blue;')
|
flowParser.parser.parse(
|
||||||
flowParser.parser.yy.getVertices()
|
'graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2,fill:blue;'
|
||||||
const edges = flowParser.parser.yy.getEdges()
|
);
|
||||||
|
flowParser.parser.yy.getVertices();
|
||||||
|
const edges = flowParser.parser.yy.getEdges();
|
||||||
const mockG = {
|
const mockG = {
|
||||||
setEdge: function (start, end, options) {
|
setEdge: function(start, end, options) {
|
||||||
expect(start).toBe('A')
|
expect(start).toBe('A');
|
||||||
expect(end).toBe('B')
|
expect(end).toBe('B');
|
||||||
expect(options.arrowhead).toBe('none')
|
expect(options.arrowhead).toBe('none');
|
||||||
expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:blue;')
|
expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:blue;');
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
flowRenderer.addEdges(edges, mockG)
|
flowRenderer.addEdges(edges, mockG);
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
describe('checking validity of input ', function () {
|
describe('checking validity of input ', function() {
|
||||||
it('it should throw for an invalid definiton', function () {
|
it('it should throw for an invalid definiton', function() {
|
||||||
expect(() => mermaid.parse('this is not a mermaid diagram definition')).toThrow()
|
expect(() => mermaid.parse('this is not a mermaid diagram definition')).toThrow();
|
||||||
})
|
});
|
||||||
|
|
||||||
it('it should not throw for a valid flow definition', function () {
|
it('it should not throw for a valid flow definition', function() {
|
||||||
expect(() => mermaid.parse('graph TD;A--x|text including URL space|B;')).not.toThrow()
|
expect(() => mermaid.parse('graph TD;A--x|text including URL space|B;')).not.toThrow();
|
||||||
})
|
});
|
||||||
it('it should throw for an invalid flow definition', function () {
|
it('it should throw for an invalid flow definition', function() {
|
||||||
expect(() => mermaid.parse('graph TQ;A--x|text including URL space|B;')).toThrow()
|
expect(() => mermaid.parse('graph TQ;A--x|text including URL space|B;')).toThrow();
|
||||||
})
|
});
|
||||||
|
|
||||||
it('it should not throw for a valid sequenceDiagram definition', function () {
|
it('it should not throw for a valid sequenceDiagram definition', function() {
|
||||||
const text = 'sequenceDiagram\n' +
|
const text =
|
||||||
|
'sequenceDiagram\n' +
|
||||||
'Alice->Bob: Hello Bob, how are you?\n\n' +
|
'Alice->Bob: Hello Bob, how are you?\n\n' +
|
||||||
'%% Comment\n' +
|
'%% Comment\n' +
|
||||||
'Note right of Bob: Bob thinks\n' +
|
'Note right of Bob: Bob thinks\n' +
|
||||||
@@ -197,12 +202,13 @@ describe('when using mermaid and ', function () {
|
|||||||
'Bob-->Alice: I am good thanks!\n' +
|
'Bob-->Alice: I am good thanks!\n' +
|
||||||
'else isSick\n' +
|
'else isSick\n' +
|
||||||
'Bob-->Alice: Feel sick...\n' +
|
'Bob-->Alice: Feel sick...\n' +
|
||||||
'end'
|
'end';
|
||||||
expect(() => mermaid.parse(text)).not.toThrow()
|
expect(() => mermaid.parse(text)).not.toThrow();
|
||||||
})
|
});
|
||||||
|
|
||||||
it('it should throw for an invalid sequenceDiagram definition', function () {
|
it('it should throw for an invalid sequenceDiagram definition', function() {
|
||||||
const text = 'sequenceDiagram\n' +
|
const text =
|
||||||
|
'sequenceDiagram\n' +
|
||||||
'Alice:->Bob: Hello Bob, how are you?\n\n' +
|
'Alice:->Bob: Hello Bob, how are you?\n\n' +
|
||||||
'%% Comment\n' +
|
'%% Comment\n' +
|
||||||
'Note right of Bob: Bob thinks\n' +
|
'Note right of Bob: Bob thinks\n' +
|
||||||
@@ -210,8 +216,8 @@ describe('when using mermaid and ', function () {
|
|||||||
'Bob-->Alice: I am good thanks!\n' +
|
'Bob-->Alice: I am good thanks!\n' +
|
||||||
'else isSick\n' +
|
'else isSick\n' +
|
||||||
'Bob-->Alice: Feel sick...\n' +
|
'Bob-->Alice: Feel sick...\n' +
|
||||||
'end'
|
'end';
|
||||||
expect(() => mermaid.parse(text)).toThrow()
|
expect(() => mermaid.parse(text)).toThrow();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
@@ -9,38 +9,38 @@
|
|||||||
* In addition to the render function, a number of behavioral configuration options are available.
|
* In addition to the render function, a number of behavioral configuration options are available.
|
||||||
*
|
*
|
||||||
* @name mermaidAPI
|
* @name mermaidAPI
|
||||||
*/
|
*/
|
||||||
import * as d3 from 'd3'
|
import * as d3 from 'd3';
|
||||||
import scope from 'scope-css'
|
import scope from 'scope-css';
|
||||||
import pkg from '../package.json'
|
import pkg from '../package.json';
|
||||||
import { setConfig, getConfig } from './config'
|
import { setConfig, getConfig } from './config';
|
||||||
import { logger, setLogLevel } from './logger'
|
import { logger, setLogLevel } from './logger';
|
||||||
import utils from './utils'
|
import utils from './utils';
|
||||||
import flowRenderer from './diagrams/flowchart/flowRenderer'
|
import flowRenderer from './diagrams/flowchart/flowRenderer';
|
||||||
import flowParser from './diagrams/flowchart/parser/flow'
|
import flowParser from './diagrams/flowchart/parser/flow';
|
||||||
import flowDb from './diagrams/flowchart/flowDb'
|
import flowDb from './diagrams/flowchart/flowDb';
|
||||||
import sequenceRenderer from './diagrams/sequence/sequenceRenderer'
|
import sequenceRenderer from './diagrams/sequence/sequenceRenderer';
|
||||||
import sequenceParser from './diagrams/sequence/parser/sequenceDiagram'
|
import sequenceParser from './diagrams/sequence/parser/sequenceDiagram';
|
||||||
import sequenceDb from './diagrams/sequence/sequenceDb'
|
import sequenceDb from './diagrams/sequence/sequenceDb';
|
||||||
import ganttRenderer from './diagrams/gantt/ganttRenderer'
|
import ganttRenderer from './diagrams/gantt/ganttRenderer';
|
||||||
import ganttParser from './diagrams/gantt/parser/gantt'
|
import ganttParser from './diagrams/gantt/parser/gantt';
|
||||||
import ganttDb from './diagrams/gantt/ganttDb'
|
import ganttDb from './diagrams/gantt/ganttDb';
|
||||||
import classRenderer from './diagrams/class/classRenderer'
|
import classRenderer from './diagrams/class/classRenderer';
|
||||||
import classParser from './diagrams/class/parser/classDiagram'
|
import classParser from './diagrams/class/parser/classDiagram';
|
||||||
import classDb from './diagrams/class/classDb'
|
import classDb from './diagrams/class/classDb';
|
||||||
import gitGraphRenderer from './diagrams/git/gitGraphRenderer'
|
import gitGraphRenderer from './diagrams/git/gitGraphRenderer';
|
||||||
import gitGraphParser from './diagrams/git/parser/gitGraph'
|
import gitGraphParser from './diagrams/git/parser/gitGraph';
|
||||||
import gitGraphAst from './diagrams/git/gitGraphAst'
|
import gitGraphAst from './diagrams/git/gitGraphAst';
|
||||||
import infoRenderer from './diagrams/info/infoRenderer'
|
import infoRenderer from './diagrams/info/infoRenderer';
|
||||||
import infoParser from './diagrams/info/parser/info'
|
import infoParser from './diagrams/info/parser/info';
|
||||||
import infoDb from './diagrams/info/infoDb'
|
import infoDb from './diagrams/info/infoDb';
|
||||||
import pieRenderer from './diagrams/pie/pieRenderer'
|
import pieRenderer from './diagrams/pie/pieRenderer';
|
||||||
import pieParser from './diagrams/pie/parser/pie'
|
import pieParser from './diagrams/pie/parser/pie';
|
||||||
import pieDb from './diagrams/pie/pieDb'
|
import pieDb from './diagrams/pie/pieDb';
|
||||||
|
|
||||||
const themes = {}
|
const themes = {};
|
||||||
for (const themeName of ['default', 'forest', 'dark', 'neutral']) {
|
for (const themeName of ['default', 'forest', 'dark', 'neutral']) {
|
||||||
themes[themeName] = require(`./themes/${themeName}/index.scss`)
|
themes[themeName] = require(`./themes/${themeName}/index.scss`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -75,7 +75,6 @@ for (const themeName of ['default', 'forest', 'dark', 'neutral']) {
|
|||||||
* @name Configuration
|
* @name Configuration
|
||||||
*/
|
*/
|
||||||
const config = {
|
const config = {
|
||||||
|
|
||||||
/** theme , the CSS style sheet
|
/** theme , the CSS style sheet
|
||||||
*
|
*
|
||||||
* **theme** - Choose one of the built-in themes:
|
* **theme** - Choose one of the built-in themes:
|
||||||
@@ -149,7 +148,6 @@ const config = {
|
|||||||
* The object containing configurations specific for sequence diagrams
|
* The object containing configurations specific for sequence diagrams
|
||||||
*/
|
*/
|
||||||
sequence: {
|
sequence: {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* margin to the right and left of the sequence diagram.
|
* margin to the right and left of the sequence diagram.
|
||||||
* **Default value 50**.
|
* **Default value 50**.
|
||||||
@@ -234,7 +232,6 @@ const config = {
|
|||||||
* **Default value false**.
|
* **Default value false**.
|
||||||
*/
|
*/
|
||||||
showSequenceNumbers: false
|
showSequenceNumbers: false
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -303,100 +300,100 @@ const config = {
|
|||||||
},
|
},
|
||||||
class: {},
|
class: {},
|
||||||
git: {}
|
git: {}
|
||||||
}
|
};
|
||||||
|
|
||||||
setLogLevel(config.logLevel)
|
setLogLevel(config.logLevel);
|
||||||
setConfig(config)
|
setConfig(config);
|
||||||
|
|
||||||
function parse (text) {
|
function parse(text) {
|
||||||
const graphType = utils.detectType(text)
|
const graphType = utils.detectType(text);
|
||||||
let parser
|
let parser;
|
||||||
|
|
||||||
logger.debug('Type ' + graphType)
|
logger.debug('Type ' + graphType);
|
||||||
switch (graphType) {
|
switch (graphType) {
|
||||||
case 'git':
|
case 'git':
|
||||||
parser = gitGraphParser
|
parser = gitGraphParser;
|
||||||
parser.parser.yy = gitGraphAst
|
parser.parser.yy = gitGraphAst;
|
||||||
break
|
break;
|
||||||
case 'flowchart':
|
case 'flowchart':
|
||||||
parser = flowParser
|
parser = flowParser;
|
||||||
parser.parser.yy = flowDb
|
parser.parser.yy = flowDb;
|
||||||
break
|
break;
|
||||||
case 'sequence':
|
case 'sequence':
|
||||||
parser = sequenceParser
|
parser = sequenceParser;
|
||||||
parser.parser.yy = sequenceDb
|
parser.parser.yy = sequenceDb;
|
||||||
break
|
break;
|
||||||
case 'gantt':
|
case 'gantt':
|
||||||
parser = ganttParser
|
parser = ganttParser;
|
||||||
parser.parser.yy = ganttDb
|
parser.parser.yy = ganttDb;
|
||||||
break
|
break;
|
||||||
case 'class':
|
case 'class':
|
||||||
parser = classParser
|
parser = classParser;
|
||||||
parser.parser.yy = classDb
|
parser.parser.yy = classDb;
|
||||||
break
|
break;
|
||||||
case 'info':
|
case 'info':
|
||||||
logger.debug('info info info')
|
logger.debug('info info info');
|
||||||
console.warn('In API', pkg.version)
|
console.warn('In API', pkg.version);
|
||||||
|
|
||||||
parser = infoParser
|
parser = infoParser;
|
||||||
parser.parser.yy = infoDb
|
parser.parser.yy = infoDb;
|
||||||
break
|
break;
|
||||||
case 'pie':
|
case 'pie':
|
||||||
logger.debug('pie')
|
logger.debug('pie');
|
||||||
parser = pieParser
|
parser = pieParser;
|
||||||
parser.parser.yy = pieDb
|
parser.parser.yy = pieDb;
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
parser.parser.yy.parseError = (str, hash) => {
|
parser.parser.yy.parseError = (str, hash) => {
|
||||||
const error = { str, hash }
|
const error = { str, hash };
|
||||||
throw error
|
throw error;
|
||||||
}
|
};
|
||||||
|
|
||||||
parser.parse(text)
|
parser.parse(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const encodeEntities = function (text) {
|
export const encodeEntities = function(text) {
|
||||||
let txt = text
|
let txt = text;
|
||||||
|
|
||||||
txt = txt.replace(/style.*:\S*#.*;/g, function (s) {
|
txt = txt.replace(/style.*:\S*#.*;/g, function(s) {
|
||||||
const innerTxt = s.substring(0, s.length - 1)
|
const innerTxt = s.substring(0, s.length - 1);
|
||||||
return innerTxt
|
return innerTxt;
|
||||||
})
|
});
|
||||||
txt = txt.replace(/classDef.*:\S*#.*;/g, function (s) {
|
txt = txt.replace(/classDef.*:\S*#.*;/g, function(s) {
|
||||||
const innerTxt = s.substring(0, s.length - 1)
|
const innerTxt = s.substring(0, s.length - 1);
|
||||||
return innerTxt
|
return innerTxt;
|
||||||
})
|
});
|
||||||
|
|
||||||
txt = txt.replace(/#\w+;/g, function (s) {
|
txt = txt.replace(/#\w+;/g, function(s) {
|
||||||
const innerTxt = s.substring(1, s.length - 1)
|
const innerTxt = s.substring(1, s.length - 1);
|
||||||
|
|
||||||
const isInt = /^\+?\d+$/.test(innerTxt)
|
const isInt = /^\+?\d+$/.test(innerTxt);
|
||||||
if (isInt) {
|
if (isInt) {
|
||||||
return 'fl°°' + innerTxt + '¶ß'
|
return 'fl°°' + innerTxt + '¶ß';
|
||||||
} else {
|
} else {
|
||||||
return 'fl°' + innerTxt + '¶ß'
|
return 'fl°' + innerTxt + '¶ß';
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
return txt
|
return txt;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const decodeEntities = function (text) {
|
export const decodeEntities = function(text) {
|
||||||
let txt = text
|
let txt = text;
|
||||||
|
|
||||||
txt = txt.replace(/fl°°/g, function () {
|
txt = txt.replace(/fl°°/g, function() {
|
||||||
return '&#'
|
return '&#';
|
||||||
})
|
});
|
||||||
txt = txt.replace(/fl°/g, function () {
|
txt = txt.replace(/fl°/g, function() {
|
||||||
return '&'
|
return '&';
|
||||||
})
|
});
|
||||||
txt = txt.replace(/¶ß/g, function () {
|
txt = txt.replace(/¶ß/g, function() {
|
||||||
return ';'
|
return ';';
|
||||||
})
|
});
|
||||||
|
|
||||||
return txt
|
return txt;
|
||||||
}
|
};
|
||||||
/**
|
/**
|
||||||
* Function that renders an svg with a graph from a chart definition. Usage example below.
|
* Function that renders an svg with a graph from a chart definition. Usage example below.
|
||||||
*
|
*
|
||||||
@@ -419,183 +416,209 @@ export const decodeEntities = function (text) {
|
|||||||
* provided a hidden div will be inserted in the body of the page instead. The element will be removed when rendering is
|
* provided a hidden div will be inserted in the body of the page instead. The element will be removed when rendering is
|
||||||
* completed.
|
* completed.
|
||||||
*/
|
*/
|
||||||
const render = function (id, txt, cb, container) {
|
const render = function(id, txt, cb, container) {
|
||||||
if (typeof container !== 'undefined') {
|
if (typeof container !== 'undefined') {
|
||||||
container.innerHTML = ''
|
container.innerHTML = '';
|
||||||
|
|
||||||
d3.select(container).append('div')
|
d3.select(container)
|
||||||
|
.append('div')
|
||||||
.attr('id', 'd' + id)
|
.attr('id', 'd' + id)
|
||||||
.append('svg')
|
.append('svg')
|
||||||
.attr('id', id)
|
.attr('id', id)
|
||||||
.attr('width', '100%')
|
.attr('width', '100%')
|
||||||
.attr('xmlns', 'http://www.w3.org/2000/svg')
|
.attr('xmlns', 'http://www.w3.org/2000/svg')
|
||||||
.append('g')
|
.append('g');
|
||||||
} else {
|
} else {
|
||||||
const element = document.querySelector('#' + 'd' + id)
|
const element = document.querySelector('#' + 'd' + id);
|
||||||
if (element) {
|
if (element) {
|
||||||
element.innerHTML = ''
|
element.innerHTML = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
d3.select('body').append('div')
|
d3.select('body')
|
||||||
|
.append('div')
|
||||||
.attr('id', 'd' + id)
|
.attr('id', 'd' + id)
|
||||||
.append('svg')
|
.append('svg')
|
||||||
.attr('id', id)
|
.attr('id', id)
|
||||||
.attr('width', '100%')
|
.attr('width', '100%')
|
||||||
.attr('xmlns', 'http://www.w3.org/2000/svg')
|
.attr('xmlns', 'http://www.w3.org/2000/svg')
|
||||||
.append('g')
|
.append('g');
|
||||||
}
|
}
|
||||||
|
|
||||||
window.txt = txt
|
window.txt = txt;
|
||||||
txt = encodeEntities(txt)
|
txt = encodeEntities(txt);
|
||||||
|
|
||||||
const element = d3.select('#d' + id).node()
|
const element = d3.select('#d' + id).node();
|
||||||
const graphType = utils.detectType(txt)
|
const graphType = utils.detectType(txt);
|
||||||
|
|
||||||
// insert inline style into svg
|
// insert inline style into svg
|
||||||
const svg = element.firstChild
|
const svg = element.firstChild;
|
||||||
const firstChild = svg.firstChild
|
const firstChild = svg.firstChild;
|
||||||
|
|
||||||
// pre-defined theme
|
// pre-defined theme
|
||||||
let style = themes[config.theme]
|
let style = themes[config.theme];
|
||||||
if (style === undefined) {
|
if (style === undefined) {
|
||||||
style = ''
|
style = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
// user provided theme CSS
|
// user provided theme CSS
|
||||||
if (config.themeCSS !== undefined) {
|
if (config.themeCSS !== undefined) {
|
||||||
style += `\n${config.themeCSS}`
|
style += `\n${config.themeCSS}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// classDef
|
// classDef
|
||||||
if (graphType === 'flowchart') {
|
if (graphType === 'flowchart') {
|
||||||
const classes = flowRenderer.getClasses(txt)
|
const classes = flowRenderer.getClasses(txt);
|
||||||
for (const className in classes) {
|
for (const className in classes) {
|
||||||
style += `\n.${className} > * { ${classes[className].styles.join(' !important; ')} !important; }`
|
style += `\n.${className} > * { ${classes[className].styles.join(
|
||||||
|
' !important; '
|
||||||
|
)} !important; }`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const style1 = document.createElement('style')
|
const style1 = document.createElement('style');
|
||||||
style1.innerHTML = scope(style, `#${id}`)
|
style1.innerHTML = scope(style, `#${id}`);
|
||||||
svg.insertBefore(style1, firstChild)
|
svg.insertBefore(style1, firstChild);
|
||||||
|
|
||||||
const style2 = document.createElement('style')
|
const style2 = document.createElement('style');
|
||||||
const cs = window.getComputedStyle(svg)
|
const cs = window.getComputedStyle(svg);
|
||||||
style2.innerHTML = `#${id} {
|
style2.innerHTML = `#${id} {
|
||||||
color: ${cs.color};
|
color: ${cs.color};
|
||||||
font: ${cs.font};
|
font: ${cs.font};
|
||||||
}`
|
}`;
|
||||||
svg.insertBefore(style2, firstChild)
|
svg.insertBefore(style2, firstChild);
|
||||||
|
|
||||||
switch (graphType) {
|
switch (graphType) {
|
||||||
case 'git':
|
case 'git':
|
||||||
config.flowchart.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
config.flowchart.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||||||
gitGraphRenderer.setConf(config.git)
|
gitGraphRenderer.setConf(config.git);
|
||||||
gitGraphRenderer.draw(txt, id, false)
|
gitGraphRenderer.draw(txt, id, false);
|
||||||
break
|
break;
|
||||||
case 'flowchart':
|
case 'flowchart':
|
||||||
config.flowchart.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
config.flowchart.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||||||
flowRenderer.setConf(config.flowchart)
|
flowRenderer.setConf(config.flowchart);
|
||||||
flowRenderer.draw(txt, id, false)
|
flowRenderer.draw(txt, id, false);
|
||||||
break
|
break;
|
||||||
case 'sequence':
|
case 'sequence':
|
||||||
config.sequence.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
config.sequence.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||||||
if (config.sequenceDiagram) { // backwards compatibility
|
if (config.sequenceDiagram) {
|
||||||
sequenceRenderer.setConf(Object.assign(config.sequence, config.sequenceDiagram))
|
// backwards compatibility
|
||||||
console.error('`mermaid config.sequenceDiagram` has been renamed to `config.sequence`. Please update your mermaid config.')
|
sequenceRenderer.setConf(Object.assign(config.sequence, config.sequenceDiagram));
|
||||||
|
console.error(
|
||||||
|
'`mermaid config.sequenceDiagram` has been renamed to `config.sequence`. Please update your mermaid config.'
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
sequenceRenderer.setConf(config.sequence)
|
sequenceRenderer.setConf(config.sequence);
|
||||||
}
|
}
|
||||||
sequenceRenderer.draw(txt, id)
|
sequenceRenderer.draw(txt, id);
|
||||||
break
|
break;
|
||||||
case 'gantt':
|
case 'gantt':
|
||||||
config.gantt.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
config.gantt.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||||||
ganttRenderer.setConf(config.gantt)
|
ganttRenderer.setConf(config.gantt);
|
||||||
ganttRenderer.draw(txt, id)
|
ganttRenderer.draw(txt, id);
|
||||||
break
|
break;
|
||||||
case 'class':
|
case 'class':
|
||||||
config.class.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
config.class.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||||||
classRenderer.setConf(config.class)
|
classRenderer.setConf(config.class);
|
||||||
classRenderer.draw(txt, id)
|
classRenderer.draw(txt, id);
|
||||||
break
|
break;
|
||||||
case 'info':
|
case 'info':
|
||||||
config.class.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
config.class.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||||||
infoRenderer.setConf(config.class)
|
infoRenderer.setConf(config.class);
|
||||||
infoRenderer.draw(txt, id, pkg.version)
|
infoRenderer.draw(txt, id, pkg.version);
|
||||||
break
|
break;
|
||||||
case 'pie':
|
case 'pie':
|
||||||
config.class.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
config.class.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||||||
pieRenderer.setConf(config.class)
|
pieRenderer.setConf(config.class);
|
||||||
pieRenderer.draw(txt, id, pkg.version)
|
pieRenderer.draw(txt, id, pkg.version);
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
d3.select(`[id="${id}"]`).selectAll('foreignobject > *').attr('xmlns', 'http://www.w3.org/1999/xhtml')
|
d3.select(`[id="${id}"]`)
|
||||||
|
.selectAll('foreignobject > *')
|
||||||
|
.attr('xmlns', 'http://www.w3.org/1999/xhtml');
|
||||||
|
|
||||||
let url = ''
|
let url = '';
|
||||||
if (config.arrowMarkerAbsolute) {
|
if (config.arrowMarkerAbsolute) {
|
||||||
url = window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.search
|
url =
|
||||||
url = url.replace(/\(/g, '\\(')
|
window.location.protocol +
|
||||||
url = url.replace(/\)/g, '\\)')
|
'//' +
|
||||||
|
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
|
// Fix for when the base tag is used
|
||||||
let svgCode = d3.select('#d' + id).node().innerHTML.replace(/url\(#arrowhead/g, 'url(' + url + '#arrowhead', 'g')
|
let svgCode = d3
|
||||||
|
.select('#d' + id)
|
||||||
|
.node()
|
||||||
|
.innerHTML.replace(/url\(#arrowhead/g, 'url(' + url + '#arrowhead', 'g');
|
||||||
|
|
||||||
svgCode = decodeEntities(svgCode)
|
svgCode = decodeEntities(svgCode);
|
||||||
|
|
||||||
if (typeof cb !== 'undefined') {
|
if (typeof cb !== 'undefined') {
|
||||||
switch (graphType) {
|
switch (graphType) {
|
||||||
case 'flowchart':
|
case 'flowchart':
|
||||||
cb(svgCode, flowDb.bindFunctions)
|
cb(svgCode, flowDb.bindFunctions);
|
||||||
break
|
break;
|
||||||
case 'gantt':
|
case 'gantt':
|
||||||
cb(svgCode, ganttDb.bindFunctions)
|
cb(svgCode, ganttDb.bindFunctions);
|
||||||
break
|
break;
|
||||||
default:
|
default:
|
||||||
cb(svgCode)
|
cb(svgCode);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.debug('CB = undefined!')
|
logger.debug('CB = undefined!');
|
||||||
}
|
}
|
||||||
|
|
||||||
const node = d3.select('#d' + id).node()
|
const node = d3.select('#d' + id).node();
|
||||||
if (node !== null && typeof node.remove === 'function') {
|
if (node !== null && typeof node.remove === 'function') {
|
||||||
d3.select('#d' + id).node().remove()
|
d3.select('#d' + id)
|
||||||
|
.node()
|
||||||
|
.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
return svgCode
|
return svgCode;
|
||||||
}
|
};
|
||||||
|
|
||||||
const setConf = function (cnf) {
|
const setConf = function(cnf) {
|
||||||
// Top level initially mermaid, gflow, sequenceDiagram and gantt
|
// Top level initially mermaid, gflow, sequenceDiagram and gantt
|
||||||
const lvl1Keys = Object.keys(cnf)
|
const lvl1Keys = Object.keys(cnf);
|
||||||
for (let i = 0; i < lvl1Keys.length; i++) {
|
for (let i = 0; i < lvl1Keys.length; i++) {
|
||||||
if (typeof cnf[lvl1Keys[i]] === 'object' && cnf[lvl1Keys[i]] != null) {
|
if (typeof cnf[lvl1Keys[i]] === 'object' && cnf[lvl1Keys[i]] != null) {
|
||||||
const lvl2Keys = Object.keys(cnf[lvl1Keys[i]])
|
const lvl2Keys = Object.keys(cnf[lvl1Keys[i]]);
|
||||||
|
|
||||||
for (let j = 0; j < lvl2Keys.length; j++) {
|
for (let j = 0; j < lvl2Keys.length; j++) {
|
||||||
logger.debug('Setting conf ', lvl1Keys[i], '-', lvl2Keys[j])
|
logger.debug('Setting conf ', lvl1Keys[i], '-', lvl2Keys[j]);
|
||||||
if (typeof config[lvl1Keys[i]] === 'undefined') {
|
if (typeof config[lvl1Keys[i]] === 'undefined') {
|
||||||
config[lvl1Keys[i]] = {}
|
config[lvl1Keys[i]] = {};
|
||||||
}
|
}
|
||||||
logger.debug('Setting config: ' + lvl1Keys[i] + ' ' + lvl2Keys[j] + ' to ' + cnf[lvl1Keys[i]][lvl2Keys[j]])
|
logger.debug(
|
||||||
config[lvl1Keys[i]][lvl2Keys[j]] = cnf[lvl1Keys[i]][lvl2Keys[j]]
|
'Setting config: ' +
|
||||||
|
lvl1Keys[i] +
|
||||||
|
' ' +
|
||||||
|
lvl2Keys[j] +
|
||||||
|
' to ' +
|
||||||
|
cnf[lvl1Keys[i]][lvl2Keys[j]]
|
||||||
|
);
|
||||||
|
config[lvl1Keys[i]][lvl2Keys[j]] = cnf[lvl1Keys[i]][lvl2Keys[j]];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
config[lvl1Keys[i]] = cnf[lvl1Keys[i]]
|
config[lvl1Keys[i]] = cnf[lvl1Keys[i]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
function initialize (options) {
|
function initialize(options) {
|
||||||
logger.debug('Initializing mermaidAPI ', pkg.version)
|
logger.debug('Initializing mermaidAPI ', pkg.version);
|
||||||
|
|
||||||
// Update default config with options supplied at initialization
|
// Update default config with options supplied at initialization
|
||||||
if (typeof options === 'object') {
|
if (typeof options === 'object') {
|
||||||
setConf(options)
|
setConf(options);
|
||||||
}
|
}
|
||||||
setConfig(config)
|
setConfig(config);
|
||||||
setLogLevel(config.logLevel)
|
setLogLevel(config.logLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
// function getConfig () {
|
// function getConfig () {
|
||||||
@@ -608,9 +631,9 @@ const mermaidAPI = {
|
|||||||
parse,
|
parse,
|
||||||
initialize,
|
initialize,
|
||||||
getConfig
|
getConfig
|
||||||
}
|
};
|
||||||
|
|
||||||
export default mermaidAPI
|
export default mermaidAPI;
|
||||||
/**
|
/**
|
||||||
* ## mermaidAPI configuration defaults
|
* ## mermaidAPI configuration defaults
|
||||||
* <pre>
|
* <pre>
|
||||||
|
@@ -1,45 +1,45 @@
|
|||||||
/* eslint-env jasmine */
|
/* eslint-env jasmine */
|
||||||
import mermaidAPI from './mermaidAPI'
|
import mermaidAPI from './mermaidAPI';
|
||||||
|
|
||||||
describe('when using mermaidAPI and ', function () {
|
describe('when using mermaidAPI and ', function() {
|
||||||
describe('doing initialize ', function () {
|
describe('doing initialize ', function() {
|
||||||
beforeEach(function () {
|
beforeEach(function() {
|
||||||
document.body.innerHTML = ''
|
document.body.innerHTML = '';
|
||||||
})
|
});
|
||||||
|
|
||||||
it('should copy a literal into the configuration', function () {
|
it('should copy a literal into the configuration', function() {
|
||||||
const orgConfig = mermaidAPI.getConfig()
|
const orgConfig = mermaidAPI.getConfig();
|
||||||
expect(orgConfig.testLiteral).toBe(undefined)
|
expect(orgConfig.testLiteral).toBe(undefined);
|
||||||
|
|
||||||
mermaidAPI.initialize({ 'testLiteral': true })
|
mermaidAPI.initialize({ testLiteral: true });
|
||||||
const config = mermaidAPI.getConfig()
|
const config = mermaidAPI.getConfig();
|
||||||
|
|
||||||
expect(config.testLiteral).toBe(true)
|
expect(config.testLiteral).toBe(true);
|
||||||
})
|
});
|
||||||
it('should copy a an object into the configuration', function () {
|
it('should copy a an object into the configuration', function() {
|
||||||
const orgConfig = mermaidAPI.getConfig()
|
const orgConfig = mermaidAPI.getConfig();
|
||||||
expect(orgConfig.testObject).toBe(undefined)
|
expect(orgConfig.testObject).toBe(undefined);
|
||||||
|
|
||||||
const object = {
|
const object = {
|
||||||
test1: 1,
|
test1: 1,
|
||||||
test2: false
|
test2: false
|
||||||
}
|
};
|
||||||
|
|
||||||
mermaidAPI.initialize({ 'testObject': object })
|
mermaidAPI.initialize({ testObject: object });
|
||||||
mermaidAPI.initialize({ 'testObject': { 'test3': true } })
|
mermaidAPI.initialize({ testObject: { test3: true } });
|
||||||
const config = mermaidAPI.getConfig()
|
const config = mermaidAPI.getConfig();
|
||||||
|
|
||||||
expect(config.testObject.test1).toBe(1)
|
expect(config.testObject.test1).toBe(1);
|
||||||
expect(config.testObject.test2).toBe(false)
|
expect(config.testObject.test2).toBe(false);
|
||||||
expect(config.testObject.test3).toBe(true)
|
expect(config.testObject.test3).toBe(true);
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
describe('checking validity of input ', function () {
|
describe('checking validity of input ', function() {
|
||||||
it('it should throw for an invalid definiton', function () {
|
it('it should throw for an invalid definiton', function() {
|
||||||
expect(() => mermaidAPI.parse('this is not a mermaid diagram definition')).toThrow()
|
expect(() => mermaidAPI.parse('this is not a mermaid diagram definition')).toThrow();
|
||||||
})
|
});
|
||||||
it('it should not throw for a valid definiton', function () {
|
it('it should not throw for a valid definiton', function() {
|
||||||
expect(() => mermaidAPI.parse('graph TD;A--x|text including URL space|B;')).not.toThrow()
|
expect(() => mermaidAPI.parse('graph TD;A--x|text including URL space|B;')).not.toThrow();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
Reference in New Issue
Block a user