Merge branch 'develop' of https://github.com/mermaid-js/mermaid into mermaid-js-develop

This commit is contained in:
Chris Moran
2020-06-14 11:40:15 -04:00
23 changed files with 1057 additions and 2138 deletions

View File

@@ -217,7 +217,7 @@ const setClickFunc = function(domId, functionName, tooltip) {
elem.addEventListener(
'click',
function() {
window[functionName](elemId);
utils.runFunc(functionName, elemId);
},
false
);
@@ -272,8 +272,8 @@ const setupToolTips = function(element) {
.style('opacity', '.9');
tooltipElem
.html(el.attr('title'))
.style('left', rect.left + (rect.right - rect.left) / 2 + 'px')
.style('top', rect.top - 14 + document.body.scrollTop + 'px');
.style('left', window.scrollX + rect.left + (rect.right - rect.left) / 2 + 'px')
.style('top', window.scrollY + rect.top - 14 + document.body.scrollTop + 'px');
el.classed('hover', true);
})
.on('mouseout', function() {

View File

@@ -10,15 +10,15 @@
%%
\%\%[^\n]*\n* /* do nothing */
\n+ return 'NEWLINE';
\n+ return 'NEWLINE';
\s+ /* skip whitespace */
"classDiagram" return 'CLASS_DIAGRAM';
[\{] { this.begin("struct"); /*console.log('Starting struct');*/return 'STRUCT_START';}
<struct><<EOF>> return "EOF_IN_STRUCT";
<struct>[\{] return "OPEN_IN_STRUCT";
<struct>\} { /*console.log('Ending struct');*/this.popState(); return 'STRUCT_STOP';}}
<struct>\} { /*console.log('Ending struct');*/this.popState(); return 'STRUCT_STOP';}}
<struct>[\n] /* nothing */
<struct>[^\{\}\n]* { /*console.log('lex-member: ' + yytext);*/ return "MEMBER";}
<struct>[^\{\}\n]* { /*console.log('lex-member: ' + yytext);*/ return "MEMBER";}
@@ -40,7 +40,7 @@
\s*\|\> return 'EXTENSION';
\s*\> return 'DEPENDENCY';
\s*\< return 'DEPENDENCY';
\s*\* return 'COMPOSITION';
\s*\* return 'COMPOSITION';
\s*o return 'AGGREGATION';
\-\- return 'LINE';
\.\. return 'DOTTED_LINE';
@@ -53,7 +53,7 @@
\= return 'EQUALS';
\w+ return 'ALPHA';
[!"#$%&'*+,-.`?\\/] return 'PUNCTUATION';
[0-9]+ return 'NUM';
[0-9]+ return 'NUM';
[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|
[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|
[\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]|

View File

@@ -278,13 +278,13 @@ export const drawClass = function(elem, classDef, conf) {
};
export const parseMember = function(text) {
const fieldRegEx = /^(\+|-|~|#)?(\w+)(~\w+~|\[\])?\s+(\w+)$/;
const methodRegEx = /^(\+|-|~|#)?(\w+)\s?\(\s*(\w+(~\w+~|\[\])?\s*(\w+)?)?\s*\)\s?([*|$])?\s?(\w+(~\w+~|\[\])?)?\s*$/;
const fieldRegEx = /(\+|-|~|#)?(\w+)(~\w+~|\[\])?\s+(\w+)/;
const methodRegEx = /^([+|\-|~|#])?(\w+) *\( *(.*)\) *(\*|\$)? *(\w*[~|[\]]*\s*\w*~?)$/;
let fieldMatch = text.match(fieldRegEx);
let methodMatch = text.match(methodRegEx);
if (fieldMatch) {
if (fieldMatch && !methodMatch) {
return buildFieldDisplay(fieldMatch);
} else if (methodMatch) {
return buildMethodDisplay(methodMatch);
@@ -294,56 +294,78 @@ export const parseMember = function(text) {
};
const buildFieldDisplay = function(parsedText) {
let visibility = parsedText[1] ? parsedText[1].trim() : '';
let fieldType = parsedText[2] ? parsedText[2].trim() : '';
let genericType = parsedText[3] ? parseGenericTypes(parsedText[3]) : '';
let fieldName = parsedText[4] ? parsedText[4].trim() : '';
let displayText = '';
try {
let visibility = parsedText[1] ? parsedText[1].trim() : '';
let fieldType = parsedText[2] ? parsedText[2].trim() : '';
let genericType = parsedText[3] ? parseGenericTypes(parsedText[3].trim()) : '';
let fieldName = parsedText[4] ? parsedText[4].trim() : '';
displayText = visibility + fieldType + genericType + ' ' + fieldName;
} catch (err) {
displayText = parsedText;
}
return {
displayText: visibility + fieldType + genericType + ' ' + fieldName,
displayText: displayText,
cssStyle: ''
};
};
const buildMethodDisplay = function(parsedText) {
let cssStyle = '';
let displayText = parsedText;
let displayText = '';
let visibility = parsedText[1] ? parsedText[1].trim() : '';
let methodName = parsedText[2] ? parsedText[2].trim() : '';
let parameters = parsedText[3] ? parseGenericTypes(parsedText[3]) : '';
let classifier = parsedText[6] ? parsedText[6].trim() : '';
let returnType = parsedText[7] ? ' : ' + parseGenericTypes(parsedText[7]).trim() : '';
try {
let visibility = parsedText[1] ? parsedText[1].trim() : '';
let methodName = parsedText[2] ? parsedText[2].trim() : '';
let parameters = parsedText[3] ? parseGenericTypes(parsedText[3].trim()) : '';
let classifier = parsedText[4] ? parsedText[4].trim() : '';
let returnType = parsedText[5] ? ' : ' + parseGenericTypes(parsedText[5]).trim() : '';
displayText = visibility + methodName + '(' + parameters + ')' + returnType;
displayText = visibility + methodName + '(' + parameters + ')' + returnType;
cssStyle = parseClassifier(classifier);
cssStyle = parseClassifier(classifier);
} catch (err) {
displayText = parsedText;
}
let member = {
return {
displayText: displayText,
cssStyle: cssStyle
};
return member;
};
const buildLegacyDisplay = function(text) {
// if for some reason we dont have any match, use old format to parse text
let memberText = '';
let displayText = '';
let cssStyle = '';
let memberText = '';
let returnType = '';
let methodStart = text.indexOf('(');
let methodEnd = text.indexOf(')');
if (methodStart > 1 && methodEnd > methodStart && methodEnd <= text.length) {
let parsedText = text.match(/(\+|-|~|#)?(\w+)/);
let visibility = parsedText[1] ? parsedText[1].trim() : '';
let methodName = parsedText[2];
let visibility = '';
let methodName = '';
let firstChar = text.substring(0, 1);
if (firstChar.match(/\w/)) {
methodName = text.substring(0, methodStart).trim();
} else {
if (firstChar.match(/\+|-|~|#/)) {
visibility = firstChar;
}
methodName = text.substring(1, methodStart).trim();
}
let parameters = text.substring(methodStart + 1, methodEnd);
let classifier = text.substring(methodEnd, methodEnd + 1);
let classifier = text.substring(methodEnd + 1, 1);
cssStyle = parseClassifier(classifier);
memberText = visibility + methodName + '(' + parseGenericTypes(parameters.trim()) + ')';
displayText = visibility + methodName + '(' + parseGenericTypes(parameters.trim()) + ')';
if (methodEnd < memberText.length) {
returnType = text.substring(methodEnd + 2).trim();
@@ -353,15 +375,13 @@ const buildLegacyDisplay = function(text) {
}
} else {
// finally - if all else fails, just send the text back as written (other than parsing for generic types)
memberText = parseGenericTypes(text);
displayText = parseGenericTypes(text);
}
let member = {
displayText: memberText + returnType,
return {
displayText: displayText,
cssStyle: cssStyle
};
return member;
};
const addTspan = function(textEl, txt, isFirst, conf) {

View File

@@ -83,6 +83,14 @@ describe('class member Renderer, ', function () {
expect(actual.cssStyle).toBe('');
});
it('should handle simple method declaration with multiple parameters', function () {
const str = 'foo(int id, object thing)';
let actual = svgDraw.parseMember(str);
expect(actual.displayText).toBe('foo(int id, object thing)');
expect(actual.cssStyle).toBe('');
});
it('should handle simple method declaration with single item in parameters', function () {
const str = 'foo(id)';
let actual = svgDraw.parseMember(str);

View File

@@ -232,7 +232,7 @@ const setClickFun = function(_id, functionName) {
elem.addEventListener(
'click',
function() {
window[functionName](id);
utils.runFunc(functionName, id);
},
false
);
@@ -324,6 +324,7 @@ const setupToolTips = function(element) {
.on('mouseover', function() {
const el = select(this);
const title = el.attr('title');
// Dont try to draw a tooltip if no data is provided
if (title === null) {
return;
@@ -336,8 +337,8 @@ const setupToolTips = function(element) {
.style('opacity', '.9');
tooltipElem
.html(el.attr('title'))
.style('left', rect.left + (rect.right - rect.left) / 2 + 'px')
.style('top', rect.top - 14 + document.body.scrollTop + 'px');
.style('left', window.scrollX + rect.left + (rect.right - rect.left) / 2 + 'px')
.style('top', window.scrollY + rect.top - 14 + document.body.scrollTop + 'px');
el.classed('hover', true);
})
.on('mouseout', function() {

View File

@@ -181,8 +181,15 @@ export const addEdges = function(edges, g) {
edges.forEach(function(edge) {
cnt++;
// Identify Link
var linkId = 'L-' + edge.start + '-' + edge.end;
var linkNameStart = 'LS-' + edge.start;
var linkNameEnd = 'LE-' + edge.end;
const edgeData = {};
edgeData.id = 'id' + cnt;
//edgeData.id = 'id' + cnt;
// Set link type for rendering
if (edge.type === 'arrow_open') {
edgeData.arrowhead = 'none';
@@ -210,12 +217,16 @@ export const addEdges = function(edges, g) {
if (typeof defaultLabelStyle !== 'undefined') {
labelStyle = defaultLabelStyle;
}
edgeData.thickness = 'normal';
edgeData.pattern = 'solid';
break;
case 'dotted':
style = 'fill:none;stroke-width:2px;stroke-dasharray:3;';
edgeData.thickness = 'normal';
edgeData.pattern = 'dotted';
break;
case 'thick':
style = ' stroke-width: 3.5px;fill:none';
edgeData.thickness = 'thick';
edgeData.pattern = 'solid';
break;
}
}
@@ -241,7 +252,7 @@ export const addEdges = function(edges, g) {
if (getConfig().flowchart.htmlLabels && false) { // eslint-disable-line
edgeData.labelType = 'html';
edgeData.label = '<span class="edgeLabel">' + edge.text + '</span>';
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');
@@ -253,6 +264,10 @@ export const addEdges = function(edges, g) {
edgeData.labelStyle = edgeData.labelStyle.replace('color:', 'fill:');
}
}
edgeData.id = linkId;
edgeData.classes = 'flowchart-link ' + linkNameStart + ' ' + linkNameEnd;
// Add the edge to the graph
g.setEdge(edge.start, edge.end, edgeData, cnt);
});

View File

@@ -166,6 +166,12 @@ export const addEdges = function(edges, g) {
edges.forEach(function(edge) {
cnt++;
// Identify Link
var linkId = 'L-' + edge.start + '-' + edge.end;
var linkNameStart = 'LS-' + edge.start;
var linkNameEnd = 'LE-' + edge.end;
const edgeData = {};
// Set link type for rendering
@@ -223,7 +229,7 @@ export const addEdges = function(edges, g) {
if (getConfig().flowchart.htmlLabels) {
edgeData.labelType = 'html';
edgeData.label = '<span class="edgeLabel">' + edge.text + '</span>';
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');
@@ -235,6 +241,10 @@ export const addEdges = function(edges, g) {
edgeData.labelStyle = edgeData.labelStyle.replace('color:', 'fill:');
}
}
edgeData.id = linkId;
edgeData.class = linkNameStart + ' ' + linkNameEnd;
// Add the edge to the graph
g.setEdge(edge.start, edge.end, edgeData, cnt);
});

View File

@@ -2,6 +2,7 @@ import moment from 'moment-mini';
import { sanitizeUrl } from '@braintree/sanitize-url';
import { logger } from '../../logger';
import { getConfig } from '../../config';
import utils from '../../utils';
const config = getConfig();
let dateFormat = '';
@@ -520,7 +521,7 @@ const setClickFun = function(id, functionName, functionArgs) {
let rawTask = findTaskById(id);
if (typeof rawTask !== 'undefined') {
pushFun(id, () => {
window[functionName](...argList);
utils.runFunc(functionName, ...argList);
});
}
};

View File

@@ -145,10 +145,11 @@ const setupNode = (g, parent, node, altFlag) => {
arrowType: '',
style: 'fill:none',
labelStyle: '',
classes: 'note-edge',
classes: 'transition note-edge',
arrowheadStyle: 'fill: #333',
labelpos: 'c',
labelType: 'text'
labelType: 'text',
thickness: 'normal'
});
} else {
g.setNode(node.id, nodeData);
@@ -184,7 +185,9 @@ const setupDoc = (g, parent, doc, altFlag) => {
label: item.description,
arrowheadStyle: 'fill: #333',
labelpos: 'c',
labelType: 'text'
labelType: 'text',
thickness: 'normal',
classes: 'transition'
};
let startId = item.state1.id;
let endId = item.state2.id;