Merge pull request #3210 from mermaid-js/3061_refactoring_and_modularisation

3061 refactoring and modularisation
This commit is contained in:
Knut Sveidqvist 2022-07-10 07:33:47 +02:00 committed by GitHub
commit c20c362557
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 583 additions and 721 deletions

View File

@ -31,14 +31,15 @@
<div class="mermaid2" style="width: 50%;">
journey
title Adding journey diagram functionality to mermaid
accTitle: Adding acc journey diagram functionality to mermaid
accDescr {
My multi-line description
of the diagram
}
section Order from website
journey
title My working day
section Go to work
Make tea: 5: Me
Go upstairs: 3: Me
Do work: 1: Me, Cat
section Go home
Go downstairs: 5: Me
Sit down: 5: Mee
</div>
<div class="mermaid2" style="width: 50%;">
pie
@ -52,20 +53,16 @@
"Iron" : 5
</div>
<div class="mermaid2" style="width: 50%;">
gitGraph
accTitle: My Gitgraph Accessibility Title
accDescr: My Gitgraph Accessibility Description
commit
commit
branch develop
checkout develop
commit
commit
checkout main
merge develop
commit
commit
gitGraph
commit
commit
branch develop
commit
commit
commit
checkout main
commit
commit
</div>
<div class="mermaid2" style="width: 50%;">
sequenceDiagram
@ -99,6 +96,9 @@ graph TD
Sit down: 5: Me
</div>
<div class="mermaid2" style="width: 100%;">
info
</div>
<div class="mermaid2" style="width: 100%;">
requirementDiagram
accTitle: My req Diagram
accDescr: My req Diagram Description
@ -138,8 +138,41 @@ requirementDiagram
test_req - traces -> test_req2
test_req - contains -> test_req3
test_req <- copies - test_entity2
</div>
<div class="mermaid" style="width: 100%;">
<div class="mermaid2" style="width: 100%;">
gantt
dateFormat YYYY-MM-DD
title Adding GANTT diagram functionality to mermaid
excludes weekends
%% (`excludes` accepts specific dates in YYYY-MM-DD format, days of the week ("sunday") or "weekends", but not the word "weekdays".)
section A section
Completed task :done, des1, 2014-01-06,2014-01-08
Active task :active, des2, 2014-01-09, 3d
Future task : des3, after des2, 5d
Future task2 : des4, after des3, 5d
section Critical tasks
Completed task in the critical line :crit, done, 2014-01-06,24h
Implement parser and jison :crit, done, after des1, 2d
Create tests for parser :crit, active, 3d
Future task in critical line :crit, 5d
Create tests for renderer :2d
Add to mermaid :1d
Functionality added :milestone, 2014-01-25, 0d
section Documentation
Describe gantt syntax :active, a1, after des1, 3d
Add gantt diagram to demo page :after a1 , 20h
Add another diagram to demo page :doc1, after a1 , 48h
section Last section
Describe gantt syntax :after doc1, 3d
Add gantt diagram to demo page :20h
Add another diagram to demo page :48h
</div>
<div class="mermaid2" style="width: 100%;">
stateDiagram
state Active {
Idle
@ -148,7 +181,7 @@ stateDiagram
Active --> Active: LOG
</div>
<div class="mermaid2" style="width: 100%;">
graph TB
flowchart TB
accTitle: My flowchart
accDescr: My flowchart Description
subgraph One
@ -165,8 +198,7 @@ stateDiagram
end
end
end
B ->> A: Return
</div>
B ->> A: Return</div>
<div class="mermaid2" style="width: 100%;">
classDiagram
accTitle: My class diagram
@ -185,7 +217,7 @@ class Class10 {
size()
}
</div>
<div class="mermaid2" style="width: 100%;">
<div class="mermaid" style="width: 100%;">
stateDiagram
accTitle: Apa
accDescr: One that can climb better then any man
@ -215,6 +247,21 @@ class Class10 {
+run()
}
</div>
<div class="mermaid2" style="width: 100%;">
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
CAR {
string registrationNumber
string make
string model
}
PERSON ||--o{ NAMED-DRIVER : is
PERSON {
string firstName
string lastName
int age
}
</div>
<script src="./mermaid.js"></script>
<script>
@ -251,6 +298,7 @@ class Class10 {
state: {
nodeSpacing: 50,
rankSpacing: 50,
defaultRenderer: 'dagre-d3',
},
logLevel: 0,
fontSize: 18,

View File

@ -57,22 +57,30 @@ class Diagram {
this.parser.parser.yy = c4Db;
this.db = c4Db;
this.renderer = c4Renderer;
this.renderer.setConf(cnf.c4);
break;
case 'gitGraph':
this.parser = gitGraphParser;
this.parser.parser.yy = gitGraphAst;
this.db = gitGraphAst;
this.renderer = gitGraphRenderer;
this.txt = this.txt + '\n';
break;
case 'flowchart':
flowRenderer.setConf(cnf.flowchart);
cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
flowDb.clear();
flowDb.setGen('gen-1');
this.parser = flowParser;
this.parser.parser.yy = flowDb;
this.db = flowDb;
this.renderer = flowRenderer;
break;
case 'flowchart-v2':
flowRendererV2.setConf(cnf.flowchart);
cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
flowDb.clear();
flowDb.setGen('gen-2');
this.parser = flowParser;
this.parser.parser.yy = flowDb;
this.db = flowDb;
@ -80,39 +88,60 @@ class Diagram {
break;
case 'sequenceDiagram':
case 'sequence':
cnf.sequence.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
if (cnf.sequenceDiagram) {
// backwards compatibility
sequenceRenderer.setConf(Object.assign(cnf.sequence, cnf.sequenceDiagram));
console.error(
'`mermaid config.sequenceDiagram` has been renamed to `config.sequence`. Please update your mermaid config.'
);
}
this.parser = sequenceParser;
this.parser.parser.yy = sequenceDb;
this.db = sequenceDb;
this.db.setWrap(cnf.wrap);
this.renderer = sequenceRenderer;
this.renderer.setConf(cnf.sequence);
this.txt = this.txt + '\n';
break;
case 'gantt':
cnf.gantt.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
this.parser = ganttParser;
this.parser.parser.yy = ganttDb;
this.db = ganttDb;
this.renderer = ganttRenderer;
ganttRenderer.setConf(cnf.gantt);
break;
case 'class':
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
this.parser = classParser;
this.parser.parser.yy = classDb;
this.db = classDb;
this.db.clear();
this.renderer = classRenderer;
break;
case 'classDiagram':
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
this.parser = classParser;
this.parser.parser.yy = classDb;
this.db = classDb;
this.db.clear();
this.renderer = classRendererV2;
break;
case 'state':
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
this.parser = stateParser;
this.parser.parser.yy = stateDb;
this.db = stateDb;
this.db.clear();
this.renderer = stateRenderer;
break;
case 'stateDiagram':
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
this.parser = stateParser;
this.parser.parser.yy = stateDb;
this.db = stateDb;
this.db.clear();
this.renderer = stateRendererV2;
break;
case 'info':
@ -138,9 +167,11 @@ class Diagram {
break;
case 'journey':
log.debug('Journey');
journeyRenderer.setConf(cnf.journey);
this.parser = journeyParser;
this.parser.parser.yy = journeyDb;
this.db = journeyDb;
this.db.clear();
this.renderer = journeyRenderer;
break;
case 'requirement':
@ -160,7 +191,7 @@ class Diagram {
const error = { str, hash };
throw error;
};
this.parser.parse(txt);
this.parser.parse(this.txt);
}
getParser() {
return this.parser;

View File

@ -817,6 +817,9 @@ const config = {
},
class: {
arrowMarkerAbsolute: false,
dividerMargin: 10,
padding: 5,
textHeight: 10,
/**
* | Parameter | Description | Type | Required | Values |

View File

@ -0,0 +1,9 @@
const diagrams = {};
export const registerDiagram = (id, parser, identifier, renderer) => {
diagrams[id] = { parser, identifier, renderer };
};
export const getDiagrams = () => {
return diagrams;
};

View File

@ -25,7 +25,7 @@ parser.yy = c4Db;
let conf = {};
class Bounds {
constructor() {
constructor(diagObj) {
this.name = '';
this.data = {};
this.data.startx = undefined;
@ -41,7 +41,7 @@ class Bounds {
this.nextData.stopy = undefined;
this.nextData.cnt = 0;
setConf(parser.yy.getConfig());
setConf(diagObj.db.getConfig());
}
setData(startx, stopx, starty, stopy) {
@ -96,7 +96,7 @@ class Bounds {
this.updateVal(this.nextData, 'stopy', _stopy, Math.max);
}
init() {
init(diagObj) {
this.name = '';
this.data = {
startx: undefined,
@ -112,7 +112,7 @@ class Bounds {
stopy: undefined,
cnt: 0,
};
setConf(parser.yy.getConfig());
setConf(diagObj.db.getConfig());
}
bumpLastMargin(margin) {
@ -411,13 +411,13 @@ let getIntersectPoints = function (fromNode, endNode) {
return { startPoint: startPoint, endPoint: endPoint };
};
export const drawRels = function (diagram, rels, getC4ShapeObj) {
export const drawRels = function (diagram, rels, getC4ShapeObj, diagObj) {
let i = 0;
for (let rel of rels) {
i = i + 1;
let relTextWrap = rel.wrap && conf.wrap;
let relConf = messageFont(conf);
let diagramType = parser.yy.getC4Type();
let diagramType = diagObj.db.getC4Type();
if (diagramType === 'C4Dynamic') rel.label.text = i + ': ' + rel.label.text;
let textLimitWidth = calculateTextWidth(rel.label.text, relConf);
calcC4ShapeTextWH('label', rel, relTextWrap, relConf, textLimitWidth);
@ -446,9 +446,10 @@ export const drawRels = function (diagram, rels, getC4ShapeObj) {
* @param parentBoundaryAlias
* @param parentBounds
* @param currentBoundarys
* @param diagObj
*/
function drawInsideBoundary(diagram, parentBoundaryAlias, parentBounds, currentBoundarys) {
let currentBounds = new Bounds();
function drawInsideBoundary(diagram, parentBoundaryAlias, parentBounds, currentBoundarys, diagObj) {
let currentBounds = new Bounds(diagObj);
// Calculate the width limit of the boundar. label/type 的长度,
currentBounds.data.widthLimit =
parentBounds.data.widthLimit / Math.min(c4BoundaryInRow, currentBoundarys.length);
@ -527,8 +528,8 @@ function drawInsideBoundary(diagram, parentBoundaryAlias, parentBounds, currentB
currentBounds.setData(_x, _x, _y, _y);
}
currentBounds.name = currentBoundary.alias;
let currentPersonOrSystemArray = parser.yy.getC4ShapeArray(currentBoundary.alias);
let currentPersonOrSystemKeys = parser.yy.getC4ShapeKeys(currentBoundary.alias);
let currentPersonOrSystemArray = diagObj.db.getC4ShapeArray(currentBoundary.alias);
let currentPersonOrSystemKeys = diagObj.db.getC4ShapeKeys(currentBoundary.alias);
if (currentPersonOrSystemKeys.length > 0) {
drawC4ShapeArray(
@ -539,13 +540,19 @@ function drawInsideBoundary(diagram, parentBoundaryAlias, parentBounds, currentB
);
}
parentBoundaryAlias = currentBoundary.alias;
let nextCurrentBoundarys = parser.yy.getBoundarys(parentBoundaryAlias);
let nextCurrentBoundarys = diagObj.db.getBoundarys(parentBoundaryAlias);
if (nextCurrentBoundarys.length > 0) {
// draw boundary inside currentBoundary
// bounds.init();
// parentBoundaryWidthLimit = bounds.data.stopx - bounds.startx;
drawInsideBoundary(diagram, parentBoundaryAlias, currentBounds, nextCurrentBoundarys);
drawInsideBoundary(
diagram,
parentBoundaryAlias,
currentBounds,
nextCurrentBoundarys,
diagObj
);
}
// draw boundary
if (currentBoundary.alias !== 'global') drawBoundary(diagram, currentBoundary, currentBounds);
@ -566,9 +573,12 @@ function drawInsideBoundary(diagram, parentBoundaryAlias, parentBounds, currentB
* Draws a sequenceDiagram in the tag with id: id based on the graph definition in text.
*
* @param {any} text
* @param _text
* @param {any} id
* @param _version
* @param diagObj
*/
export const draw = function (text, id) {
export const draw = function (_text, id, _version, diagObj) {
conf = configApi.getConfig().c4;
const securityLevel = configApi.getConfig().securityLevel;
// Handle root and Document for when rendering in sanbox mode
@ -580,13 +590,10 @@ export const draw = function (text, id) {
securityLevel === 'sandbox'
? select(sandboxElement.nodes()[0].contentDocument.body)
: select('body');
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
let db = parser.yy;
let db = diagObj.db;
parser.yy.clear();
parser.yy.setWrap(conf.wrap);
parser.parse(text + '\n');
diagObj.db.setWrap(conf.wrap);
c4ShapeInRow = db.getC4ShapeInRow();
c4BoundaryInRow = db.getC4BoundaryInRow();
@ -600,7 +607,7 @@ export const draw = function (text, id) {
svgDraw.insertDatabaseIcon(diagram);
svgDraw.insertClockIcon(diagram);
let screenBounds = new Bounds();
let screenBounds = new Bounds(diagObj);
screenBounds.setData(
conf.diagramMarginX,
@ -613,12 +620,12 @@ export const draw = function (text, id) {
globalBoundaryMaxX = conf.diagramMarginX;
globalBoundaryMaxY = conf.diagramMarginY;
const title = parser.yy.getTitle();
const c4type = parser.yy.getC4Type();
let currentBoundarys = parser.yy.getBoundarys('');
const title = diagObj.db.getTitle();
const c4type = diagObj.db.getC4Type();
let currentBoundarys = diagObj.db.getBoundarys('');
// switch (c4type) {
// case 'C4Context':
drawInsideBoundary(diagram, '', screenBounds, currentBoundarys);
drawInsideBoundary(diagram, '', screenBounds, currentBoundarys, diagObj);
// break;
// }
@ -628,7 +635,7 @@ export const draw = function (text, id) {
svgDraw.insertArrowCrossHead(diagram);
svgDraw.insertArrowFilledHead(diagram);
drawRels(diagram, parser.yy.getRels(), parser.yy.getC4Shape);
drawRels(diagram, diagObj.db.getRels(), diagObj.db.getC4Shape, diagObj);
screenBounds.data.stopx = globalBoundaryMaxX;
screenBounds.data.stopy = globalBoundaryMaxY;

View File

@ -1,10 +1,6 @@
import { select } from 'd3';
import dagre from 'dagre';
import graphlib from 'graphlib';
import { log } from '../../logger';
import classDb, { lookUpDomId } from './classDb';
import { parser } from './parser/classDiagram';
import svgDraw from './svgDraw';
import { getConfig } from '../../config';
import { render } from '../../dagre-wrapper/index.js';
// import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js';
@ -13,14 +9,12 @@ import { interpolateToCurve, getStylesFromArray, setupGraphViewbox } from '../..
import common from '../common/common';
import addSVGAccessibilityFields from '../../accessibility';
parser.yy = classDb;
let idCache = {};
const padding = 20;
const sanitizeText = (txt) => common.sanitizeText(txt, getConfig());
const conf = {
let conf = {
dividerMargin: 10,
padding: 5,
textHeight: 10,
@ -144,6 +138,7 @@ export const addClasses = function (classes, g) {
* @param {object} g The graph object
*/
export const addRelations = function (relations, g) {
const conf = getConfig().flowchart;
let cnt = 0;
let defaultStyle;
@ -269,16 +264,18 @@ export const setConf = function (cnf) {
*
* @param {string} text
* @param {string} id
* @param _version
* @param diagObj
*/
export const draw = function (text, id) {
export const draw = function (text, id, _version, diagObj) {
log.info('Drawing class - ', id);
classDb.clear();
// const parser = classDb.parser;
// diagObj.db.clear();
// const parser = diagObj.db.parser;
// parser.yy = classDb;
// Parse the graph definition
// try {
parser.parse(text);
// parser.parse(text);
// } catch (err) {
// log.debug('Parsing failed');
// }
@ -298,7 +295,7 @@ export const draw = function (text, id) {
compound: true,
})
.setGraph({
rankdir: classDb.getDirection(),
rankdir: diagObj.db.getDirection(),
nodesep: nodeSpacing,
ranksep: rankSpacing,
marginx: 8,
@ -318,8 +315,8 @@ export const draw = function (text, id) {
// }
// Fetch the vertices/nodes and edges/links from the parsed graph definition
const classes = classDb.getClasses();
const relations = classDb.getRelations();
const classes = diagObj.db.getClasses();
const relations = diagObj.db.getRelations();
log.info(relations);
addClasses(classes, g, id);
@ -366,7 +363,7 @@ export const draw = function (text, id) {
}
}
addSVGAccessibilityFields(parser.yy, svg, id);
addSVGAccessibilityFields(diagObj.db, svg, id);
// If node has a link, wrap it in an anchor SVG object.
// const keys = Object.keys(classes);
// keys.forEach(function(key) {

View File

@ -2,19 +2,15 @@ import { select } from 'd3';
import dagre from 'dagre';
import graphlib from 'graphlib';
import { log } from '../../logger';
import classDb, { lookUpDomId } from './classDb';
import { parser } from './parser/classDiagram';
import svgDraw from './svgDraw';
import { configureSvgSize } from '../../utils';
import { getConfig } from '../../config';
import addSVGAccessibilityFields from '../../accessibility';
parser.yy = classDb;
let idCache = {};
const padding = 20;
const conf = {
const confa = {
dividerMargin: 10,
padding: 5,
textHeight: 10,
@ -141,29 +137,20 @@ const insertMarkers = function (elem) {
.attr('d', 'M 18,7 L9,13 L14,7 L9,1 Z');
};
/**
* Merges the value of `conf` with the passed `cnf`
*
* @param {object} cnf Config to merge
*/
export const setConf = function (cnf) {
const keys = Object.keys(cnf);
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 {string} text
* @param {string} id
* @param version
* @param _version
* @param diagObj
*/
export const draw = function (text, id) {
export const draw = function (text, id, _version, diagObj) {
const conf = getConfig().class;
idCache = {};
parser.yy.clear();
parser.parse(text);
// diagObj.db.clear();
// diagObj.parser.parse(text);
log.info('Rendering diagram ' + text);
@ -198,12 +185,12 @@ export const draw = function (text, id) {
return {};
});
const classes = classDb.getClasses();
const classes = diagObj.db.getClasses();
const keys = Object.keys(classes);
for (let i = 0; i < keys.length; i++) {
const classDef = classes[keys[i]];
const node = svgDraw.drawClass(diagram, classDef, conf);
const node = svgDraw.drawClass(diagram, classDef, conf, diagObj);
idCache[node.id] = node;
// Add nodes to the graph. The first argument is the node id. The second is
@ -214,7 +201,7 @@ export const draw = function (text, id) {
log.info('Org height: ' + node.height);
}
const relations = classDb.getRelations();
const relations = diagObj.db.getRelations();
relations.forEach(function (relation) {
log.info(
'tjoho' + getGraphId(relation.id1) + getGraphId(relation.id2) + JSON.stringify(relation)
@ -234,7 +221,7 @@ export const draw = function (text, id) {
if (typeof v !== 'undefined' && typeof g.node(v) !== 'undefined') {
log.debug('Node ' + v + ': ' + JSON.stringify(g.node(v)));
root
.select('#' + lookUpDomId(v))
.select('#' + diagObj.db.lookUpDomId(v))
.attr(
'transform',
'translate(' +
@ -249,7 +236,7 @@ export const draw = function (text, id) {
g.edges().forEach(function (e) {
if (typeof e !== 'undefined' && typeof g.edge(e) !== 'undefined') {
log.debug('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(g.edge(e)));
svgDraw.drawEdge(diagram, g.edge(e), g.edge(e).relation, conf);
svgDraw.drawEdge(diagram, g.edge(e), g.edge(e).relation, conf, diagObj);
}
});
@ -263,10 +250,9 @@ export const draw = function (text, id) {
const vBox = `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`;
log.debug(`viewBox ${vBox}`);
diagram.attr('viewBox', vBox);
addSVGAccessibilityFields(parser.yy, diagram, id);
addSVGAccessibilityFields(diagObj.db, diagram, id);
};
export default {
setConf,
draw,
};

View File

@ -1,19 +1,18 @@
import { line, curveBasis } from 'd3';
import { lookUpDomId, relationType } from './classDb';
import utils from '../../utils';
import { log } from '../../logger';
let edgeCount = 0;
export const drawEdge = function (elem, path, relation, conf) {
export const drawEdge = function (elem, path, relation, conf, diagObj) {
const getRelationType = function (type) {
switch (type) {
case relationType.AGGREGATION:
case diagObj.db.relationType.AGGREGATION:
return 'aggregation';
case relationType.EXTENSION:
case diagObj.db.EXTENSION:
return 'extension';
case relationType.COMPOSITION:
case diagObj.db.COMPOSITION:
return 'composition';
case relationType.DEPENDENCY:
case diagObj.db.DEPENDENCY:
return 'dependency';
}
};
@ -150,10 +149,11 @@ export const drawEdge = function (elem, path, relation, conf) {
* @param {SVGSVGElement} elem The element to draw it into
* @param classDef
* @param conf
* @param diagObj
* @todo Add more information in the JSDOC here
*/
export const drawClass = function (elem, classDef, conf) {
log.info('Rendering class ' + classDef);
export const drawClass = function (elem, classDef, conf, diagObj) {
log.debug('Rendering class ', classDef, conf);
const id = classDef.id;
const classInfo = {
@ -164,7 +164,7 @@ export const drawClass = function (elem, classDef, conf) {
};
// add class group
const g = elem.append('g').attr('id', lookUpDomId(id)).attr('class', 'classGroup');
const g = elem.append('g').attr('id', diagObj.db.lookUpDomId(id)).attr('class', 'classGroup');
// add title
let title;

View File

@ -1,7 +1,7 @@
import graphlib from 'graphlib';
import { line, curveBasis, select } from 'd3';
import erDb from './erDb';
import erParser from './parser/erDiagram';
// import erDb from './erDb';
// import erParser from './parser/erDiagram';
import dagre from 'dagre';
import { getConfig } from '../../config';
import { log } from '../../logger';
@ -9,7 +9,7 @@ import erMarkers from './erMarkers';
import { configureSvgSize } from '../../utils';
import addSVGAccessibilityFields from '../../accessibility';
const conf = {};
let conf = {};
/**
* Allows the top-level API module to inject config specific to this renderer, storing it in the
@ -409,8 +409,9 @@ let relCnt = 0;
* @param g The graph containing the edge information
* @param insert The insertion point in the svg DOM (because relationships have markers that need to
* sit 'behind' opaque entity boxes)
* @param diagObj
*/
const drawRelationshipFromLayout = function (svg, rel, g, insert) {
const drawRelationshipFromLayout = function (svg, rel, g, insert, diagObj) {
relCnt++;
// Find the edge relating to this relationship
@ -435,7 +436,7 @@ const drawRelationshipFromLayout = function (svg, rel, g, insert) {
.attr('fill', 'none');
// ...and with dashes if necessary
if (rel.relSpec.relType === erDb.Identification.NON_IDENTIFYING) {
if (rel.relSpec.relType === diagObj.db.Identification.NON_IDENTIFYING) {
svgPath.attr('stroke-dasharray', '8,8');
}
@ -457,40 +458,40 @@ const drawRelationshipFromLayout = function (svg, rel, g, insert) {
// Note that the 'A' entity's marker is at the end of the relationship and the 'B' entity's marker is at the start
switch (rel.relSpec.cardA) {
case erDb.Cardinality.ZERO_OR_ONE:
case diagObj.db.Cardinality.ZERO_OR_ONE:
svgPath.attr('marker-end', 'url(' + url + '#' + erMarkers.ERMarkers.ZERO_OR_ONE_END + ')');
break;
case erDb.Cardinality.ZERO_OR_MORE:
case diagObj.db.Cardinality.ZERO_OR_MORE:
svgPath.attr('marker-end', 'url(' + url + '#' + erMarkers.ERMarkers.ZERO_OR_MORE_END + ')');
break;
case erDb.Cardinality.ONE_OR_MORE:
case diagObj.db.Cardinality.ONE_OR_MORE:
svgPath.attr('marker-end', 'url(' + url + '#' + erMarkers.ERMarkers.ONE_OR_MORE_END + ')');
break;
case erDb.Cardinality.ONLY_ONE:
case diagObj.db.Cardinality.ONLY_ONE:
svgPath.attr('marker-end', 'url(' + url + '#' + erMarkers.ERMarkers.ONLY_ONE_END + ')');
break;
}
switch (rel.relSpec.cardB) {
case erDb.Cardinality.ZERO_OR_ONE:
case diagObj.db.Cardinality.ZERO_OR_ONE:
svgPath.attr(
'marker-start',
'url(' + url + '#' + erMarkers.ERMarkers.ZERO_OR_ONE_START + ')'
);
break;
case erDb.Cardinality.ZERO_OR_MORE:
case diagObj.db.Cardinality.ZERO_OR_MORE:
svgPath.attr(
'marker-start',
'url(' + url + '#' + erMarkers.ERMarkers.ZERO_OR_MORE_START + ')'
);
break;
case erDb.Cardinality.ONE_OR_MORE:
case diagObj.db.Cardinality.ONE_OR_MORE:
svgPath.attr(
'marker-start',
'url(' + url + '#' + erMarkers.ERMarkers.ONE_OR_MORE_START + ')'
);
break;
case erDb.Cardinality.ONLY_ONE:
case diagObj.db.Cardinality.ONLY_ONE:
svgPath.attr('marker-start', 'url(' + url + '#' + erMarkers.ERMarkers.ONLY_ONE_START + ')');
break;
}
@ -540,12 +541,14 @@ const drawRelationshipFromLayout = function (svg, rel, g, insert) {
*
* @param text The text of the diagram
* @param id The unique id of the DOM node that contains the diagram
* @param _version
* @param diag
* @param diagObj
*/
export const draw = function (text, id) {
export const draw = function (text, id, _version, diagObj) {
conf = getConfig().er;
log.info('Drawing ER diagram');
erDb.clear();
const parser = erParser.parser;
parser.yy = erDb;
// diag.db.clear();
const securityLevel = getConfig().securityLevel;
// Handle root and Document for when rendering in sanbox mode
let sandboxElement;
@ -556,14 +559,14 @@ export const draw = function (text, id) {
securityLevel === 'sandbox'
? select(sandboxElement.nodes()[0].contentDocument.body)
: select('body');
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
// const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
// Parse the text to populate erDb
try {
parser.parse(text);
} catch (err) {
log.debug('Parsing failed');
}
// try {
// parser.parse(text);
// } catch (err) {
// log.debug('Parsing failed');
// }
// Get a reference to the svg node that contains the text
const svg = root.select(`[id='${id}']`);
@ -612,12 +615,12 @@ export const draw = function (text, id) {
// Draw the entities (at 0,0), returning the first svg node that got
// inserted - this represents the insertion point for relationship paths
const firstEntity = drawEntities(svg, erDb.getEntities(), g);
const firstEntity = drawEntities(svg, diagObj.db.getEntities(), g);
// TODO: externalise the addition of entities to the graph - it's a bit 'buried' in the above
// Add all the relationships to the graph
const relationships = addRelationships(erDb.getRelationships(), g);
const relationships = addRelationships(diagObj.db.getRelationships(), g);
dagre.layout(g); // Node and edge positions will be updated
@ -626,7 +629,7 @@ export const draw = function (text, id) {
// Draw the relationships
relationships.forEach(function (rel) {
drawRelationshipFromLayout(svg, rel, g, firstEntity);
drawRelationshipFromLayout(svg, rel, g, firstEntity, diagObj);
});
const padding = conf.diagramPadding;
@ -639,7 +642,7 @@ export const draw = function (text, id) {
svg.attr('viewBox', `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`);
addSVGAccessibilityFields(parser.yy, svg, id);
addSVGAccessibilityFields(diagObj.db, svg, id);
}; // draw
export default {

View File

@ -489,7 +489,6 @@ export const addSubGraph = function (_id, list, _title) {
const { nodeList: nl, dir } = uniq(nodeList.concat.apply(nodeList, list));
nodeList = nl;
if (version === 'gen-1') {
log.warn('LOOKING UP');
for (let i = 0; i < nodeList.length; i++) {
nodeList[i] = lookUpDomId(nodeList[i]);
}

View File

@ -28,8 +28,9 @@ export const setConf = function (cnf) {
* @param svgId
* @param root
* @param doc
* @param diagObj
*/
export const addVertices = function (vert, g, svgId, root, doc) {
export const addVertices = function (vert, g, svgId, root, doc, diagObj) {
const svg = root.select(`[id="${svgId}"]`);
const keys = Object.keys(vert);
@ -152,8 +153,8 @@ export const addVertices = function (vert, g, svgId, root, doc) {
id: vertex.id,
link: vertex.link,
linkTarget: vertex.linkTarget,
tooltip: flowDb.getTooltip(vertex.id) || '',
domId: flowDb.lookUpDomId(vertex.id),
tooltip: diagObj.db.getTooltip(vertex.id) || '',
domId: diagObj.db.lookUpDomId(vertex.id),
haveCallback: vertex.haveCallback,
width: vertex.type === 'group' ? 500 : undefined,
dir: vertex.dir,
@ -171,7 +172,7 @@ export const addVertices = function (vert, g, svgId, root, doc) {
class: classStr,
style: styles.style,
id: vertex.id,
domId: flowDb.lookUpDomId(vertex.id),
domId: diagObj.db.lookUpDomId(vertex.id),
width: vertex.type === 'group' ? 500 : undefined,
type: vertex.type,
dir: vertex.dir,
@ -186,8 +187,9 @@ export const addVertices = function (vert, g, svgId, root, doc) {
*
* @param {object} edges The edges to add to the graph
* @param {object} g The graph object
* @param diagObj
*/
export const addEdges = function (edges, g) {
export const addEdges = function (edges, g, diagObj) {
log.info('abc78 edges = ', edges);
let cnt = 0;
let linkIdCnt = {};
@ -304,11 +306,7 @@ export const addEdges = function (edges, g) {
edgeData.arrowheadStyle = 'fill: #333';
edgeData.labelpos = 'c';
}
// if (evaluate(getConfig().flowchart.htmlLabels) && false) {
// // eslint-disable-line
// edgeData.labelType = 'html';
// edgeData.label = `<span id="L-${linkId}" class="edgeLabel L-${linkNameStart}' L-${linkNameEnd}">${edge.text}</span>`;
// } else {
edgeData.labelType = 'text';
edgeData.label = edge.text.replace(common.lineBreakRegex, '\n');
@ -317,7 +315,6 @@ export const addEdges = function (edges, g) {
}
edgeData.labelStyle = edgeData.labelStyle.replace('color:', 'fill:');
// }
edgeData.id = linkId;
edgeData.classes = 'flowchart-link ' + linkNameStart + ' ' + linkNameEnd;
@ -331,22 +328,19 @@ export const addEdges = function (edges, g) {
* Returns the all the styles from classDef statements in the graph definition.
*
* @param text
* @param diagObj
* @returns {object} ClassDef styles
*/
export const getClasses = function (text) {
export const getClasses = function (text, diagObj) {
log.info('Extracting classes');
flowDb.clear();
const parser = flow.parser;
parser.yy = flowDb;
diagObj.db.clear();
try {
// Parse the graph definition
parser.parse(text);
diagObj.parse(text);
return diagObj.db.getClasses();
} catch (e) {
return;
}
return flowDb.getClasses();
};
/**
@ -356,22 +350,15 @@ export const getClasses = function (text) {
* @param id
*/
export const draw = function (text, id) {
export const draw = function (text, id, _version, diagObj) {
log.info('Drawing flowchart');
flowDb.clear();
diagObj.db.clear();
flowDb.setGen('gen-2');
const parser = flow.parser;
parser.yy = flowDb;
// Parse the graph definition
// try {
parser.parse(text);
// } catch (err) {
// log.debug('Parsing failed');
// }
diagObj.parser.parse(text);
// Fetch the default direction, use TD if none was found
let dir = flowDb.getDirection();
let dir = diagObj.db.getDirection();
if (typeof dir === 'undefined') {
dir = 'TD';
}
@ -409,18 +396,18 @@ export const draw = function (text, id) {
});
let subG;
const subGraphs = flowDb.getSubGraphs();
const subGraphs = diagObj.db.getSubGraphs();
log.info('Subgraphs - ', subGraphs);
for (let i = subGraphs.length - 1; i >= 0; i--) {
subG = subGraphs[i];
log.info('Subgraph - ', subG);
flowDb.addVertex(subG.id, subG.title, 'group', undefined, subG.classes, subG.dir);
diagObj.db.addVertex(subG.id, subG.title, 'group', undefined, subG.classes, subG.dir);
}
// Fetch the vertices/nodes and edges/links from the parsed graph definition
const vert = flowDb.getVertices();
const vert = diagObj.db.getVertices();
const edges = flowDb.getEdges();
const edges = diagObj.db.getEdges();
log.info(edges);
let i = 0;
@ -435,8 +422,8 @@ export const draw = function (text, id) {
g.setParent(subG.nodes[j], subG.id);
}
}
addVertices(vert, g, id, root, doc);
addEdges(edges, g);
addVertices(vert, g, id, root, doc, diagObj);
addEdges(edges, g, diagObj);
// Add custom shapes
// flowChartShapes.addToRenderV2(addShape);
@ -445,7 +432,7 @@ export const draw = function (text, id) {
const svg = root.select(`[id="${id}"]`);
// Adds title and description to the flow chart
addSVGAccessibilityFields(parser.yy, svg, id);
addSVGAccessibilityFields(diagObj.db, svg, id);
// Run the renderer. This is what draws the final graph.
const element = root.select('#' + id + ' g');
@ -454,7 +441,7 @@ export const draw = function (text, id) {
setupGraphViewbox(g, svg, conf.diagramPadding, conf.useMaxWidth);
// Index nodes
flowDb.indexNodes('subGraph' + i);
diagObj.db.indexNodes('subGraph' + i);
// Add label rects for non html labels
if (!conf.htmlLabels) {

View File

@ -1,10 +1,6 @@
import graphlib from 'graphlib';
import { select, curveLinear, selectAll } from 'd3';
import flowDb from './flowDb';
import flow from './parser/flow';
import { getConfig } from '../../config';
import dagreD3 from 'dagre-d3';
import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js';
import { log } from '../../logger';
@ -30,8 +26,9 @@ export const setConf = function (cnf) {
* @param root
* @param doc
* @param _doc
* @param diagObj
*/
export const addVertices = function (vert, g, svgId, root, _doc) {
export const addVertices = function (vert, g, svgId, root, _doc, diagObj) {
const securityLevel = getConfig().securityLevel;
const svg = !root ? select(`[id="${svgId}"]`) : root.select(`[id="${svgId}"]`);
@ -144,7 +141,7 @@ export const addVertices = function (vert, g, svgId, root, _doc) {
}
// Add the node
log.warn('Adding node', vertex.id, vertex.domId);
g.setNode(flowDb.lookUpDomId(vertex.id), {
g.setNode(diagObj.db.lookUpDomId(vertex.id), {
labelType: 'svg',
labelStyle: styles.labelStyle,
shape: _shape,
@ -153,7 +150,7 @@ export const addVertices = function (vert, g, svgId, root, _doc) {
ry: radious,
class: classStr,
style: styles.style,
id: flowDb.lookUpDomId(vertex.id),
id: diagObj.db.lookUpDomId(vertex.id),
});
});
};
@ -163,8 +160,9 @@ export const addVertices = function (vert, g, svgId, root, _doc) {
*
* @param {object} edges The edges to add to the graph
* @param {object} g The graph object
* @param diagObj
*/
export const addEdges = function (edges, g) {
export const addEdges = function (edges, g, diagObj) {
let cnt = 0;
let defaultStyle;
@ -264,7 +262,7 @@ export const addEdges = function (edges, g) {
edgeData.minlen = edge.length || 1;
// Add the edge to the graph
g.setEdge(flowDb.lookUpDomId(edge.start), flowDb.lookUpDomId(edge.end), edgeData, cnt);
g.setEdge(diagObj.db.lookUpDomId(edge.start), diagObj.db.lookUpDomId(edge.end), edgeData, cnt);
});
};
@ -272,18 +270,16 @@ export const addEdges = function (edges, g) {
* Returns the all the styles from classDef statements in the graph definition.
*
* @param text
* @param diagObj
* @returns {object} ClassDef styles
*/
export const getClasses = function (text) {
export const getClasses = function (text, diagObj) {
log.info('Extracting classes');
flowDb.clear();
diagObj.db.clear();
try {
const parser = flow.parser;
parser.yy = flowDb;
// Parse the graph definition
parser.parse(text);
return flowDb.getClasses();
diagObj.parse(text);
return diagObj.db.getClasses();
} catch (e) {
return;
}
@ -294,14 +290,12 @@ export const getClasses = function (text) {
*
* @param text
* @param id
* @param _version
* @param diagObj
*/
export const draw = function (text, id) {
export const draw = function (text, id, _version, diagObj) {
log.info('Drawing flowchart');
flowDb.clear();
flowDb.setGen('gen-1');
const parser = flow.parser;
parser.yy = flowDb;
diagObj.db.clear();
const securityLevel = getConfig().securityLevel;
let sandboxElement;
if (securityLevel === 'sandbox') {
@ -314,14 +308,14 @@ export const draw = function (text, id) {
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
// Parse the graph definition
// try {
parser.parse(text);
// } catch (err) {
// log.debug('Parsing failed');
// }
try {
diagObj.parser.parse(text);
} catch (err) {
log.debug('Parsing failed');
}
// Fetch the default direction, use TD if none was found
let dir = flowDb.getDirection();
let dir = diagObj.db.getDirection();
if (typeof dir === 'undefined') {
dir = 'TD';
}
@ -347,17 +341,17 @@ export const draw = function (text, id) {
});
let subG;
const subGraphs = flowDb.getSubGraphs();
const subGraphs = diagObj.db.getSubGraphs();
for (let i = subGraphs.length - 1; i >= 0; i--) {
subG = subGraphs[i];
flowDb.addVertex(subG.id, subG.title, 'group', undefined, subG.classes);
diagObj.db.addVertex(subG.id, subG.title, 'group', undefined, subG.classes);
}
// Fetch the vertices/nodes and edges/links from the parsed graph definition
const vert = flowDb.getVertices();
const vert = diagObj.db.getVertices();
log.warn('Get vertices', vert);
const edges = flowDb.getEdges();
const edges = diagObj.db.getEdges();
let i = 0;
for (i = subGraphs.length - 1; i >= 0; i--) {
@ -369,14 +363,14 @@ export const draw = function (text, id) {
log.warn(
'Setting subgraph',
subG.nodes[j],
flowDb.lookUpDomId(subG.nodes[j]),
flowDb.lookUpDomId(subG.id)
diagObj.db.lookUpDomId(subG.nodes[j]),
diagObj.db.lookUpDomId(subG.id)
);
g.setParent(flowDb.lookUpDomId(subG.nodes[j]), flowDb.lookUpDomId(subG.id));
g.setParent(diagObj.db.lookUpDomId(subG.nodes[j]), diagObj.db.lookUpDomId(subG.id));
}
}
addVertices(vert, g, id, root, doc);
addEdges(edges, g);
addVertices(vert, g, id, root, doc, diagObj);
addEdges(edges, g, diagObj);
// Create the renderer
const Render = dagreD3.render;
@ -427,28 +421,28 @@ export const draw = function (text, id) {
const svg = root.select(`[id="${id}"]`);
// Adds title and description to the flow chart
addSVGAccessibilityFields(parser.yy, svg, id);
addSVGAccessibilityFields(diagObj.db, svg, id);
// Run the renderer. This is what draws the final graph.
const element = root.select('#' + id + ' g');
render(element, g);
element.selectAll('g.node').attr('title', function () {
return flowDb.getTooltip(this.id);
return diagObj.db.getTooltip(this.id);
});
// Index nodes
flowDb.indexNodes('subGraph' + i);
diagObj.db.indexNodes('subGraph' + i);
// reposition labels
for (i = 0; i < subGraphs.length; i++) {
subG = subGraphs[i];
if (subG.title !== 'undefined') {
const clusterRects = doc.querySelectorAll(
'#' + id + ' [id="' + flowDb.lookUpDomId(subG.id) + '"] rect'
'#' + id + ' [id="' + diagObj.db.lookUpDomId(subG.id) + '"] rect'
);
const clusterEl = doc.querySelectorAll(
'#' + id + ' [id="' + flowDb.lookUpDomId(subG.id) + '"]'
'#' + id + ' [id="' + diagObj.db.lookUpDomId(subG.id) + '"]'
);
const xPos = clusterRects[0].x.baseVal.value;
@ -492,7 +486,7 @@ export const draw = function (text, id) {
const vertex = vert[key];
if (vertex.link) {
const node = root.select('#' + id + ' [id="' + flowDb.lookUpDomId(key) + '"]');
const node = root.select('#' + id + ' [id="' + diagObj.db.lookUpDomId(key) + '"]');
if (node) {
const link = doc.createElementNS('http://www.w3.org/2000/svg', 'a');
link.setAttributeNS('http://www.w3.org/2000/svg', 'class', vertex.classes.join(' '));

View File

@ -1,5 +1,6 @@
import { addVertices, addEdges } from './flowRenderer';
import { setConfig } from '../../config';
import Diagram from '../../Diagram';
setConfig({
flowchart: {
@ -28,6 +29,13 @@ describe('the flowchart renderer', function () {
['group', 'rect'],
].forEach(function ([type, expectedShape, expectedRadios = 0]) {
it(`should add the correct shaped node to the graph for vertex type ${type}`, function () {
const fakeDiag = {
db: {
lookUpDomId: () => {
return 'my-node-id';
},
},
};
const addedNodes = [];
const mockG = {
setNode: function (id, object) {
@ -45,7 +53,10 @@ describe('the flowchart renderer', function () {
},
},
mockG,
'svg-id'
'svg-id',
undefined,
undefined,
fakeDiag
);
expect(addedNodes).toHaveLength(1);
expect(addedNodes[0][0]).toEqual('my-node-id');
@ -62,6 +73,13 @@ describe('the flowchart renderer', function () {
) {
it('should handle multiline texts with different line breaks', function () {
const addedNodes = [];
const fakeDiag = {
db: {
lookUpDomId: () => {
return 'my-node-id';
},
},
};
const mockG = {
setNode: function (id, object) {
addedNodes.push([id, object]);
@ -78,7 +96,10 @@ describe('the flowchart renderer', function () {
},
},
mockG,
'svg-id'
'svg-id',
false,
document,
fakeDiag
);
expect(addedNodes).toHaveLength(1);
expect(addedNodes[0][0]).toEqual('my-node-id');
@ -103,6 +124,13 @@ describe('the flowchart renderer', function () {
].forEach(function ([style, expectedStyle, expectedLabelStyle]) {
it(`should add the styles to style and/or labelStyle for style ${style}`, function () {
const addedNodes = [];
const fakeDiag = {
db: {
lookUpDomId: () => {
return 'my-node-id';
},
},
};
const mockG = {
setNode: function (id, object) {
addedNodes.push([id, object]);
@ -119,7 +147,10 @@ describe('the flowchart renderer', function () {
},
},
mockG,
'svg-id'
'svg-id',
undefined,
undefined,
fakeDiag
);
expect(addedNodes).toHaveLength(1);
expect(addedNodes[0][0]).toEqual('my-node-id');
@ -137,11 +168,18 @@ describe('the flowchart renderer', function () {
addedNodes.push([id, object]);
},
};
const fakeDiag = {
db: {
lookUpDomId: () => {
return 'my-node-id';
},
},
};
addVertices(
{
v1: {
type: 'rect',
id: 'defaultNode',
id: 'my-node-id',
classes: [],
styles: [],
text: 'my vertex text',
@ -155,12 +193,15 @@ describe('the flowchart renderer', function () {
},
},
mockG,
'svg-id'
'svg-id',
undefined,
undefined,
fakeDiag
);
expect(addedNodes).toHaveLength(2);
expect(addedNodes[0][0]).toEqual('defaultNode');
expect(addedNodes[0][0]).toEqual('my-node-id');
expect(addedNodes[0][1]).toHaveProperty('class', 'default');
expect(addedNodes[1][0]).toEqual('myNode');
expect(addedNodes[1][0]).toEqual('my-node-id');
expect(addedNodes[1][1]).toHaveProperty('class', 'myClass');
});
});
@ -168,6 +209,13 @@ describe('the flowchart renderer', function () {
describe('when adding edges to a graph', function () {
it('should handle multiline texts and set centered label position', function () {
const addedEdges = [];
const fakeDiag = {
db: {
lookUpDomId: () => {
return 'my-node-id';
},
},
};
const mockG = {
setEdge: function (s, e, data, c) {
addedEdges.push(data);
@ -185,7 +233,7 @@ describe('the flowchart renderer', function () {
{ style: ['stroke:DarkGray', 'stroke-width:2px'], text: 'Multi<br\t/>Line' },
],
mockG,
'svg-id'
fakeDiag
);
addedEdges.forEach(function (edge) {
@ -206,12 +254,19 @@ describe('the flowchart renderer', function () {
].forEach(function ([style, expectedStyle, expectedLabelStyle]) {
it(`should add the styles to style and/or labelStyle for style ${style}`, function () {
const addedEdges = [];
const fakeDiag = {
db: {
lookUpDomId: () => {
return 'my-node-id';
},
},
};
const mockG = {
setEdge: function (s, e, data, c) {
addedEdges.push(data);
},
};
addEdges([{ style: style, text: 'styling' }], mockG, 'svg-id');
addEdges([{ style: style, text: 'styling' }], mockG, fakeDiag);
expect(addedEdges).toHaveLength(1);
expect(addedEdges[0]).toHaveProperty('style', expectedStyle);

View File

@ -11,23 +11,20 @@ import {
axisTop,
timeFormat,
} from 'd3';
import { parser } from './parser/gantt';
import common from '../common/common';
import ganttDb from './ganttDb';
import { getConfig } from '../../config';
import { configureSvgSize } from '../../utils';
import addSVGAccessibilityFields from '../../accessibility';
parser.yy = ganttDb;
export const setConf = function () {
log.debug('Something is calling, setConf, remove the call');
};
let w;
export const draw = function (text, id) {
export const draw = function (text, id, version, diagObj) {
const conf = getConfig().gantt;
parser.yy.clear();
parser.parse(text);
// diagObj.db.clear();
// parser.parse(text);
const securityLevel = getConfig().securityLevel;
// Handle root and Document for when rendering in sanbox mode
@ -52,7 +49,7 @@ export const draw = function (text, id) {
w = conf.useWidth;
}
const taskArray = parser.yy.getTasks();
const taskArray = diagObj.db.getTasks();
// Set height based on number of tasks
const h = taskArray.length * (conf.barHeight + conf.barGap) + 2 * conf.topPadding;
@ -109,12 +106,12 @@ export const draw = function (text, id) {
svg
.append('text')
.text(parser.yy.getDiagramTitle())
.text(diagObj.db.getDiagramTitle())
.attr('x', w / 2)
.attr('y', conf.titleTopMargin)
.attr('class', 'titleText');
addSVGAccessibilityFields(parser.yy, svg, id);
addSVGAccessibilityFields(diagObj.db, svg, id);
/**
* @param tasks
@ -139,8 +136,8 @@ export const draw = function (text, id) {
pageWidth,
pageHeight,
tasks,
parser.yy.getExcludes(),
parser.yy.getIncludes()
diagObj.db.getExcludes(),
diagObj.db.getIncludes()
);
makeGrid(leftPadding, topPadding, pageWidth, pageHeight);
drawRects(tasks, gap, topPadding, leftPadding, barHeight, colorScale, pageWidth, pageHeight);
@ -187,7 +184,7 @@ export const draw = function (text, id) {
// Draw the rects representing the tasks
const rectangles = svg.append('g').selectAll('rect').data(theArray).enter();
const links = ganttDb.getLinks();
const links = diagObj.db.getLinks();
// Render the tasks with links
// Render the other tasks
@ -430,14 +427,14 @@ export const draw = function (text, id) {
0
);
const maxTime = tasks.reduce((max, { endTime }) => (max ? Math.max(max, endTime) : endTime), 0);
const dateFormat = parser.yy.getDateFormat();
const dateFormat = diagObj.db.getDateFormat();
if (!minTime || !maxTime) return;
const excludeRanges = [];
let range = null;
let d = moment(minTime);
while (d.valueOf() <= maxTime) {
if (parser.yy.isInvalidDate(d, dateFormat, excludes, includes)) {
if (diagObj.db.isInvalidDate(d, dateFormat, excludes, includes)) {
if (!range) {
range = {
start: d.clone(),
@ -495,7 +492,7 @@ export const draw = function (text, id) {
function makeGrid(theSidePad, theTopPad, w, h) {
let bottomXAxis = axisBottom(timeScale)
.tickSize(-h + theTopPad + conf.gridLineStartPadding)
.tickFormat(timeFormat(parser.yy.getAxisFormat() || conf.axisFormat || '%Y-%m-%d'));
.tickFormat(timeFormat(diagObj.db.getAxisFormat() || conf.axisFormat || '%Y-%m-%d'));
svg
.append('g')
@ -509,10 +506,10 @@ export const draw = function (text, id) {
.attr('font-size', 10)
.attr('dy', '1em');
if (ganttDb.topAxisEnabled() || conf.topAxis) {
if (diagObj.db.topAxisEnabled() || conf.topAxis) {
let topXAxis = axisTop(timeScale)
.tickSize(-h + theTopPad + conf.gridLineStartPadding)
.tickFormat(timeFormat(parser.yy.getAxisFormat() || conf.axisFormat || '%Y-%m-%d'));
.tickFormat(timeFormat(diagObj.db.getAxisFormat() || conf.axisFormat || '%Y-%m-%d'));
svg
.append('g')
@ -592,7 +589,7 @@ export const draw = function (text, id) {
* @param h
*/
function drawToday(theSidePad, theTopPad, w, h) {
const todayMarker = ganttDb.getTodayMarker();
const todayMarker = diagObj.db.getTodayMarker();
if (todayMarker === 'off') {
return;
}

View File

@ -1,7 +1,5 @@
import { curveBasis, line, select } from 'd3';
import { interpolateToCurve, getStylesFromArray, configureSvgSize } from '../../utils';
import db from './gitGraphAst';
import gitGraphParser from './parser/gitGraph';
import { select } from 'd3';
import { configureSvgSize } from '../../utils';
import { log } from '../../logger';
import { getConfig } from '../../config';
import addSVGAccessibilityFields from '../../accessibility';
@ -515,23 +513,17 @@ const drawBranches = (svg, branches) => {
* @param txt
* @param id
* @param ver
* @param diagObj
*/
export const draw = function (txt, id, ver) {
export const draw = function (txt, id, ver, diagObj) {
clear();
const conf = getConfig();
const gitGraphConfig = getConfig().gitGraph;
// try {
const parser = gitGraphParser.parser;
parser.yy = db;
parser.yy.clear();
log.debug('in gitgraph renderer', txt + '\n', 'id:', id, ver);
// // Parse the graph definition
parser.parse(txt + '\n');
const direction = db.getDirection();
allCommitsDict = db.getCommits();
const branches = db.getBranchesAsObjArray();
allCommitsDict = diagObj.db.getCommits();
const branches = diagObj.db.getBranchesAsObjArray();
// Position branches vertically
let pos = 0;
@ -543,7 +535,7 @@ export const draw = function (txt, id, ver) {
const diagram = select(`[id="${id}"]`);
// Adds title and description to the flow chart
addSVGAccessibilityFields(parser.yy, diagram, id);
addSVGAccessibilityFields(diagObj.db, diagram, id);
drawCommits(diagram, allCommitsDict, false);
if (gitGraphConfig.showBranches) {

View File

@ -1,30 +1,20 @@
/** Created by knut on 14-12-11. */
import { select } from 'd3';
import db from './infoDb';
import infoParser from './parser/info';
import { log } from '../../logger';
import { getConfig } from '../../config';
const conf = {};
export const setConf = function (cnf) {
const keys = Object.keys(cnf);
keys.forEach(function (key) {
conf[key] = cnf[key];
});
};
/**
* Draws a an info picture in the tag with id: id based on the graph definition in text.
*
* @param {any} text
* @param {any} id
* @param {any} version
* @param diagObj
*/
export const draw = (text, id, version) => {
export const draw = (text, id, version, diagObj) => {
try {
const parser = infoParser.parser;
parser.yy = db;
// const parser = infoParser.parser;
// parser.yy = db;
log.debug('Renering info diagram\n' + text);
const securityLevel = getConfig().securityLevel;
@ -40,8 +30,8 @@ export const draw = (text, id, version) => {
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
// Parse the graph definition
parser.parse(text);
log.debug('Parsed info diagram');
// parser.parse(text);
// log.debug('Parsed info diagram');
// Fetch the default direction, use TD if none was found
const svg = root.select('#' + id);
@ -65,6 +55,5 @@ export const draw = (text, id, version) => {
};
export default {
setConf,
draw,
};

View File

@ -1,7 +1,5 @@
/** Created by AshishJ on 11-09-2019. */
import { select, scaleOrdinal, pie as d3pie, arc } from 'd3';
import pieData from './pieDb';
import pieParser from './parser/pie';
import { log } from '../../logger';
import { configureSvgSize } from '../../utils';
import * as configApi from '../../config';
@ -17,11 +15,9 @@ let conf = configApi.getConfig();
*/
let width;
const height = 450;
export const draw = (txt, id) => {
export const draw = (txt, id, _version, diagObj) => {
try {
conf = configApi.getConfig();
const parser = pieParser.parser;
parser.yy = pieData;
log.debug('Rendering info diagram\n' + txt);
const securityLevel = configApi.getConfig().securityLevel;
@ -37,8 +33,8 @@ export const draw = (txt, id) => {
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
// Parse the Pie Chart definition
parser.yy.clear();
parser.parse(txt);
diagObj.db.clear();
diagObj.parser.parse(txt);
log.debug('Parsed info diagram');
const elem = doc.getElementById(id);
width = elem.parentElement.offsetWidth;
@ -57,7 +53,7 @@ export const draw = (txt, id) => {
const diagram = root.select('#' + id);
configureSvgSize(diagram, height, width, conf.pie.useMaxWidth);
addSVGAccessibilityFields(parser.yy, diagram, id);
addSVGAccessibilityFields(diagObj.db, diagram, id);
// Set viewBox
elem.setAttribute('viewBox', '0 0 ' + width + ' ' + height);
@ -72,7 +68,7 @@ export const draw = (txt, id) => {
.append('g')
.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');
var data = pieData.getSections();
var data = diagObj.db.getSections();
var sum = 0;
Object.keys(data).forEach(function (key) {
sum += data[key];
@ -136,7 +132,7 @@ export const draw = (txt, id) => {
svg
.append('text')
.text(parser.yy.getDiagramTitle())
.text(diagObj.db.getDiagramTitle())
.attr('x', 0)
.attr('y', -(height - 50) / 2)
.attr('class', 'pieTitleText');
@ -169,7 +165,7 @@ export const draw = (txt, id) => {
.attr('x', legendRectSize + legendSpacing)
.attr('y', legendRectSize - legendSpacing)
.text(function (d) {
if (parser.yy.getShowData() || conf.showData || conf.pie.showData) {
if (diagObj.db.getShowData() || conf.showData || conf.pie.showData) {
return d.data[0] + ' [' + d.data[1] + ']';
} else {
return d.data[0];

View File

@ -1,29 +1,16 @@
import { line, select } from 'd3';
import dagre from 'dagre';
import graphlib from 'graphlib';
// import * as configApi from '../../config';
import { log } from '../../logger';
import { configureSvgSize } from '../../utils';
import common from '../common/common';
import { parser } from './parser/requirementDiagram';
import requirementDb from './requirementDb';
import markers from './requirementMarkers';
import { getConfig } from '../../config';
import addSVGAccessibilityFields from '../../accessibility';
const conf = {};
let conf = {};
let relCnt = 0;
export const setConf = function (cnf) {
if (typeof cnf === 'undefined') {
return;
}
const keys = Object.keys(cnf);
for (let i = 0; i < keys.length; i++) {
conf[keys[i]] = cnf[keys[i]];
}
};
const newRectNode = (parentNode, id) => {
return parentNode
.insert('rect', '#' + id)
@ -162,7 +149,7 @@ const addEdgeLabel = (parentNode, svgPath, conf, txt) => {
.attr('fill-opacity', '85%');
};
const drawRelationshipFromLayout = function (svg, rel, g, insert) {
const drawRelationshipFromLayout = function (svg, rel, g, insert, diagObj) {
// Find the edge relating to this relationship
const edge = g.edge(elementString(rel.src), elementString(rel.dst));
@ -182,7 +169,7 @@ const drawRelationshipFromLayout = function (svg, rel, g, insert) {
.attr('d', lineFunction(edge.points))
.attr('fill', 'none');
if (rel.type == requirementDb.Relationships.CONTAINS) {
if (rel.type == diagObj.db.Relationships.CONTAINS) {
svgPath.attr(
'marker-start',
'url(' + common.getUrl(conf.arrowMarkerAbsolute) + '#' + rel.type + '_line_ending' + ')'
@ -318,12 +305,12 @@ const elementString = (str) => {
return str.replace(/\s/g, '').replace(/\./g, '_');
};
export const draw = (text, id) => {
parser.yy = requirementDb;
parser.yy.clear();
parser.parse(text);
export const draw = (text, id, _version, diagObj) => {
conf = getConfig().requirement;
diagObj.db.clear();
diagObj.parser.parse(text);
const securityLevel = getConfig().securityLevel;
const securityLevel = conf.securityLevel;
// Handle root and Document for when rendering in sanbox mode
let sandboxElement;
if (securityLevel === 'sandbox') {
@ -355,9 +342,9 @@ export const draw = (text, id) => {
return {};
});
let requirements = requirementDb.getRequirements();
let elements = requirementDb.getElements();
let relationships = requirementDb.getRelationships();
let requirements = diagObj.db.getRequirements();
let elements = diagObj.db.getElements();
let relationships = diagObj.db.getRelationships();
drawReqs(requirements, g, svg);
drawElements(elements, g, svg);
@ -366,10 +353,9 @@ export const draw = (text, id) => {
adjustEntities(svg, g);
relationships.forEach(function (rel) {
drawRelationshipFromLayout(svg, rel, g, id);
drawRelationshipFromLayout(svg, rel, g, id, diagObj);
});
// svg.attr('height', '500px');
const padding = conf.rect_padding;
const svgBounds = svg.node().getBBox();
const width = svgBounds.width + padding * 2;
@ -379,10 +365,9 @@ export const draw = (text, id) => {
svg.attr('viewBox', `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`);
// Adds title and description to the requirements diagram
addSVGAccessibilityFields(parser.yy, svg, id);
addSVGAccessibilityFields(diagObj.db, svg, id);
};
export default {
setConf,
draw,
};

View File

@ -1,9 +1,9 @@
import { parser } from './parser/sequenceDiagram';
import sequence from './parser/sequenceDiagram';
import sequenceDb from './sequenceDb';
import * as configApi from '../../config';
import renderer from './sequenceRenderer';
import mermaidAPI from '../../mermaidAPI';
import Diagram from '../../Diagram';
/**
* @param conf
* @param key
@ -16,18 +16,23 @@ function addConf(conf, key, value) {
return conf;
}
const parser = sequence.parser;
describe('when parsing a sequenceDiagram', function () {
beforeEach(function () {
parser.yy = sequenceDb;
parser.yy.clear();
});
it('should handle a sequenceDiagram definition', function () {
fit('should handle a sequenceDiagram definition', function () {
const str = `
sequenceDiagram
Alice->Bob:Hello Bob, how are you?
Note right of Bob: Bob thinks
Bob-->Alice: I am good thanks!`;
// const dia = new Diagram(str);
// console.log('Type = ' + dia.type);
mermaidAPI.parse(str);
const actors = parser.yy.getActors();
expect(actors.Alice.description).toBe('Alice');

View File

@ -1,15 +1,13 @@
import { select, selectAll } from 'd3';
import svgDraw, { drawText, fixLifeLineHeights } from './svgDraw';
import { log } from '../../logger';
import { parser } from './parser/sequenceDiagram';
// import { parser } from './parser/sequenceDiagram';
import common from '../common/common';
import sequenceDb from './sequenceDb';
// import sequenceDb from './sequenceDb';
import * as configApi from '../../config';
import utils, { assignWithDepth, configureSvgSize } from '../../utils';
import addSVGAccessibilityFields from '../../accessibility';
parser.yy = sequenceDb;
let conf = {};
export const bounds = {
@ -86,7 +84,7 @@ export const bounds = {
stopy: undefined,
};
this.verticalPos = 0;
setConf(parser.yy.getConfig());
setConf(configApi.getConfig());
},
updateVal: function (obj, key, val, fun) {
if (typeof obj[key] === 'undefined') {
@ -327,8 +325,9 @@ const boundMessage = function (diagram, msgModel) {
* @param {any} diagram - The parent of the message element
* @param {any} msgModel - The model containing fields describing a message
* @param {float} lineStarty - The Y coordinate at which the message line starts
* @param diagObj
*/
const drawMessage = function (diagram, msgModel, lineStarty) {
const drawMessage = function (diagram, msgModel, lineStarty, diagObj) {
const { startx, stopx, starty, message, type, sequenceIndex, sequenceVisible } = msgModel;
let textDims = utils.calculateTextDimensions(message, messageFont(conf));
const textObj = svgDraw.getTextObj();
@ -394,10 +393,10 @@ const drawMessage = function (diagram, msgModel, lineStarty) {
// Make an SVG Container
// Draw the line
if (
type === parser.yy.LINETYPE.DOTTED ||
type === parser.yy.LINETYPE.DOTTED_CROSS ||
type === parser.yy.LINETYPE.DOTTED_POINT ||
type === parser.yy.LINETYPE.DOTTED_OPEN
type === diagObj.db.LINETYPE.DOTTED ||
type === diagObj.db.LINETYPE.DOTTED_CROSS ||
type === diagObj.db.LINETYPE.DOTTED_POINT ||
type === diagObj.db.LINETYPE.DOTTED_OPEN
) {
line.style('stroke-dasharray', '3, 3');
line.attr('class', 'messageLine1');
@ -420,14 +419,14 @@ const drawMessage = function (diagram, msgModel, lineStarty) {
line.attr('stroke-width', 2);
line.attr('stroke', 'none'); // handled by theme/css anyway
line.style('fill', 'none'); // remove any fill colour
if (type === parser.yy.LINETYPE.SOLID || type === parser.yy.LINETYPE.DOTTED) {
if (type === diagObj.db.LINETYPE.SOLID || type === diagObj.db.LINETYPE.DOTTED) {
line.attr('marker-end', 'url(' + url + '#arrowhead)');
}
if (type === parser.yy.LINETYPE.SOLID_POINT || type === parser.yy.LINETYPE.DOTTED_POINT) {
if (type === diagObj.db.LINETYPE.SOLID_POINT || type === diagObj.db.LINETYPE.DOTTED_POINT) {
line.attr('marker-end', 'url(' + url + '#filled-head)');
}
if (type === parser.yy.LINETYPE.SOLID_CROSS || type === parser.yy.LINETYPE.DOTTED_CROSS) {
if (type === diagObj.db.LINETYPE.SOLID_CROSS || type === diagObj.db.LINETYPE.DOTTED_CROSS) {
line.attr('marker-end', 'url(' + url + '#crosshead)');
}
@ -581,10 +580,13 @@ function adjustLoopHeightForWrap(loopWidths, msg, preMargin, postMargin, addLoop
/**
* Draws a sequenceDiagram in the tag with id: id based on the graph definition in text.
*
* @param {any} text
* @param {any} id
* @param {any} text The text of the diagram
* @param _text
* @param {any} id The id of the diagram which will be used as a DOM element id¨
* @param {any} _version Mermaid version from package.json
* @param {any} diagObj A stanard diagram containing the db and the text and type etc of the diagram
*/
export const draw = function (text, id) {
export const draw = function (_text, id, _version, diagObj) {
conf = configApi.getConfig().sequence;
const securityLevel = configApi.getConfig().securityLevel;
// Handle root and Document for when rendering in sanbox mode
@ -592,28 +594,25 @@ export const draw = function (text, id) {
if (securityLevel === 'sandbox') {
sandboxElement = select('#i' + id);
}
const root =
securityLevel === 'sandbox'
? select(sandboxElement.nodes()[0].contentDocument.body)
: select('body');
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
parser.yy.clear();
parser.yy.setWrap(conf.wrap);
parser.parse(text + '\n');
bounds.init();
log.debug(`C:${JSON.stringify(conf, null, 2)}`);
log.debug(diagObj.db);
const diagram =
securityLevel === 'sandbox' ? root.select(`[id="${id}"]`) : select(`[id="${id}"]`);
// Fetch data from the parsing
const actors = parser.yy.getActors();
const actorKeys = parser.yy.getActorKeys();
const messages = parser.yy.getMessages();
const title = parser.yy.getDiagramTitle();
const actors = diagObj.db.getActors();
const actorKeys = diagObj.db.getActorKeys();
const messages = diagObj.db.getMessages();
const title = diagObj.db.getDiagramTitle();
const maxMessageWidthPerActor = getMaxMessageWidthPerActor(actors, messages);
const maxMessageWidthPerActor = getMaxMessageWidthPerActor(actors, messages, diagObj);
conf.height = calculateActorMargins(actors, maxMessageWidthPerActor);
svgDraw.insertComputerIcon(diagram);
@ -621,7 +620,7 @@ export const draw = function (text, id) {
svgDraw.insertClockIcon(diagram);
drawActors(diagram, actors, actorKeys, 0, conf, messages);
const loopWidths = calculateLoopBounds(messages, actors, maxMessageWidthPerActor);
const loopWidths = calculateLoopBounds(messages, actors, maxMessageWidthPerActor, diagObj);
// The arrow head definition is attached to the svg once
svgDraw.insertArrowHead(diagram);
@ -658,17 +657,17 @@ export const draw = function (text, id) {
let loopModel, noteModel, msgModel;
switch (msg.type) {
case parser.yy.LINETYPE.NOTE:
case diagObj.db.LINETYPE.NOTE:
noteModel = msg.noteModel;
drawNote(diagram, noteModel);
break;
case parser.yy.LINETYPE.ACTIVE_START:
case diagObj.db.LINETYPE.ACTIVE_START:
bounds.newActivation(msg, diagram, actors);
break;
case parser.yy.LINETYPE.ACTIVE_END:
case diagObj.db.LINETYPE.ACTIVE_END:
activeEnd(msg, bounds.getVerticalPos());
break;
case parser.yy.LINETYPE.LOOP_START:
case diagObj.db.LINETYPE.LOOP_START:
adjustLoopHeightForWrap(
loopWidths,
msg,
@ -677,24 +676,24 @@ export const draw = function (text, id) {
(message) => bounds.newLoop(message)
);
break;
case parser.yy.LINETYPE.LOOP_END:
case diagObj.db.LINETYPE.LOOP_END:
loopModel = bounds.endLoop();
svgDraw.drawLoop(diagram, loopModel, 'loop', conf);
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
bounds.models.addLoop(loopModel);
break;
case parser.yy.LINETYPE.RECT_START:
case diagObj.db.LINETYPE.RECT_START:
adjustLoopHeightForWrap(loopWidths, msg, conf.boxMargin, conf.boxMargin, (message) =>
bounds.newLoop(undefined, message.message)
);
break;
case parser.yy.LINETYPE.RECT_END:
case diagObj.db.LINETYPE.RECT_END:
loopModel = bounds.endLoop();
svgDraw.drawBackgroundRect(diagram, loopModel);
bounds.models.addLoop(loopModel);
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
break;
case parser.yy.LINETYPE.OPT_START:
case diagObj.db.LINETYPE.OPT_START:
adjustLoopHeightForWrap(
loopWidths,
msg,
@ -703,13 +702,13 @@ export const draw = function (text, id) {
(message) => bounds.newLoop(message)
);
break;
case parser.yy.LINETYPE.OPT_END:
case diagObj.db.LINETYPE.OPT_END:
loopModel = bounds.endLoop();
svgDraw.drawLoop(diagram, loopModel, 'opt', conf);
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
bounds.models.addLoop(loopModel);
break;
case parser.yy.LINETYPE.ALT_START:
case diagObj.db.LINETYPE.ALT_START:
adjustLoopHeightForWrap(
loopWidths,
msg,
@ -718,7 +717,7 @@ export const draw = function (text, id) {
(message) => bounds.newLoop(message)
);
break;
case parser.yy.LINETYPE.ALT_ELSE:
case diagObj.db.LINETYPE.ALT_ELSE:
adjustLoopHeightForWrap(
loopWidths,
msg,
@ -727,13 +726,13 @@ export const draw = function (text, id) {
(message) => bounds.addSectionToLoop(message)
);
break;
case parser.yy.LINETYPE.ALT_END:
case diagObj.db.LINETYPE.ALT_END:
loopModel = bounds.endLoop();
svgDraw.drawLoop(diagram, loopModel, 'alt', conf);
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
bounds.models.addLoop(loopModel);
break;
case parser.yy.LINETYPE.PAR_START:
case diagObj.db.LINETYPE.PAR_START:
adjustLoopHeightForWrap(
loopWidths,
msg,
@ -742,7 +741,7 @@ export const draw = function (text, id) {
(message) => bounds.newLoop(message)
);
break;
case parser.yy.LINETYPE.PAR_AND:
case diagObj.db.LINETYPE.PAR_AND:
adjustLoopHeightForWrap(
loopWidths,
msg,
@ -751,19 +750,19 @@ export const draw = function (text, id) {
(message) => bounds.addSectionToLoop(message)
);
break;
case parser.yy.LINETYPE.PAR_END:
case diagObj.db.LINETYPE.PAR_END:
loopModel = bounds.endLoop();
svgDraw.drawLoop(diagram, loopModel, 'par', conf);
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
bounds.models.addLoop(loopModel);
break;
case parser.yy.LINETYPE.AUTONUMBER:
case diagObj.db.LINETYPE.AUTONUMBER:
sequenceIndex = msg.message.start || sequenceIndex;
sequenceIndexStep = msg.message.step || sequenceIndexStep;
if (msg.message.visible) parser.yy.enableSequenceNumbers();
else parser.yy.disableSequenceNumbers();
if (msg.message.visible) diagObj.db.enableSequenceNumbers();
else diagObj.db.disableSequenceNumbers();
break;
case parser.yy.LINETYPE.CRITICAL_START:
case diagObj.db.LINETYPE.CRITICAL_START:
adjustLoopHeightForWrap(
loopWidths,
msg,
@ -772,7 +771,7 @@ export const draw = function (text, id) {
(message) => bounds.newLoop(message)
);
break;
case parser.yy.LINETYPE.CRITICAL_OPTION:
case diagObj.db.LINETYPE.CRITICAL_OPTION:
adjustLoopHeightForWrap(
loopWidths,
msg,
@ -781,13 +780,13 @@ export const draw = function (text, id) {
(message) => bounds.addSectionToLoop(message)
);
break;
case parser.yy.LINETYPE.CRITICAL_END:
case diagObj.db.LINETYPE.CRITICAL_END:
loopModel = bounds.endLoop();
svgDraw.drawLoop(diagram, loopModel, 'critical', conf);
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
bounds.models.addLoop(loopModel);
break;
case parser.yy.LINETYPE.BREAK_START:
case diagObj.db.LINETYPE.BREAK_START:
adjustLoopHeightForWrap(
loopWidths,
msg,
@ -796,7 +795,7 @@ export const draw = function (text, id) {
(message) => bounds.newLoop(message)
);
break;
case parser.yy.LINETYPE.BREAK_END:
case diagObj.db.LINETYPE.BREAK_END:
loopModel = bounds.endLoop();
svgDraw.drawLoop(diagram, loopModel, 'break', conf);
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
@ -808,7 +807,7 @@ export const draw = function (text, id) {
msgModel = msg.msgModel;
msgModel.starty = bounds.getVerticalPos();
msgModel.sequenceIndex = sequenceIndex;
msgModel.sequenceVisible = parser.yy.showSequenceNumbers();
msgModel.sequenceVisible = diagObj.db.showSequenceNumbers();
let lineStarty = boundMessage(diagram, msgModel);
messagesToDraw.push({ messageModel: msgModel, lineStarty: lineStarty });
bounds.models.addMessage(msgModel);
@ -820,21 +819,21 @@ export const draw = function (text, id) {
// Increment sequence counter if msg.type is a line (and not another event like activation or note, etc)
if (
[
parser.yy.LINETYPE.SOLID_OPEN,
parser.yy.LINETYPE.DOTTED_OPEN,
parser.yy.LINETYPE.SOLID,
parser.yy.LINETYPE.DOTTED,
parser.yy.LINETYPE.SOLID_CROSS,
parser.yy.LINETYPE.DOTTED_CROSS,
parser.yy.LINETYPE.SOLID_POINT,
parser.yy.LINETYPE.DOTTED_POINT,
diagObj.db.LINETYPE.SOLID_OPEN,
diagObj.db.LINETYPE.DOTTED_OPEN,
diagObj.db.LINETYPE.SOLID,
diagObj.db.LINETYPE.DOTTED,
diagObj.db.LINETYPE.SOLID_CROSS,
diagObj.db.LINETYPE.DOTTED_CROSS,
diagObj.db.LINETYPE.SOLID_POINT,
diagObj.db.LINETYPE.DOTTED_POINT,
].includes(msg.type)
) {
sequenceIndex = sequenceIndex + sequenceIndexStep;
}
});
messagesToDraw.forEach((e) => drawMessage(diagram, e.messageModel, e.lineStarty));
messagesToDraw.forEach((e) => drawMessage(diagram, e.messageModel, e.lineStarty, diagObj));
if (conf.mirrorActors) {
// Draw actors below diagram
@ -895,7 +894,7 @@ export const draw = function (text, id) {
(height + extraVertForTitle)
);
addSVGAccessibilityFields(parser.yy, diagram, id);
addSVGAccessibilityFields(diagObj.db, diagram, id);
log.debug(`models:`, bounds.models);
};
@ -907,9 +906,10 @@ export const draw = function (text, id) {
*
* @param {any} actors - The actors map
* @param {Array} messages - A list of message objects to iterate
* @param diagObj
* @returns {any}
*/
const getMaxMessageWidthPerActor = function (actors, messages) {
const getMaxMessageWidthPerActor = function (actors, messages, diagObj) {
const maxMessageWidthPerActor = {};
messages.forEach(function (msg) {
@ -917,12 +917,12 @@ const getMaxMessageWidthPerActor = function (actors, messages) {
const actor = actors[msg.to];
// If this is the first actor, and the message is left of it, no need to calculate the margin
if (msg.placement === parser.yy.PLACEMENT.LEFTOF && !actor.prevActor) {
if (msg.placement === diagObj.db.PLACEMENT.LEFTOF && !actor.prevActor) {
return;
}
// If this is the last actor, and the message is right of it, no need to calculate the margin
if (msg.placement === parser.yy.PLACEMENT.RIGHTOF && !actor.nextActor) {
if (msg.placement === diagObj.db.PLACEMENT.RIGHTOF && !actor.nextActor) {
return;
}
@ -972,17 +972,17 @@ const getMaxMessageWidthPerActor = function (actors, messages) {
maxMessageWidthPerActor[msg.to] || 0,
messageWidth / 2
);
} else if (msg.placement === parser.yy.PLACEMENT.RIGHTOF) {
} else if (msg.placement === diagObj.db.PLACEMENT.RIGHTOF) {
maxMessageWidthPerActor[msg.from] = Math.max(
maxMessageWidthPerActor[msg.from] || 0,
messageWidth
);
} else if (msg.placement === parser.yy.PLACEMENT.LEFTOF) {
} else if (msg.placement === diagObj.db.PLACEMENT.LEFTOF) {
maxMessageWidthPerActor[actor.prevActor] = Math.max(
maxMessageWidthPerActor[actor.prevActor] || 0,
messageWidth
);
} else if (msg.placement === parser.yy.PLACEMENT.OVER) {
} else if (msg.placement === diagObj.db.PLACEMENT.OVER) {
if (actor.prevActor) {
maxMessageWidthPerActor[actor.prevActor] = Math.max(
maxMessageWidthPerActor[actor.prevActor] || 0,
@ -1070,7 +1070,7 @@ const calculateActorMargins = function (actors, actorToMessageWidth) {
return Math.max(maxHeight, conf.height);
};
const buildNoteModel = function (msg, actors) {
const buildNoteModel = function (msg, actors, diagObj) {
let startx = actors[msg.from].x;
let stopx = actors[msg.to].x;
let shouldWrap = msg.wrap && msg.message;
@ -1090,7 +1090,7 @@ const buildNoteModel = function (msg, actors) {
stopy: 0,
message: msg.message,
};
if (msg.placement === parser.yy.PLACEMENT.RIGHTOF) {
if (msg.placement === diagObj.db.PLACEMENT.RIGHTOF) {
noteModel.width = shouldWrap
? Math.max(conf.width, textDimensions.width)
: Math.max(
@ -1098,7 +1098,7 @@ const buildNoteModel = function (msg, actors) {
textDimensions.width + 2 * conf.noteMargin
);
noteModel.startx = startx + (actors[msg.from].width + conf.actorMargin) / 2;
} else if (msg.placement === parser.yy.PLACEMENT.LEFTOF) {
} else if (msg.placement === diagObj.db.PLACEMENT.LEFTOF) {
noteModel.width = shouldWrap
? Math.max(conf.width, textDimensions.width + 2 * conf.noteMargin)
: Math.max(
@ -1139,18 +1139,18 @@ const buildNoteModel = function (msg, actors) {
return noteModel;
};
const buildMessageModel = function (msg, actors) {
const buildMessageModel = function (msg, actors, diagObj) {
let process = false;
if (
[
parser.yy.LINETYPE.SOLID_OPEN,
parser.yy.LINETYPE.DOTTED_OPEN,
parser.yy.LINETYPE.SOLID,
parser.yy.LINETYPE.DOTTED,
parser.yy.LINETYPE.SOLID_CROSS,
parser.yy.LINETYPE.DOTTED_CROSS,
parser.yy.LINETYPE.SOLID_POINT,
parser.yy.LINETYPE.DOTTED_POINT,
diagObj.db.LINETYPE.SOLID_OPEN,
diagObj.db.LINETYPE.DOTTED_OPEN,
diagObj.db.LINETYPE.SOLID,
diagObj.db.LINETYPE.DOTTED,
diagObj.db.LINETYPE.SOLID_CROSS,
diagObj.db.LINETYPE.DOTTED_CROSS,
diagObj.db.LINETYPE.SOLID_POINT,
diagObj.db.LINETYPE.DOTTED_POINT,
].includes(msg.type)
) {
process = true;
@ -1192,7 +1192,7 @@ const buildMessageModel = function (msg, actors) {
};
};
const calculateLoopBounds = function (messages, actors) {
const calculateLoopBounds = function (messages, actors, _maxWidthPerActor, diagObj) {
const loops = {};
const stack = [];
let current, noteModel, msgModel;
@ -1200,12 +1200,12 @@ const calculateLoopBounds = function (messages, actors) {
messages.forEach(function (msg) {
msg.id = utils.random({ length: 10 });
switch (msg.type) {
case parser.yy.LINETYPE.LOOP_START:
case parser.yy.LINETYPE.ALT_START:
case parser.yy.LINETYPE.OPT_START:
case parser.yy.LINETYPE.PAR_START:
case parser.yy.LINETYPE.CRITICAL_START:
case parser.yy.LINETYPE.BREAK_START:
case diagObj.db.LINETYPE.LOOP_START:
case diagObj.db.LINETYPE.ALT_START:
case diagObj.db.LINETYPE.OPT_START:
case diagObj.db.LINETYPE.PAR_START:
case diagObj.db.LINETYPE.CRITICAL_START:
case diagObj.db.LINETYPE.BREAK_START:
stack.push({
id: msg.id,
msg: msg.message,
@ -1214,9 +1214,9 @@ const calculateLoopBounds = function (messages, actors) {
width: 0,
});
break;
case parser.yy.LINETYPE.ALT_ELSE:
case parser.yy.LINETYPE.PAR_AND:
case parser.yy.LINETYPE.CRITICAL_OPTION:
case diagObj.db.LINETYPE.ALT_ELSE:
case diagObj.db.LINETYPE.PAR_AND:
case diagObj.db.LINETYPE.CRITICAL_OPTION:
if (msg.message) {
current = stack.pop();
loops[current.id] = current;
@ -1224,16 +1224,16 @@ const calculateLoopBounds = function (messages, actors) {
stack.push(current);
}
break;
case parser.yy.LINETYPE.LOOP_END:
case parser.yy.LINETYPE.ALT_END:
case parser.yy.LINETYPE.OPT_END:
case parser.yy.LINETYPE.PAR_END:
case parser.yy.LINETYPE.CRITICAL_END:
case parser.yy.LINETYPE.BREAK_END:
case diagObj.db.LINETYPE.LOOP_END:
case diagObj.db.LINETYPE.ALT_END:
case diagObj.db.LINETYPE.OPT_END:
case diagObj.db.LINETYPE.PAR_END:
case diagObj.db.LINETYPE.CRITICAL_END:
case diagObj.db.LINETYPE.BREAK_END:
current = stack.pop();
loops[current.id] = current;
break;
case parser.yy.LINETYPE.ACTIVE_START:
case diagObj.db.LINETYPE.ACTIVE_START:
{
const actorRect = actors[msg.from ? msg.from.actor : msg.to.actor];
const stackedSize = actorActivations(msg.from ? msg.from.actor : msg.to.actor).length;
@ -1248,7 +1248,7 @@ const calculateLoopBounds = function (messages, actors) {
bounds.activations.push(toAdd);
}
break;
case parser.yy.LINETYPE.ACTIVE_END:
case diagObj.db.LINETYPE.ACTIVE_END:
{
const lastActorActivationIdx = bounds.activations
.map((a) => a.actor)
@ -1259,7 +1259,7 @@ const calculateLoopBounds = function (messages, actors) {
}
const isNote = msg.placement !== undefined;
if (isNote) {
noteModel = buildNoteModel(msg, actors);
noteModel = buildNoteModel(msg, actors, diagObj);
msg.noteModel = noteModel;
stack.forEach((stk) => {
current = stk;
@ -1269,7 +1269,7 @@ const calculateLoopBounds = function (messages, actors) {
Math.max(current.width, Math.abs(current.from - current.to)) - conf.labelBoxWidth;
});
} else {
msgModel = buildMessageModel(msg, actors);
msgModel = buildMessageModel(msg, actors, diagObj);
msg.msgModel = msgModel;
if (msgModel.startx && msgModel.stopx && stack.length > 0) {
stack.forEach((stk) => {

View File

@ -1,7 +1,5 @@
import graphlib from 'graphlib';
import { select } from 'd3';
import stateDb from './stateDb';
import state from './parser/stateDiagram';
import { getConfig } from '../../config';
import { render } from '../../dagre-wrapper/index.js';
import { log } from '../../logger';
@ -23,17 +21,16 @@ let nodeDb = {};
* Returns the all the styles from classDef statements in the graph definition.
*
* @param {any} text
* @param diag
* @returns {object} ClassDef styles
*/
export const getClasses = function (text) {
export const getClasses = function (text, diag) {
log.trace('Extracting classes');
stateDb.clear();
const parser = state.parser;
parser.yy = stateDb;
diag.sb.clear();
// Parse the graph definition
parser.parse(text);
return stateDb.getClasses();
diag.parser.parse(text);
return diag.sb.getClasses();
};
const setupNode = (g, parent, node, altFlag) => {
@ -238,19 +235,15 @@ const getDir = (nodes, defaultDir) => {
*
* @param {any} text
* @param {any} id
* @param _version
* @param diag
*/
export const draw = function (text, id) {
export const draw = function (text, id, _version, diag) {
log.info('Drawing state diagram (v2)', id);
stateDb.clear();
// diag.sb.clear();
nodeDb = {};
const parser = state.parser;
parser.yy = stateDb;
// Parse the graph definition
parser.parse(text);
// Fetch the default direction, use TD if none was found
let dir = stateDb.getDirection();
let dir = diag.db.getDirection();
if (typeof dir === 'undefined') {
dir = 'LR';
}
@ -261,9 +254,9 @@ export const draw = function (text, id) {
const securityLevel = getConfig().securityLevel;
log.info(stateDb.getRootDocV2());
stateDb.extract(stateDb.getRootDocV2());
log.info(stateDb.getRootDocV2());
log.info(diag.db.getRootDocV2());
diag.db.extract(diag.db.getRootDocV2());
log.info(diag.db.getRootDocV2());
// Create the input mermaid.graph
const g = new graphlib.Graph({
@ -271,7 +264,7 @@ export const draw = function (text, id) {
compound: true,
})
.setGraph({
rankdir: getDir(stateDb.getRootDocV2()),
rankdir: getDir(diag.db.getRootDocV2()),
nodesep: nodeSpacing,
ranksep: rankSpacing,
marginx: 8,
@ -281,7 +274,7 @@ export const draw = function (text, id) {
return {};
});
setupNode(g, undefined, stateDb.getRootDocV2(), true);
setupNode(g, undefined, diag.db.getRootDocV2(), true);
// Set up an SVG group so that we can translate the final graph.
let sandboxElement;
@ -337,7 +330,7 @@ export const draw = function (text, id) {
label.insertBefore(rect, label.firstChild);
// }
}
addSVGAccessibilityFields(parser.yy, svg, id);
addSVGAccessibilityFields(diag.db, svg, id);
};
export default {

View File

@ -2,17 +2,12 @@ import { select } from 'd3';
import dagre from 'dagre';
import graphlib from 'graphlib';
import { log } from '../../logger';
import stateDb from './stateDb';
import common from '../common/common';
import { parser } from './parser/stateDiagram';
// import idCache from './id-cache';
import { drawState, addTitleAndBox, drawEdge } from './shapes';
import { getConfig } from '../../config';
import { configureSvgSize } from '../../utils';
import addSVGAccessibilityFields from '../../accessibility';
parser.yy = stateDb;
// TODO Move conf object to main conf in mermaidAPI
let conf;
@ -44,8 +39,10 @@ const insertMarkers = function (elem) {
*
* @param {any} text
* @param {any} id
* @param _version
* @param diagObj
*/
export const draw = function (text, id) {
export const draw = function (text, id, _version, diagObj) {
conf = getConfig().state;
const securityLevel = getConfig().securityLevel;
// Handle root and Document for when rendering in sanbox mode
@ -59,8 +56,8 @@ export const draw = function (text, id) {
: select('body');
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
parser.yy.clear();
parser.parse(text);
// diagObj.db.clear();
// parser.parse(text);
log.debug('Rendering diagram ' + text);
// Fetch the default direction, use TD if none was found
@ -81,8 +78,8 @@ export const draw = function (text, id) {
return {};
});
const rootDoc = stateDb.getRootDoc();
renderDoc(rootDoc, diagram, undefined, false, root, doc);
const rootDoc = diagObj.db.getRootDoc();
renderDoc(rootDoc, diagram, undefined, false, root, doc, diagObj);
const padding = conf.padding;
const bounds = diagram.node().getBBox();
@ -98,13 +95,13 @@ export const draw = function (text, id) {
'viewBox',
`${bounds.x - conf.padding} ${bounds.y - conf.padding} ` + width + ' ' + height
);
addSVGAccessibilityFields(parser.yy, diagram, id);
addSVGAccessibilityFields(diagObj.db, diagram, id);
};
const getLabelWidth = (text) => {
return text ? text.length * conf.fontSizeFactor : 1;
};
const renderDoc = (doc, diagram, parentId, altBkg, root, domDocument) => {
const renderDoc = (doc, diagram, parentId, altBkg, root, domDocument, diagObj) => {
// Layout graph, Create a new directed graph
const graph = new graphlib.Graph({
compound: true,
@ -155,9 +152,9 @@ const renderDoc = (doc, diagram, parentId, altBkg, root, domDocument) => {
return {};
});
stateDb.extract(doc);
const states = stateDb.getStates();
const relations = stateDb.getRelations();
diagObj.db.extract(doc);
const states = diagObj.db.getStates();
const relations = diagObj.db.getRelations();
const keys = Object.keys(states);
@ -173,7 +170,7 @@ const renderDoc = (doc, diagram, parentId, altBkg, root, domDocument) => {
let node;
if (stateDef.doc) {
let sub = diagram.append('g').attr('id', stateDef.id).attr('class', 'stateGroup');
node = renderDoc(stateDef.doc, sub, stateDef.id, !altBkg, root, domDocument);
node = renderDoc(stateDef.doc, sub, stateDef.id, !altBkg, root, domDocument, diagObj);
if (first) {
// first = false;

View File

@ -1,13 +1,9 @@
import { select } from 'd3';
import { parser } from './parser/journey';
import journeyDb from './journeyDb';
import svgDraw from './svgDraw';
import { getConfig } from '../../config';
import { configureSvgSize } from '../../utils';
import addSVGAccessibilityFields from '../../accessibility';
parser.yy = journeyDb;
export const setConf = function (cnf) {
const keys = Object.keys(cnf);
@ -50,10 +46,10 @@ function drawActorLegend(diagram) {
}
const conf = getConfig().journey;
const LEFT_MARGIN = getConfig().journey.leftMargin;
export const draw = function (text, id) {
export const draw = function (text, id, version, diagObj) {
const conf = getConfig().journey;
parser.yy.clear();
parser.parse(text + '\n');
diagObj.db.clear();
diagObj.parser.parse(text + '\n');
const securityLevel = getConfig().securityLevel;
// Handle root and Document for when rendering in sanbox mode
@ -65,17 +61,18 @@ export const draw = function (text, id) {
securityLevel === 'sandbox'
? select(sandboxElement.nodes()[0].contentDocument.body)
: select('body');
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
// const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
bounds.init();
const diagram = root.select('#' + id);
svgDraw.initGraphics(diagram);
const tasks = parser.yy.getTasks();
const title = parser.yy.getDiagramTitle();
const tasks = diagObj.db.getTasks();
console.log('text and tasks', text, tasks);
const title = diagObj.db.getDiagramTitle();
const actorNames = parser.yy.getActors();
const actorNames = diagObj.db.getActors();
for (let member in actors) delete actors[member];
let actorPos = 0;
actorNames.forEach((actorName) => {
@ -122,7 +119,7 @@ export const draw = function (text, id) {
diagram.attr('preserveAspectRatio', 'xMinYMin meet');
diagram.attr('height', height + extraVertForTitle + 25);
addSVGAccessibilityFields(parser.yy, diagram, id);
addSVGAccessibilityFields(diagObj.db, diagram, id);
};
export const bounds = {

View File

@ -2,6 +2,7 @@ import mermaid from './mermaid';
import flowDb from './diagrams/flowchart/flowDb';
import flowParser from './diagrams/flowchart/parser/flow';
import flowRenderer from './diagrams/flowchart/flowRenderer';
import Diagram from './Diagram';
const spyOn = jest.spyOn;
@ -46,9 +47,9 @@ describe('when using mermaid and ', function () {
flowDb.setGen('gen-2');
});
it('it should handle edges with text', function () {
flowParser.parser.parse('graph TD;A-->|text ex|B;');
flowParser.parser.yy.getVertices();
const edges = flowParser.parser.yy.getEdges();
const diag = new Diagram('graph TD;A-->|text ex|B;');
diag.db.getVertices();
const edges = diag.db.getEdges();
const mockG = {
setEdge: function (start, end, options) {
@ -59,13 +60,13 @@ describe('when using mermaid and ', function () {
},
};
flowRenderer.addEdges(edges, mockG);
flowRenderer.addEdges(edges, mockG, diag);
});
it('should handle edges without text', function () {
flowParser.parser.parse('graph TD;A-->B;');
flowParser.parser.yy.getVertices();
const edges = flowParser.parser.yy.getEdges();
const diag = new Diagram('graph TD;A-->B;');
diag.db.getVertices();
const edges = diag.db.getEdges();
const mockG = {
setEdge: function (start, end, options) {
@ -75,13 +76,13 @@ describe('when using mermaid and ', function () {
},
};
flowRenderer.addEdges(edges, mockG);
flowRenderer.addEdges(edges, mockG, diag);
});
it('should handle open-ended edges', function () {
flowParser.parser.parse('graph TD;A---B;');
flowParser.parser.yy.getVertices();
const edges = flowParser.parser.yy.getEdges();
const diag = new Diagram('graph TD;A---B;');
diag.db.getVertices();
const edges = diag.db.getEdges();
const mockG = {
setEdge: function (start, end, options) {
@ -91,13 +92,13 @@ describe('when using mermaid and ', function () {
},
};
flowRenderer.addEdges(edges, mockG);
flowRenderer.addEdges(edges, mockG, diag);
});
it('should handle edges with styles defined', function () {
flowParser.parser.parse('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;');
flowParser.parser.yy.getVertices();
const edges = flowParser.parser.yy.getEdges();
const diag = new Diagram('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;');
diag.db.getVertices();
const edges = diag.db.getEdges();
const mockG = {
setEdge: function (start, end, options) {
@ -108,12 +109,12 @@ describe('when using mermaid and ', function () {
},
};
flowRenderer.addEdges(edges, mockG);
flowRenderer.addEdges(edges, mockG, diag);
});
it('should handle edges with interpolation defined', function () {
flowParser.parser.parse('graph TD;A---B; linkStyle 0 interpolate basis');
flowParser.parser.yy.getVertices();
const edges = flowParser.parser.yy.getEdges();
const diag = new Diagram('graph TD;A---B; linkStyle 0 interpolate basis');
diag.db.getVertices();
const edges = diag.db.getEdges();
const mockG = {
setEdge: function (start, end, options) {
@ -124,14 +125,14 @@ describe('when using mermaid and ', function () {
},
};
flowRenderer.addEdges(edges, mockG);
flowRenderer.addEdges(edges, mockG, diag);
});
it('should handle edges with text and styles defined', function () {
flowParser.parser.parse(
const diag = new Diagram(
'graph TD;A---|the text|B; linkStyle 0 stroke:val1,stroke-width:val2;'
);
flowParser.parser.yy.getVertices();
const edges = flowParser.parser.yy.getEdges();
diag.db.getVertices();
const edges = diag.db.getEdges();
const mockG = {
setEdge: function (start, end, options) {
@ -143,13 +144,13 @@ describe('when using mermaid and ', function () {
},
};
flowRenderer.addEdges(edges, mockG);
flowRenderer.addEdges(edges, mockG, diag);
});
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.yy.getVertices();
const edges = flowParser.parser.yy.getEdges();
const diag = new Diagram('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;');
diag.db.getVertices();
const edges = diag.db.getEdges();
const mockG = {
setEdge: function (start, end, options) {
@ -160,15 +161,15 @@ describe('when using mermaid and ', function () {
},
};
flowRenderer.addEdges(edges, mockG);
flowRenderer.addEdges(edges, mockG, diag);
});
it('should not set fill to none if fill is set in linkStyle', function () {
flowParser.parser.parse(
const diag = new Diagram(
'graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2,fill:blue;'
);
flowParser.parser.yy.getVertices();
const edges = flowParser.parser.yy.getEdges();
diag.db.getVertices();
const edges = diag.db.getEdges();
const mockG = {
setEdge: function (start, end, options) {
expect(start).toContain('flowchart-A-');
@ -178,7 +179,7 @@ describe('when using mermaid and ', function () {
},
};
flowRenderer.addEdges(edges, mockG);
flowRenderer.addEdges(edges, mockG, diag);
});
});

View File

@ -59,6 +59,7 @@ import stateRendererV2 from './diagrams/state/stateRenderer-v2';
import journeyDb from './diagrams/user-journey/journeyDb';
import journeyRenderer from './diagrams/user-journey/journeyRenderer';
import journeyParser from './diagrams/user-journey/parser/journey';
import Diagram from './Diagram';
import errorRenderer from './errorRenderer';
import { attachFunctions } from './interactionDb';
import { log, setLogLevel } from './logger';
@ -70,96 +71,20 @@ import mermaid from './mermaid';
/**
* @param text
* @param dia
* @returns {any}
*/
function parse(text) {
function parse(text, dia) {
var parseEncounteredException = false;
try {
text = text + '\n';
const diag = dia ? dia : new Diagram(text);
diag.db.clear();
const cnf = configApi.getConfig();
const graphInit = utils.detectInit(text, cnf);
if (graphInit) {
reinitialize(graphInit);
log.info('reinit ', graphInit);
}
const graphType = utils.detectType(text, cnf);
let parser;
let parser = diag.parser;
log.debug('Type ' + graphType);
switch (graphType) {
case 'c4':
c4Db.clear();
parser = c4Parser;
parser.parser.yy = c4Db;
break;
case 'gitGraph':
gitGraphAst.clear();
parser = gitGraphParser;
parser.parser.yy = gitGraphAst;
break;
case 'flowchart':
flowDb.clear();
parser = flowParser;
parser.parser.yy = flowDb;
break;
case 'flowchart-v2':
flowDb.clear();
parser = flowParser;
parser.parser.yy = flowDb;
break;
case 'sequence':
sequenceDb.clear();
parser = sequenceParser;
parser.parser.yy = sequenceDb;
break;
case 'gantt':
parser = ganttParser;
parser.parser.yy = ganttDb;
break;
case 'class':
parser = classParser;
parser.parser.yy = classDb;
break;
case 'classDiagram':
parser = classParser;
parser.parser.yy = classDb;
break;
case 'state':
parser = stateParser;
parser.parser.yy = stateDb;
break;
case 'stateDiagram':
parser = stateParser;
parser.parser.yy = stateDb;
break;
case 'info':
log.debug('info info info');
parser = infoParser;
parser.parser.yy = infoDb;
break;
case 'pie':
log.debug('pie');
parser = pieParser;
parser.parser.yy = pieDb;
break;
case 'er':
log.debug('er');
parser = erParser;
parser.parser.yy = erDb;
break;
case 'journey':
log.debug('Journey');
parser = journeyParser;
parser.parser.yy = journeyDb;
break;
case 'requirement':
case 'requirementDiagram':
log.debug('RequirementDiagram');
parser = requirementParser;
parser.parser.yy = requirementDb;
break;
}
parser.parser.yy.graphType = graphType;
log.debug('Type ' + diag.type);
parser.parser.yy.graphType = diag.type;
parser.parser.yy.parseError = (str, hash) => {
const error = { str, hash };
throw error;
@ -269,7 +194,6 @@ const render = function (id, _txt, cb, container) {
txt = 'graph TB;a[Maximum text size in diagram exceeded];style a fill:#faa';
}
// let d3Iframe;
let root = select('body');
// In regular execution the container will be the div with a mermaid class
@ -282,7 +206,6 @@ const render = function (id, _txt, cb, container) {
.attr('id', 'i' + id)
.attr('style', 'width: 100%; height: 100%;')
.attr('sandbox', '');
// const iframeBody = ;
root = select(iframe.nodes()[0].contentDocument.body);
root.node().style.margin = 0;
}
@ -335,15 +258,6 @@ const render = function (id, _txt, cb, container) {
element.remove();
}
// if (cnf.securityLevel === 'sandbox') {
// const iframe = select('body')
// .append('iframe')
// .attr('id', 'i' + id)
// .attr('sandbox', '');
// // const iframeBody = ;
// root = select(iframe.nodes()[0].contentDocument.body);
// }
// Add the tmp div used for rendering with the id `d${id}`
// d+id it will contain a svg with the id "id"
@ -355,7 +269,7 @@ const render = function (id, _txt, cb, container) {
.attr('id', 'i' + id)
.attr('style', 'width: 100%; height: 100%;')
.attr('sandbox', '');
// const iframeBody = ;
root = select(iframe.nodes()[0].contentDocument.body);
root.node().style.margin = 0;
} else {
@ -376,9 +290,10 @@ const render = function (id, _txt, cb, container) {
txt = encodeEntities(txt);
const diag = new Diagram(txt);
// Get the tmp element containing the the svg
const element = root.select('#d' + id).node();
const graphType = utils.detectType(txt, cnf);
const graphType = diag.type;
// insert inline style into svg
const svg = element.firstChild;
@ -402,7 +317,7 @@ const render = function (id, _txt, cb, container) {
// classDef
if (graphType === 'flowchart' || graphType === 'flowchart-v2' || graphType === 'graph') {
const classes = flowRenderer.getClasses(txt);
const classes = flowRenderer.getClasses(txt, diag);
const htmlLabels = cnf.htmlLabels || cnf.flowchart.htmlLabels;
for (const className in classes) {
if (htmlLabels) {
@ -437,8 +352,6 @@ const render = function (id, _txt, cb, container) {
}
}
// log.warn(cnf.themeVariables);
const stylis = (selector, styles) => serialize(compile(`${selector}{${styles}}`), stringify);
const rules = stylis(`#${id}`, getStyles(graphType, userStyles, cnf.themeVariables));
@ -446,102 +359,9 @@ const render = function (id, _txt, cb, container) {
style1.innerHTML = `#${id} ` + rules;
svg.insertBefore(style1, firstChild);
// Verify that the generated svgs are ok before removing this
// const style2 = document.createElement('style');
// const cs = window.getComputedStyle(svg);
// style2.innerHTML = `#d${id} * {
// color: ${cs.color};
// // font: ${cs.font};
// // font-family: Arial;
// // font-size: 24px;
// }`;
// svg.insertBefore(style2, firstChild);
try {
switch (graphType) {
case 'c4':
c4Renderer.setConf(cnf.c4);
c4Renderer.draw(txt, id);
break;
case 'gitGraph':
// cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
//gitGraphRenderer.setConf(cnf.git);
gitGraphRenderer.draw(txt, id, false);
break;
case 'flowchart':
cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
flowRenderer.setConf(cnf.flowchart);
flowRenderer.draw(txt, id, false);
break;
case 'flowchart-v2':
cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
flowRendererV2.setConf(cnf.flowchart);
flowRendererV2.draw(txt, id, false);
break;
case 'sequence':
cnf.sequence.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
if (cnf.sequenceDiagram) {
// backwards compatibility
sequenceRenderer.setConf(Object.assign(cnf.sequence, cnf.sequenceDiagram));
console.error(
'`mermaid config.sequenceDiagram` has been renamed to `config.sequence`. Please update your mermaid config.'
);
} else {
sequenceRenderer.setConf(cnf.sequence);
}
sequenceRenderer.draw(txt, id);
break;
case 'gantt':
cnf.gantt.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
ganttRenderer.setConf(cnf.gantt);
ganttRenderer.draw(txt, id);
break;
case 'class':
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
classRenderer.setConf(cnf.class);
classRenderer.draw(txt, id);
break;
case 'classDiagram':
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
classRendererV2.setConf(cnf.class);
classRendererV2.draw(txt, id);
break;
case 'state':
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
stateRenderer.setConf(cnf.state);
stateRenderer.draw(txt, id);
break;
case 'stateDiagram':
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
stateRendererV2.setConf(cnf.state);
stateRendererV2.draw(txt, id);
break;
case 'info':
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
infoRenderer.setConf(cnf.class);
infoRenderer.draw(txt, id, pkg.version);
break;
case 'pie':
//cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
//pieRenderer.setConf(cnf.pie);
pieRenderer.draw(txt, id, pkg.version);
break;
case 'er':
erRenderer.setConf(cnf.er);
erRenderer.draw(txt, id, pkg.version);
break;
case 'journey':
journeyRenderer.setConf(cnf.journey);
journeyRenderer.draw(txt, id, pkg.version);
break;
case 'requirement':
requirementRenderer.setConf(cnf.requirement);
requirementRenderer.draw(txt, id, pkg.version);
break;
}
diag.renderer.draw(txt, id, pkg.version, diag);
} catch (e) {
// errorRenderer.setConf(cnf.class);
errorRenderer.draw(id, pkg.version);
throw e;
}
@ -572,7 +392,6 @@ const render = function (id, _txt, cb, container) {
let width = '100%';
let height = '100%';
if (svgEl) {
// width = svgEl.viewBox.baseVal.width + 'px';
height = svgEl.viewBox.baseVal.height + 'px';
}
svgCode = `<iframe style="width:${width};height:${height};border:0;margin:0;" src="data:text/html;base64,${btoa(
@ -666,7 +485,6 @@ const handleDirective = function (p, directive, type) {
log.debug('sanitize in handleDirective', directive.args);
directiveSanitizer(directive.args);
log.debug('sanitize in handleDirective (done)', directive.args);
reinitialize(directive.args);
configApi.addDirective(directive.args);
break;
}
@ -694,7 +512,6 @@ const handleDirective = function (p, directive, type) {
function updateRendererConfigs(conf) {
// Todo remove, all diagrams should get config on demand from the config object, no need for this
// gitGraphRenderer.setConf(conf.git); // Todo Remove all of these
flowRenderer.setConf(conf.flowchart);
flowRendererV2.setConf(conf.flowchart);
if (typeof conf['sequenceDiagram'] !== 'undefined') {
@ -702,37 +519,16 @@ function updateRendererConfigs(conf) {
}
sequenceRenderer.setConf(conf.sequence);
ganttRenderer.setConf(conf.gantt);
classRenderer.setConf(conf.class);
// classRenderer.setConf(conf.class);
stateRenderer.setConf(conf.state);
stateRendererV2.setConf(conf.state);
infoRenderer.setConf(conf.class);
// pieRenderer.setConf(conf.class);
erRenderer.setConf(conf.er);
// infoRenderer.setConf(conf.class);
journeyRenderer.setConf(conf.journey);
requirementRenderer.setConf(conf.requirement);
errorRenderer.setConf(conf.class);
}
/** To be removed */
function reinitialize() {
// `mermaidAPI.reinitialize: v${pkg.version}`,
// JSON.stringify(options),
// options.themeVariables.primaryColor;
// // if (options.theme && theme[options.theme]) {
// // options.themeVariables = theme[options.theme].getThemeVariables(options.themeVariables);
// // }
// // Set default options
// const config =
// typeof options === 'object' ? configApi.setConfig(options) : configApi.getSiteConfig();
// updateRendererConfigs(config);
// setLogLevel(config.logLevel);
// log.debug('mermaidAPI.reinitialize: ', config);
}
/** @param {any} options */
function initialize(options) {
// console.warn(`mermaidAPI.initialize: v${pkg.version} `, options);
// Handle legacy location of font-family configuration
if (options && options.fontFamily) {
if (!options.themeVariables) {
@ -758,7 +554,6 @@ function initialize(options) {
updateRendererConfigs(config);
setLogLevel(config.logLevel);
// log.debug('mermaidAPI.initialize: ', config);
}
const mermaidAPI = Object.freeze({
@ -766,16 +561,12 @@ const mermaidAPI = Object.freeze({
parse,
parseDirective,
initialize,
reinitialize,
getConfig: configApi.getConfig,
setConfig: configApi.setConfig,
getSiteConfig: configApi.getSiteConfig,
updateSiteConfig: configApi.updateSiteConfig,
reset: () => {
// console.warn('reset');
configApi.reset();
// const siteConfig = configApi.getSiteConfig();
// updateRendererConfigs(siteConfig);
},
globalReset: () => {
configApi.reset(configApi.defaultConfig);

View File

@ -64,7 +64,7 @@ describe('when using mermaidAPI and ', function () {
mermaidAPI.initialize({ securityLevel: 'loose' });
},
};
mermaidAPI.reinitialize(config);
// mermaidAPI.reinitialize(config);
expect(mermaidAPI.getConfig().secure).toEqual(mermaidAPI.getSiteConfig().secure);
expect(mermaidAPI.getConfig().securityLevel).toBe('strict');
mermaidAPI.reset();