mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-24 09:49:46 +02:00
Merge branch 'release/8.4.1'
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import * as d3 from 'd3';
|
||||
import dagre from 'dagre-layout';
|
||||
import graphlib from 'graphlibrary';
|
||||
import dagre from 'dagre';
|
||||
import graphlib from 'graphlib';
|
||||
import { logger } from '../../logger';
|
||||
import classDb from './classDb';
|
||||
import utils from '../../utils';
|
||||
@@ -204,14 +204,12 @@ const drawEdge = function(elem, path, relation) {
|
||||
x = labalPosition.x;
|
||||
y = labalPosition.y;
|
||||
|
||||
let p1_card_x,
|
||||
p1_card_y,
|
||||
p1_card_padd_x = conf.padding * 2,
|
||||
p1_card_padd_y = conf.padding;
|
||||
let p2_card_x,
|
||||
p2_card_y,
|
||||
p2_card_padd_x = conf.padding * 2,
|
||||
p2_card_padd_y = -conf.padding / 2;
|
||||
let p1_card_x, p1_card_y;
|
||||
// p1_card_padd_x = conf.padding * 2,
|
||||
// p1_card_padd_y = conf.padding;
|
||||
let p2_card_x, p2_card_y;
|
||||
// p2_card_padd_x = conf.padding * 2,
|
||||
// p2_card_padd_y = -conf.padding / 2;
|
||||
if (l % 2 !== 0 && l > 1) {
|
||||
let cardinality_1_point = utils.calcCardinalityPosition(
|
||||
relation.relation.type1 !== 'none',
|
||||
@@ -258,8 +256,7 @@ const drawEdge = function(elem, path, relation) {
|
||||
logger.info('Rendering relation ' + JSON.stringify(relation));
|
||||
if (typeof relation.relationTitle1 !== 'undefined' && relation.relationTitle1 !== 'none') {
|
||||
const g = elem.append('g').attr('class', 'cardinality');
|
||||
const label = g
|
||||
.append('text')
|
||||
g.append('text')
|
||||
.attr('class', 'type1')
|
||||
.attr('x', p1_card_x)
|
||||
.attr('y', p1_card_y)
|
||||
@@ -269,8 +266,7 @@ const drawEdge = function(elem, path, relation) {
|
||||
}
|
||||
if (typeof relation.relationTitle2 !== 'undefined' && relation.relationTitle2 !== 'none') {
|
||||
const g = elem.append('g').attr('class', 'cardinality');
|
||||
const label = g
|
||||
.append('text')
|
||||
g.append('text')
|
||||
.attr('class', 'type2')
|
||||
.attr('x', p2_card_x)
|
||||
.attr('y', p2_card_y)
|
||||
@@ -323,8 +319,6 @@ const drawClass = function(elem, classDef) {
|
||||
isFirst = false;
|
||||
});
|
||||
|
||||
console.warn('classDef.id', classDef.id);
|
||||
console.warn('isFirst', isFirst);
|
||||
// add class title
|
||||
const classTitle = title
|
||||
.append('tspan')
|
||||
@@ -348,7 +342,6 @@ const drawClass = function(elem, classDef) {
|
||||
.attr('y', titleHeight + conf.dividerMargin + conf.textHeight)
|
||||
.attr('fill', 'white')
|
||||
.attr('class', 'classText');
|
||||
console.warn(classDef.id, titleHeight, conf.dividerMargin, conf.textHeight);
|
||||
|
||||
isFirst = true;
|
||||
classDef.members.forEach(function(member) {
|
||||
|
@@ -163,7 +163,7 @@ members
|
||||
methodStatement
|
||||
: className {/*console.log('Rel found',$1);*/}
|
||||
| className LABEL {yy.addMember($1,yy.cleanupLabel($2));}
|
||||
| MEMBER {console.warn('Member',$1);}
|
||||
| MEMBER {/*console.warn('Member',$1);*/}
|
||||
| SEPARATOR {/*console.log('sep found',$1);*/}
|
||||
;
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import dagreD3 from 'dagre-d3-renderer';
|
||||
import dagreD3 from 'dagre-d3';
|
||||
|
||||
function question(parent, bbox, node) {
|
||||
const w = bbox.width;
|
||||
|
@@ -223,7 +223,7 @@ const setClickFun = function(_id, functionName) {
|
||||
return;
|
||||
}
|
||||
if (typeof vertices[id] !== 'undefined') {
|
||||
funs.push(function(element) {
|
||||
funs.push(function() {
|
||||
const elem = document.querySelector(`[id="${id}"]`);
|
||||
if (elem !== null) {
|
||||
elem.addEventListener(
|
||||
@@ -395,7 +395,7 @@ export const addSubGraph = function(_id, list, _title) {
|
||||
return false;
|
||||
}
|
||||
if (type in prims) {
|
||||
return prims[type].hasOwnProperty(item) ? false : (prims[type][item] = true);
|
||||
return prims[type].hasOwnProperty(item) ? false : (prims[type][item] = true); // eslint-disable-line
|
||||
} else {
|
||||
return objs.indexOf(item) >= 0 ? false : objs.push(item);
|
||||
}
|
||||
|
@@ -1,11 +1,16 @@
|
||||
import graphlib from 'graphlibrary';
|
||||
import graphlib from 'graphlib';
|
||||
import * as d3 from 'd3';
|
||||
|
||||
import flowDb from './flowDb';
|
||||
import flow from './parser/flow';
|
||||
import { getConfig } from '../../config';
|
||||
import dagreD3 from 'dagre-d3-renderer';
|
||||
import addHtmlLabel from 'dagre-d3-renderer/lib/label/add-html-label.js';
|
||||
|
||||
const newDagreD3 = true;
|
||||
import dagreD3 from 'dagre-d3';
|
||||
// const newDagreD3 = false;
|
||||
// import dagreD3 from '../../../../dagre-d3-renderer/dist/dagre-d3.core.js';
|
||||
|
||||
import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js';
|
||||
import { logger } from '../../logger';
|
||||
import { interpolateToCurve } from '../../utils';
|
||||
import flowChartShapes from './flowChartShapes';
|
||||
@@ -291,18 +296,35 @@ export const draw = function(text, id) {
|
||||
}
|
||||
|
||||
// Create the input mermaid.graph
|
||||
const g = new graphlib.Graph({
|
||||
multigraph: true,
|
||||
compound: true
|
||||
})
|
||||
.setGraph({
|
||||
rankdir: dir,
|
||||
marginx: 20,
|
||||
marginy: 20
|
||||
let g;
|
||||
// Todo remove newDagreD3 when properly verified
|
||||
if (newDagreD3) {
|
||||
g = new graphlib.Graph({
|
||||
multigraph: true,
|
||||
compound: true
|
||||
})
|
||||
.setDefaultEdgeLabel(function() {
|
||||
return {};
|
||||
});
|
||||
.setGraph({
|
||||
rankdir: dir,
|
||||
marginx: 8,
|
||||
marginy: 8
|
||||
})
|
||||
.setDefaultEdgeLabel(function() {
|
||||
return {};
|
||||
});
|
||||
} else {
|
||||
g = new graphlib.Graph({
|
||||
multigraph: true,
|
||||
compound: true
|
||||
})
|
||||
.setGraph({
|
||||
rankdir: dir,
|
||||
marginx: 20,
|
||||
marginy: 20
|
||||
})
|
||||
.setDefaultEdgeLabel(function() {
|
||||
return {};
|
||||
});
|
||||
}
|
||||
|
||||
let subG;
|
||||
const subGraphs = flowDb.getSubGraphs();
|
||||
@@ -354,7 +376,7 @@ export const draw = function(text, id) {
|
||||
};
|
||||
|
||||
// Override normal arrowhead defined in d3. Remove style & add class to allow css styling.
|
||||
render.arrows().normal = function normal(parent, id, edge, type) {
|
||||
render.arrows().normal = function normal(parent, id) {
|
||||
const marker = parent
|
||||
.append('marker')
|
||||
.attr('id', id)
|
||||
@@ -386,22 +408,50 @@ export const draw = function(text, id) {
|
||||
});
|
||||
|
||||
const conf = getConfig().flowchart;
|
||||
|
||||
const padding = 8;
|
||||
const width = g.maxX - g.minX + padding * 2;
|
||||
const height = g.maxY - g.minY + padding * 2;
|
||||
// Todo remove newDagreD3 when properly verified
|
||||
if (newDagreD3) {
|
||||
const svgBounds = svg.node().getBBox();
|
||||
const width = svgBounds.width + padding * 2;
|
||||
const height = svgBounds.height + padding * 2;
|
||||
logger.debug(
|
||||
`new ViewBox 0 0 ${width} ${height}`,
|
||||
`translate(${padding - g._label.marginx}, ${padding - g._label.marginy})`
|
||||
);
|
||||
|
||||
if (conf.useMaxWidth) {
|
||||
svg.attr('width', '100%');
|
||||
svg.attr('style', `max-width: ${width}px;`);
|
||||
if (conf.useMaxWidth) {
|
||||
svg.attr('width', '100%');
|
||||
svg.attr('style', `max-width: ${width}px;`);
|
||||
} else {
|
||||
svg.attr('height', height);
|
||||
svg.attr('width', width);
|
||||
}
|
||||
|
||||
svg.attr('viewBox', `0 0 ${width} ${height}`);
|
||||
svg
|
||||
.select('g')
|
||||
.attr('transform', `translate(${padding - g._label.marginx}, ${padding - svgBounds.y})`);
|
||||
} else {
|
||||
svg.attr('height', height);
|
||||
svg.attr('width', width);
|
||||
const width = g.maxX - g.minX + padding * 2;
|
||||
const height = g.maxY - g.minY + padding * 2;
|
||||
|
||||
if (conf.useMaxWidth) {
|
||||
svg.attr('width', '100%');
|
||||
svg.attr('style', `max-width: ${width}px;`);
|
||||
} else {
|
||||
svg.attr('height', height);
|
||||
svg.attr('width', width);
|
||||
}
|
||||
|
||||
logger.debug(
|
||||
`Org ViewBox 0 0 ${width} ${height}`,
|
||||
`translate(${padding - g.minX}, ${padding - g.minY})\n${location.href}`
|
||||
);
|
||||
|
||||
svg.attr('viewBox', `0 0 ${width} ${height}`);
|
||||
svg.select('g').attr('transform', `translate(${padding - g.minX}, ${padding - g.minY})`);
|
||||
// svg.select('g').attr('transform', `translate(${padding - minX}, ${padding - minY})`);
|
||||
}
|
||||
|
||||
svg.attr('viewBox', `0 0 ${width} ${height}`);
|
||||
svg.select('g').attr('transform', `translate(${padding - g.minX}, ${padding - g.minY})`);
|
||||
|
||||
// Index nodes
|
||||
flowDb.indexNodes('subGraph' + i);
|
||||
|
||||
|
@@ -387,10 +387,11 @@ const compileTasks = function() {
|
||||
const task = rawTasks[pos];
|
||||
let startTime = '';
|
||||
switch (rawTasks[pos].raw.startTime.type) {
|
||||
case 'prevTaskEnd':
|
||||
case 'prevTaskEnd': {
|
||||
const prevTask = findTaskById(task.prevTaskId);
|
||||
task.startTime = prevTask.endTime;
|
||||
break;
|
||||
}
|
||||
case 'getStartDate':
|
||||
startTime = getStartDate(undefined, dateFormat, rawTasks[pos].raw.startTime.startData);
|
||||
if (startTime) {
|
||||
@@ -501,7 +502,7 @@ const setClickFun = function(id, functionName, functionArgs) {
|
||||
* @param callbackFunction A function to be executed when clicked on the task or the task's text
|
||||
*/
|
||||
const pushFun = function(id, callbackFunction) {
|
||||
funs.push(function(element) {
|
||||
funs.push(function() {
|
||||
// const elem = d3.select(element).select(`[id="${id}"]`)
|
||||
const elem = document.querySelector(`[id="${id}"]`);
|
||||
if (elem !== null) {
|
||||
@@ -510,7 +511,7 @@ const pushFun = function(id, callbackFunction) {
|
||||
});
|
||||
}
|
||||
});
|
||||
funs.push(function(element) {
|
||||
funs.push(function() {
|
||||
// const elem = d3.select(element).select(`[id="${id}-text"]`)
|
||||
const elem = document.querySelector(`[id="${id}-text"]`);
|
||||
if (elem !== null) {
|
||||
|
@@ -102,7 +102,7 @@ export const draw = function(text, id) {
|
||||
drawToday(leftPadding, topPadding, pageWidth, pageHeight);
|
||||
}
|
||||
|
||||
function drawRects(theArray, theGap, theTopPad, theSidePad, theBarHeight, theColorScale, w, h) {
|
||||
function drawRects(theArray, theGap, theTopPad, theSidePad, theBarHeight, theColorScale, w) {
|
||||
// Draw background rects covering the entire width of the graph, these form the section rows.
|
||||
svg
|
||||
.append('g')
|
||||
@@ -401,7 +401,7 @@ export const draw = function(text, id) {
|
||||
const hash = {};
|
||||
const result = [];
|
||||
for (let i = 0, l = arr.length; i < l; ++i) {
|
||||
if (!hash.hasOwnProperty(arr[i])) {
|
||||
if (!hash.hasOwnProperty(arr[i])) { // eslint-disable-line
|
||||
// it works with objects! in FF, at least
|
||||
hash[arr[i]] = true;
|
||||
result.push(arr[i]);
|
||||
|
@@ -21,7 +21,7 @@ export const setConf = function(cnf) {
|
||||
* @param id
|
||||
*/
|
||||
let w;
|
||||
export const draw = (txt, id, ver) => {
|
||||
export const draw = (txt, id) => {
|
||||
try {
|
||||
const parser = pieParser.parser;
|
||||
parser.yy = pieData;
|
||||
@@ -50,6 +50,8 @@ export const draw = (txt, id, ver) => {
|
||||
var width = w; // 450
|
||||
var height = 450;
|
||||
var margin = 40;
|
||||
var legendRectSize = 18;
|
||||
var legendSpacing = 4;
|
||||
|
||||
var radius = Math.min(width, height) / 2 - margin;
|
||||
|
||||
@@ -62,6 +64,10 @@ export const draw = (txt, id, ver) => {
|
||||
.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');
|
||||
|
||||
var data = pieData.getSections();
|
||||
var sum = 0;
|
||||
Object.keys(data).forEach(function(key) {
|
||||
sum += data[key];
|
||||
});
|
||||
logger.info(data);
|
||||
|
||||
// set the color scale
|
||||
@@ -75,7 +81,6 @@ export const draw = (txt, id, ver) => {
|
||||
return d.value;
|
||||
});
|
||||
var dataReady = pie(d3.entries(data));
|
||||
// Now I know that group A goes from 0 degrees to x degrees and so on.
|
||||
|
||||
// shape helper to build arcs:
|
||||
var arcGenerator = d3
|
||||
@@ -97,14 +102,14 @@ export const draw = (txt, id, ver) => {
|
||||
.style('stroke-width', '2px')
|
||||
.style('opacity', 0.7);
|
||||
|
||||
// Now add the annotation. Use the centroid method to get the best coordinates
|
||||
// Now add the Percentage. Use the centroid method to get the best coordinates
|
||||
svg
|
||||
.selectAll('mySlices')
|
||||
.data(dataReady)
|
||||
.enter()
|
||||
.append('text')
|
||||
.text(function(d) {
|
||||
return d.data.key;
|
||||
return ((d.data.value / sum) * 100).toFixed(0) + '%';
|
||||
})
|
||||
.attr('transform', function(d) {
|
||||
return 'translate(' + arcGenerator.centroid(d) + ')';
|
||||
@@ -119,6 +124,36 @@ export const draw = (txt, id, ver) => {
|
||||
.attr('x', 0)
|
||||
.attr('y', -(h - 50) / 2)
|
||||
.attr('class', 'pieTitleText');
|
||||
|
||||
//Add the slegend/annotations for each section
|
||||
var legend = svg
|
||||
.selectAll('.legend')
|
||||
.data(color.domain())
|
||||
.enter()
|
||||
.append('g')
|
||||
.attr('class', 'legend')
|
||||
.attr('transform', function(d, i) {
|
||||
var height = legendRectSize + legendSpacing;
|
||||
var offset = (height * color.domain().length) / 2;
|
||||
var horz = 12 * legendRectSize;
|
||||
var vert = i * height - offset;
|
||||
return 'translate(' + horz + ',' + vert + ')';
|
||||
});
|
||||
|
||||
legend
|
||||
.append('rect')
|
||||
.attr('width', legendRectSize)
|
||||
.attr('height', legendRectSize)
|
||||
.style('fill', color)
|
||||
.style('stroke', color);
|
||||
|
||||
legend
|
||||
.append('text')
|
||||
.attr('x', legendRectSize + legendSpacing)
|
||||
.attr('y', legendRectSize - legendSpacing)
|
||||
.text(function(d) {
|
||||
return d;
|
||||
});
|
||||
} catch (e) {
|
||||
logger.error('Error while rendering info diagram');
|
||||
logger.error(e.message);
|
||||
|
@@ -514,11 +514,12 @@ export const draw = function(text, id) {
|
||||
bounds.newLoop(undefined, msg.message);
|
||||
bounds.bumpVerticalPos(conf.boxMargin);
|
||||
break;
|
||||
case parser.yy.LINETYPE.RECT_END:
|
||||
case parser.yy.LINETYPE.RECT_END: {
|
||||
const rectData = bounds.endLoop();
|
||||
svgDraw.drawBackgroundRect(diagram, rectData);
|
||||
bounds.bumpVerticalPos(conf.boxMargin);
|
||||
break;
|
||||
}
|
||||
case parser.yy.LINETYPE.OPT_START:
|
||||
bounds.bumpVerticalPos(conf.boxMargin);
|
||||
bounds.newLoop(msg.message);
|
||||
|
@@ -16,7 +16,7 @@ export const drawRect = function(elem, rectData) {
|
||||
return rectElem;
|
||||
};
|
||||
|
||||
export const drawText = function(elem, textData, width) {
|
||||
export const drawText = function(elem, textData) {
|
||||
// Remove and ignore br:s
|
||||
const nText = textData.text.replace(/<br\/?>/gi, ' ');
|
||||
|
||||
@@ -374,7 +374,7 @@ const _drawTextCandidateFunc = (function() {
|
||||
|
||||
function _setTextAttrs(toText, fromTextAttrsDict) {
|
||||
for (const key in fromTextAttrsDict) {
|
||||
if (fromTextAttrsDict.hasOwnProperty(key)) {
|
||||
if (fromTextAttrsDict.hasOwnProperty(key)) { // eslint-disable-line
|
||||
toText.attr(key, fromTextAttrsDict[key]);
|
||||
}
|
||||
}
|
||||
|
@@ -43,10 +43,10 @@
|
||||
<SCALE>\s+"width" {this.popState();}
|
||||
|
||||
<INITIAL,struct>"state"\s+ { this.pushState('STATE'); }
|
||||
<STATE>.*"<<fork>>" {this.popState();yytext=yytext.slice(0,-8).trim(); console.warn('Fork Fork: ',yytext);return 'FORK';}
|
||||
<STATE>.*"<<join>>" {this.popState();yytext=yytext.slice(0,-8).trim();console.warn('Fork Join: ',yytext);return 'JOIN';}
|
||||
<STATE>.*"[[fork]]" {this.popState();yytext=yytext.slice(0,-8).trim();console.warn('Fork Fork: ',yytext);return 'FORK';}
|
||||
<STATE>.*"[[join]]" {this.popState();yytext=yytext.slice(0,-8).trim();console.warn('Fork Join: ',yytext);return 'JOIN';}
|
||||
<STATE>.*"<<fork>>" {this.popState();yytext=yytext.slice(0,-8).trim(); /*console.warn('Fork Fork: ',yytext);*/return 'FORK';}
|
||||
<STATE>.*"<<join>>" {this.popState();yytext=yytext.slice(0,-8).trim();/*console.warn('Fork Join: ',yytext);*/return 'JOIN';}
|
||||
<STATE>.*"[[fork]]" {this.popState();yytext=yytext.slice(0,-8).trim();/*console.warn('Fork Fork: ',yytext);*/return 'FORK';}
|
||||
<STATE>.*"[[join]]" {this.popState();yytext=yytext.slice(0,-8).trim();/*console.warn('Fork Join: ',yytext);*/return 'JOIN';}
|
||||
<STATE>["] this.begin("STATE_STRING");
|
||||
<STATE>"as"\s* {this.popState();this.pushState('STATE_ID');return "AS";}
|
||||
<STATE_ID>[^\n\{]* {this.popState();/* console.log('STATE_ID', yytext);*/return "ID";}
|
||||
@@ -133,7 +133,17 @@ statement
|
||||
/* console.warn('Adding document for state without id ', $1);*/
|
||||
$$={ stmt: 'state', id: $1, type: 'default', description: '', doc: $3 }
|
||||
}
|
||||
| STATE_DESCR AS ID { $$={stmt: 'state', id: $3, type: 'default', description: $1.trim()};}
|
||||
| STATE_DESCR AS ID {
|
||||
var id=$3;
|
||||
var description = $1.trim();
|
||||
if($3.match(':')){
|
||||
var parts = $3.split(':');
|
||||
id=parts[0];
|
||||
description = [description, parts[1]];
|
||||
}
|
||||
$$={stmt: 'state', id: id, type: 'default', description: description};
|
||||
|
||||
}
|
||||
| STATE_DESCR AS ID STRUCT_START document STRUCT_STOP
|
||||
{
|
||||
//console.warn('Adding document for state with id ', $3, $4); yy.addDocument($3);
|
||||
|
@@ -2,7 +2,7 @@ import * as d3 from 'd3';
|
||||
import idCache from './id-cache.js';
|
||||
import stateDb from './stateDb';
|
||||
import utils from '../../utils';
|
||||
import { getConfig, conf } from '../../config';
|
||||
import { getConfig } from '../../config';
|
||||
|
||||
// let conf;
|
||||
|
||||
@@ -76,7 +76,7 @@ export const drawDescrState = (g, stateDef) => {
|
||||
.attr('y', getConfig().state.textHeight + 1.5 * getConfig().state.padding)
|
||||
.attr('font-size', getConfig().state.fontSize)
|
||||
.attr('class', 'state-title')
|
||||
.text(stateDef.id);
|
||||
.text(stateDef.descriptions[0]);
|
||||
|
||||
const titleBox = title.node().getBBox();
|
||||
const titleHeight = titleBox.height;
|
||||
@@ -94,8 +94,12 @@ export const drawDescrState = (g, stateDef) => {
|
||||
.attr('class', 'state-description');
|
||||
|
||||
let isFirst = true;
|
||||
let isSecond = true;
|
||||
stateDef.descriptions.forEach(function(descr) {
|
||||
addTspan(description, descr, isFirst);
|
||||
if (!isFirst) {
|
||||
addTspan(description, descr, isSecond);
|
||||
isSecond = false;
|
||||
}
|
||||
isFirst = false;
|
||||
});
|
||||
|
||||
@@ -106,7 +110,6 @@ export const drawDescrState = (g, stateDef) => {
|
||||
.attr('y2', getConfig().state.padding + titleHeight + getConfig().state.dividerMargin / 2)
|
||||
.attr('class', 'descr-divider');
|
||||
const descrBox = description.node().getBBox();
|
||||
console.warn(descrBox.width, titleBox.width);
|
||||
const width = Math.max(descrBox.width, titleBox.width);
|
||||
|
||||
descrLine.attr('x2', width + 3 * getConfig().state.padding);
|
||||
@@ -128,15 +131,15 @@ export const drawDescrState = (g, stateDef) => {
|
||||
*/
|
||||
export const addIdAndBox = (g, stateDef) => {
|
||||
// TODO Move hardcodings to conf
|
||||
const addTspan = function(textEl, txt, isFirst) {
|
||||
const tSpan = textEl
|
||||
.append('tspan')
|
||||
.attr('x', 2 * getConfig().state.padding)
|
||||
.text(txt);
|
||||
if (!isFirst) {
|
||||
tSpan.attr('dy', getConfig().state.textHeight);
|
||||
}
|
||||
};
|
||||
// const addTspan = function(textEl, txt, isFirst) {
|
||||
// const tSpan = textEl
|
||||
// .append('tspan')
|
||||
// .attr('x', 2 * getConfig().state.padding)
|
||||
// .text(txt);
|
||||
// if (!isFirst) {
|
||||
// tSpan.attr('dy', getConfig().state.textHeight);
|
||||
// }
|
||||
// };
|
||||
const title = g
|
||||
.append('text')
|
||||
.attr('x', 2 * getConfig().state.padding)
|
||||
@@ -145,7 +148,7 @@ export const addIdAndBox = (g, stateDef) => {
|
||||
.attr('class', 'state-title')
|
||||
.text(stateDef.id);
|
||||
|
||||
const titleHeight = title.node().getBBox().height;
|
||||
const titleBox = title.node().getBBox();
|
||||
|
||||
const lineY = 1 - getConfig().state.textHeight;
|
||||
const descrLine = g
|
||||
@@ -156,7 +159,7 @@ export const addIdAndBox = (g, stateDef) => {
|
||||
.attr('class', 'descr-divider');
|
||||
|
||||
const graphBox = g.node().getBBox();
|
||||
title.attr('x', graphBox.width / 2 - title.node().getBBox().width / 2);
|
||||
title.attr('x', graphBox.width / 2 - titleBox.width / 2);
|
||||
descrLine.attr('x2', graphBox.width + getConfig().state.padding);
|
||||
|
||||
// White color
|
||||
@@ -238,7 +241,7 @@ const drawForkJoinState = (g, stateDef) => {
|
||||
.attr('y', getConfig().state.padding);
|
||||
};
|
||||
|
||||
export const drawText = function(elem, textData, width) {
|
||||
export const drawText = function(elem, textData) {
|
||||
// Remove and ignore br:s
|
||||
const nText = textData.text.replace(/<br\/?>/gi, ' ');
|
||||
|
||||
@@ -261,7 +264,7 @@ export const drawText = function(elem, textData, width) {
|
||||
|
||||
const _drawLongText = (_text, x, y, g) => {
|
||||
let textHeight = 0;
|
||||
let textWidth = 0;
|
||||
|
||||
const textElem = g.append('text');
|
||||
textElem.style('text-anchor', 'start');
|
||||
textElem.attr('class', 'noteText');
|
||||
@@ -269,17 +272,22 @@ const _drawLongText = (_text, x, y, g) => {
|
||||
let text = _text.replace(/\r\n/g, '<br/>');
|
||||
text = text.replace(/\n/g, '<br/>');
|
||||
const lines = text.split(/<br\/?>/gi);
|
||||
|
||||
let tHeight = 1.25 * getConfig().state.noteMargin;
|
||||
for (const line of lines) {
|
||||
const txt = line.trim();
|
||||
|
||||
if (txt.length > 0) {
|
||||
const span = textElem.append('tspan');
|
||||
span.text(txt);
|
||||
const textBounds = span.node().getBBox();
|
||||
textHeight += textBounds.height;
|
||||
if (tHeight === 0) {
|
||||
const textBounds = span.node().getBBox();
|
||||
tHeight += textBounds.height;
|
||||
}
|
||||
// console.warn('textBounds', textBounds);
|
||||
textHeight += tHeight;
|
||||
span.attr('x', x + getConfig().state.noteMargin);
|
||||
span.attr('y', y + textHeight + 1.25 * getConfig().state.noteMargin);
|
||||
// textWidth = Math.max(textBounds.width, textWidth);
|
||||
}
|
||||
}
|
||||
return { textWidth: textElem.node().getBBox().width, textHeight };
|
||||
@@ -314,8 +322,7 @@ export const drawNote = (text, g) => {
|
||||
* @param {*} stateDef
|
||||
*/
|
||||
|
||||
let cnt = 0;
|
||||
export const drawState = function(elem, stateDef, graph, doc) {
|
||||
export const drawState = function(elem, stateDef) {
|
||||
const id = stateDef.id;
|
||||
const stateInfo = {
|
||||
id: id,
|
||||
@@ -347,6 +354,12 @@ export const drawState = function(elem, stateDef, graph, doc) {
|
||||
return stateInfo;
|
||||
};
|
||||
|
||||
const getRows = s => {
|
||||
let str = s.replace(/<br\/?>/gi, '#br#');
|
||||
str = str.replace(/\\n/g, '#br#');
|
||||
return str.split('#br#');
|
||||
};
|
||||
|
||||
let edgeCount = 0;
|
||||
export const drawEdge = function(elem, path, relation) {
|
||||
const getRelationType = function(type) {
|
||||
@@ -401,20 +414,48 @@ export const drawEdge = function(elem, path, relation) {
|
||||
);
|
||||
|
||||
if (typeof relation.title !== 'undefined') {
|
||||
const g = elem.append('g').attr('class', 'stateLabel');
|
||||
const label = g
|
||||
.append('text')
|
||||
.attr('text-anchor', 'middle')
|
||||
.text(relation.title);
|
||||
const label = elem.append('g').attr('class', 'stateLabel');
|
||||
|
||||
const { x, y } = utils.calcLabelPosition(path.points);
|
||||
label.attr('x', x).attr('y', y);
|
||||
|
||||
const rows = getRows(relation.title);
|
||||
|
||||
// console.warn(rows);
|
||||
|
||||
let titleHeight = 0;
|
||||
const titleRows = [];
|
||||
for (let i = 0; i <= rows.length; i++) {
|
||||
const title = label
|
||||
.append('text')
|
||||
.attr('text-anchor', 'middle')
|
||||
.text(rows[i])
|
||||
.attr('x', x)
|
||||
.attr('y', y + titleHeight);
|
||||
|
||||
if (titleHeight === 0) {
|
||||
const titleBox = title.node().getBBox();
|
||||
titleHeight = titleBox.height;
|
||||
}
|
||||
titleRows.push(title);
|
||||
}
|
||||
|
||||
if (rows.length > 1) {
|
||||
const heightAdj = rows.length * titleHeight * 0.25;
|
||||
|
||||
titleRows.forEach((title, i) => title.attr('y', y + i * titleHeight - heightAdj));
|
||||
}
|
||||
|
||||
const bounds = label.node().getBBox();
|
||||
g.insert('rect', ':first-child')
|
||||
label
|
||||
.insert('rect', ':first-child')
|
||||
.attr('class', 'box')
|
||||
.attr('x', bounds.x - getConfig().state.padding / 2)
|
||||
.attr('y', bounds.y - getConfig().state.padding / 2)
|
||||
.attr('width', bounds.width + getConfig().state.padding)
|
||||
.attr('height', bounds.height + getConfig().state.padding);
|
||||
|
||||
//label.attr('transform', '0 -' + (bounds.y / 2));
|
||||
|
||||
// Debug points
|
||||
// path.points.forEach(point => {
|
||||
// g.append('circle')
|
||||
|
@@ -9,7 +9,7 @@ const setRootDoc = o => {
|
||||
const getRootDoc = () => rootDoc;
|
||||
|
||||
const extract = doc => {
|
||||
const res = { states: [], relations: [] };
|
||||
// const res = { states: [], relations: [] };
|
||||
clear();
|
||||
|
||||
doc.forEach(item => {
|
||||
@@ -37,8 +37,8 @@ let documents = {
|
||||
let currentDocument = documents.root;
|
||||
|
||||
let startCnt = 0;
|
||||
let endCnt = 0;
|
||||
let stateCnt = 0;
|
||||
let endCnt = 0; // eslint-disable-line
|
||||
// let stateCnt = 0;
|
||||
|
||||
/**
|
||||
* Function called by parser when a node definition has been found.
|
||||
@@ -64,7 +64,14 @@ export const addState = function(id, type, doc, descr, note) {
|
||||
currentDocument.states[id].type = type;
|
||||
}
|
||||
}
|
||||
if (descr) addDescription(id, descr.trim());
|
||||
if (descr) {
|
||||
if (typeof descr === 'string') addDescription(id, descr.trim());
|
||||
|
||||
if (typeof descr === 'object') {
|
||||
descr.forEach(des => addDescription(id, des.trim()));
|
||||
}
|
||||
}
|
||||
|
||||
if (note) currentDocument.states[id].note = note;
|
||||
};
|
||||
|
||||
|
@@ -1,18 +1,15 @@
|
||||
import * as d3 from 'd3';
|
||||
import dagre from 'dagre-layout';
|
||||
import graphlib from 'graphlibrary';
|
||||
import dagre from 'dagre';
|
||||
import graphlib from 'graphlib';
|
||||
import { logger } from '../../logger';
|
||||
import stateDb from './stateDb';
|
||||
import { parser } from './parser/stateDiagram';
|
||||
import utils from '../../utils';
|
||||
import idCache from './id-cache';
|
||||
import { drawState, addIdAndBox, drawEdge, drawNote } from './shapes';
|
||||
// import idCache from './id-cache';
|
||||
import { drawState, addIdAndBox, drawEdge } from './shapes';
|
||||
import { getConfig } from '../../config';
|
||||
|
||||
parser.yy = stateDb;
|
||||
|
||||
let total = 0;
|
||||
|
||||
// TODO Move conf object to main conf in mermaidAPI
|
||||
let conf;
|
||||
// {
|
||||
@@ -28,20 +25,20 @@ let conf;
|
||||
|
||||
const transformationLog = {};
|
||||
|
||||
export const setConf = function(cnf) {};
|
||||
export const setConf = function() {};
|
||||
|
||||
// Todo optimize
|
||||
const getGraphId = function(label) {
|
||||
const keys = idCache.keys();
|
||||
// const getGraphId = function(label) {
|
||||
// const keys = idCache.keys();
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
if (idCache.get(keys[i]).label === label) {
|
||||
return keys[i];
|
||||
}
|
||||
}
|
||||
// for (let i = 0; i < keys.length; i++) {
|
||||
// if (idCache.get(keys[i]).label === label) {
|
||||
// return keys[i];
|
||||
// }
|
||||
// }
|
||||
|
||||
return undefined;
|
||||
};
|
||||
// return undefined;
|
||||
// };
|
||||
|
||||
/**
|
||||
* Setup arrow head and define the marker. The result is appended to the svg.
|
||||
@@ -90,24 +87,49 @@ export const draw = function(text, id) {
|
||||
});
|
||||
|
||||
const rootDoc = stateDb.getRootDoc();
|
||||
const n = renderDoc(rootDoc, diagram);
|
||||
renderDoc(rootDoc, diagram);
|
||||
|
||||
const padding = conf.padding;
|
||||
const bounds = diagram.node().getBBox();
|
||||
|
||||
diagram.attr('height', '100%');
|
||||
diagram.attr('style', `width: ${bounds.width * 3 + conf.padding * 2};`);
|
||||
console.warn(bounds);
|
||||
|
||||
const width = bounds.width + padding * 2;
|
||||
const height = bounds.height + padding * 2;
|
||||
|
||||
// diagram.attr('height', '100%');
|
||||
// diagram.attr('style', `width: ${bounds.width * 3 + conf.padding * 2};`);
|
||||
// diagram.attr('height', height);
|
||||
|
||||
// Zoom in a bit
|
||||
diagram.attr('width', width * 2);
|
||||
// diagram.attr('height', bounds.height * 3 + conf.padding * 2);
|
||||
diagram.attr(
|
||||
'viewBox',
|
||||
`${conf.padding * -1} ${conf.padding * -1} ` +
|
||||
(bounds.width * 1.5 + conf.padding * 2) +
|
||||
' ' +
|
||||
(bounds.height + conf.padding * 5)
|
||||
`${bounds.x - conf.padding} ${bounds.y - conf.padding} ` + width + ' ' + height
|
||||
);
|
||||
// diagram.attr('transform', `translate(, 0)`);
|
||||
|
||||
// diagram.attr(
|
||||
// 'viewBox',
|
||||
// `${conf.padding * -1} ${conf.padding * -1} ` +
|
||||
// (bounds.width * 1.5 + conf.padding * 2) +
|
||||
// ' ' +
|
||||
// (bounds.height + conf.padding * 5)
|
||||
// );
|
||||
};
|
||||
const getLabelWidth = text => {
|
||||
return text ? text.length * conf.fontSizeFactor : 1;
|
||||
};
|
||||
|
||||
/* TODO: REMOVE DUPLICATION, SEE SHAPES */
|
||||
const getRows = s => {
|
||||
if (!s) return 1;
|
||||
let str = s.replace(/<br\/?>/gi, '#br#');
|
||||
str = str.replace(/\\n/g, '#br#');
|
||||
return str.split('#br#');
|
||||
};
|
||||
|
||||
const renderDoc = (doc, diagram, parentId) => {
|
||||
// // Layout graph, Create a new directed graph
|
||||
const graph = new graphlib.Graph({
|
||||
@@ -121,7 +143,6 @@ const renderDoc = (doc, diagram, parentId) => {
|
||||
// multigraph: false,
|
||||
compound: true,
|
||||
// acyclicer: 'greedy',
|
||||
rankdir: 'LR',
|
||||
ranker: 'tight-tree',
|
||||
ranksep: conf.edgeLengthFactor
|
||||
// isMultiGraph: false
|
||||
@@ -151,7 +172,6 @@ const renderDoc = (doc, diagram, parentId) => {
|
||||
|
||||
const keys = Object.keys(states);
|
||||
|
||||
total = keys.length;
|
||||
let first = true;
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
@@ -221,7 +241,7 @@ const renderDoc = (doc, diagram, parentId) => {
|
||||
graph.setEdge(relation.id1, relation.id2, {
|
||||
relation: relation,
|
||||
width: getLabelWidth(relation.title),
|
||||
height: conf.labelHeight,
|
||||
height: conf.labelHeight * getRows(relation.title).length,
|
||||
labelpos: 'c'
|
||||
});
|
||||
});
|
||||
@@ -278,7 +298,7 @@ const renderDoc = (doc, diagram, parentId) => {
|
||||
});
|
||||
|
||||
stateBox = svgElem.getBBox();
|
||||
console.warn('Diagram node', svgElem.id);
|
||||
|
||||
const stateInfo = {
|
||||
id: parentId ? parentId : 'root',
|
||||
label: parentId ? parentId : 'root',
|
||||
|
Reference in New Issue
Block a user