mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-11-19 04:04:28 +01:00
Merge branch 'develop' into 1179-SupportGenericTypesForMembers
This commit is contained in:
@@ -502,8 +502,8 @@ export const draw = function(text, id) {
|
||||
}
|
||||
});
|
||||
|
||||
diagram.attr('height', '100%');
|
||||
diagram.attr('width', `${g.graph().width * 1.5 + 20}`);
|
||||
diagram.attr('height', g.graph().height + 40);
|
||||
diagram.attr('width', g.graph().width * 1.5 + 20);
|
||||
diagram.attr('viewBox', '-10 -10 ' + (g.graph().width + 20) + ' ' + (g.graph().height + 20));
|
||||
};
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ export const addVertices = function(vert, g, svgId) {
|
||||
vertexNode.parentNode.removeChild(vertexNode);
|
||||
} else {
|
||||
const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
svgLabel.setAttribute('style', labelStyle.replace('color:', 'fill:'));
|
||||
|
||||
const rows = vertexText.split(/<br\s*\/?>/gi);
|
||||
|
||||
|
||||
29
src/diagrams/flowchart/parser/flow-huge.spec.js
Normal file
29
src/diagrams/flowchart/parser/flow-huge.spec.js
Normal file
File diff suppressed because one or more lines are too long
@@ -48,7 +48,7 @@
|
||||
<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>\s*"as"\s+ {this.popState();this.pushState('STATE_ID');return "AS";}
|
||||
<STATE_ID>[^\n\{]* {this.popState();/* console.log('STATE_ID', yytext);*/return "ID";}
|
||||
<STATE_STRING>["] this.popState();
|
||||
<STATE_STRING>[^"]* { /*console.log('Long description:', yytext);*/return "STATE_DESCR";}
|
||||
|
||||
@@ -53,6 +53,39 @@ describe('state diagram, ', function() {
|
||||
|
||||
parser.parse(str);
|
||||
});
|
||||
|
||||
it('handle "as" in state names', function() {
|
||||
const str = `stateDiagram
|
||||
assemble
|
||||
state assemble
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
});
|
||||
it('handle "as" in state names 1', function() {
|
||||
const str = `stateDiagram
|
||||
assemble
|
||||
state assemble
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
});
|
||||
it('handle "as" in state names 2', function() {
|
||||
const str = `stateDiagram
|
||||
assembleas
|
||||
state assembleas
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
});
|
||||
it('handle "as" in state names 3', function() {
|
||||
const str = `stateDiagram
|
||||
state "as" as as
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
});
|
||||
|
||||
it('scale', function() {
|
||||
const str = `stateDiagram\n
|
||||
scale 350 width
|
||||
|
||||
@@ -53,7 +53,7 @@ export const draw = function(text, id) {
|
||||
|
||||
// Layout graph, Create a new directed graph
|
||||
const graph = new graphlib.Graph({
|
||||
multigraph: false,
|
||||
multigraph: true,
|
||||
compound: true,
|
||||
// acyclicer: 'greedy',
|
||||
rankdir: 'RL'
|
||||
@@ -110,7 +110,8 @@ const getRows = s => {
|
||||
const renderDoc = (doc, diagram, parentId, altBkg) => {
|
||||
// // Layout graph, Create a new directed graph
|
||||
const graph = new graphlib.Graph({
|
||||
compound: true
|
||||
compound: true,
|
||||
multigraph: true
|
||||
});
|
||||
|
||||
let i;
|
||||
@@ -126,28 +127,29 @@ const renderDoc = (doc, diagram, parentId, altBkg) => {
|
||||
if (parentId)
|
||||
graph.setGraph({
|
||||
rankdir: 'LR',
|
||||
// multigraph: false,
|
||||
multigraph: true,
|
||||
compound: true,
|
||||
// acyclicer: 'greedy',
|
||||
ranker: 'tight-tree',
|
||||
ranksep: edgeFreeDoc ? 1 : conf.edgeLengthFactor,
|
||||
nodeSep: edgeFreeDoc ? 1 : 50
|
||||
// isMultiGraph: false
|
||||
nodeSep: edgeFreeDoc ? 1 : 50,
|
||||
isMultiGraph: true
|
||||
// ranksep: 5,
|
||||
// nodesep: 1
|
||||
});
|
||||
else {
|
||||
graph.setGraph({
|
||||
rankdir: 'TB',
|
||||
multigraph: true,
|
||||
compound: true,
|
||||
// isCompound: true,
|
||||
// acyclicer: 'greedy',
|
||||
// ranker: 'longest-path'
|
||||
ranksep: edgeFreeDoc ? 1 : conf.edgeLengthFactor,
|
||||
nodeSep: edgeFreeDoc ? 1 : 50,
|
||||
ranker: 'tight-tree'
|
||||
ranker: 'tight-tree',
|
||||
// ranker: 'network-simplex'
|
||||
// isMultiGraph: false
|
||||
isMultiGraph: true
|
||||
});
|
||||
}
|
||||
|
||||
@@ -226,14 +228,22 @@ const renderDoc = (doc, diagram, parentId, altBkg) => {
|
||||
}
|
||||
}
|
||||
|
||||
logger.info('Count=', graph.nodeCount());
|
||||
logger.debug('Count=', graph.nodeCount(), graph);
|
||||
let cnt = 0;
|
||||
relations.forEach(function(relation) {
|
||||
graph.setEdge(relation.id1, relation.id2, {
|
||||
relation: relation,
|
||||
width: getLabelWidth(relation.title),
|
||||
height: conf.labelHeight * getRows(relation.title).length,
|
||||
labelpos: 'c'
|
||||
});
|
||||
cnt++;
|
||||
logger.debug('Setting edge', relation);
|
||||
graph.setEdge(
|
||||
relation.id1,
|
||||
relation.id2,
|
||||
{
|
||||
relation: relation,
|
||||
width: getLabelWidth(relation.title),
|
||||
height: conf.labelHeight * getRows(relation.title).length,
|
||||
labelpos: 'c'
|
||||
},
|
||||
'id' + cnt
|
||||
);
|
||||
});
|
||||
|
||||
dagre.layout(graph);
|
||||
@@ -299,7 +309,7 @@ const renderDoc = (doc, diagram, parentId, altBkg) => {
|
||||
stateInfo.width = stateBox.width + 2 * conf.padding;
|
||||
stateInfo.height = stateBox.height + 2 * conf.padding;
|
||||
|
||||
logger.info('Doc rendered', stateInfo, graph);
|
||||
logger.debug('Doc rendered', stateInfo, graph);
|
||||
return stateInfo;
|
||||
};
|
||||
|
||||
|
||||
@@ -95,6 +95,8 @@ const config = {
|
||||
*/
|
||||
theme: 'default',
|
||||
themeCSS: undefined,
|
||||
/* **maxTextSize** - The maximum allowed size of the users text diamgram */
|
||||
maxTextSize: 50000,
|
||||
|
||||
/**
|
||||
* **fontFamily** The font to be used for the rendered diagrams. Default value is \"trebuchet ms\", verdana, arial;
|
||||
@@ -460,7 +462,13 @@ export const decodeEntities = function(text) {
|
||||
* provided a hidden div will be inserted in the body of the page instead. The element will be removed when rendering is
|
||||
* completed.
|
||||
*/
|
||||
const render = function(id, txt, cb, container) {
|
||||
const render = function(id, _txt, cb, container) {
|
||||
// Check the maximum allowed text size
|
||||
let txt = _txt;
|
||||
if (_txt.length > config.maxTextSize) {
|
||||
txt = 'graph TB;a[Maximum text size in diagram exceeded];style a fill:#faa';
|
||||
}
|
||||
|
||||
if (typeof container !== 'undefined') {
|
||||
container.innerHTML = '';
|
||||
|
||||
|
||||
@@ -99,10 +99,6 @@ export const formatUrl = (linkStr, config) => {
|
||||
if (url) {
|
||||
if (config.securityLevel !== 'loose') {
|
||||
return sanitizeUrl(url);
|
||||
} else {
|
||||
if (!/^(https?:)?\/\//i.test(url)) {
|
||||
url = 'http://' + url;
|
||||
}
|
||||
}
|
||||
|
||||
return url;
|
||||
|
||||
@@ -37,3 +37,61 @@ describe('when finding substring in array ', function() {
|
||||
expect(result).toEqual(-1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when formatting urls', function() {
|
||||
it('should handle links', function() {
|
||||
const url = 'https://mermaid-js.github.io/mermaid/#/';
|
||||
|
||||
let config = { securityLevel: 'loose' };
|
||||
let result = utils.formatUrl(url, config);
|
||||
expect(result).toEqual(url);
|
||||
|
||||
config.securityLevel = 'strict';
|
||||
result = utils.formatUrl(url, config);
|
||||
expect(result).toEqual(url);
|
||||
});
|
||||
it('should handle anchors', function() {
|
||||
const url = '#interaction';
|
||||
|
||||
let config = { securityLevel: 'loose' };
|
||||
let result = utils.formatUrl(url, config);
|
||||
expect(result).toEqual(url);
|
||||
|
||||
config.securityLevel = 'strict';
|
||||
result = utils.formatUrl(url, config);
|
||||
expect(result).toEqual('about:blank');
|
||||
});
|
||||
it('should handle mailto', function() {
|
||||
const url = 'mailto:user@user.user';
|
||||
|
||||
let config = { securityLevel: 'loose' };
|
||||
let result = utils.formatUrl(url, config);
|
||||
expect(result).toEqual(url);
|
||||
|
||||
config.securityLevel = 'strict';
|
||||
result = utils.formatUrl(url, config);
|
||||
expect(result).toEqual(url);
|
||||
});
|
||||
it('should handle other protocols', function() {
|
||||
const url = 'notes://do-your-thing/id';
|
||||
|
||||
let config = { securityLevel: 'loose' };
|
||||
let result = utils.formatUrl(url, config);
|
||||
expect(result).toEqual(url);
|
||||
|
||||
config.securityLevel = 'strict';
|
||||
result = utils.formatUrl(url, config);
|
||||
expect(result).toEqual(url);
|
||||
});
|
||||
it('should handle scripts', function() {
|
||||
const url = 'javascript:alert("test")';
|
||||
|
||||
let config = { securityLevel: 'loose' };
|
||||
let result = utils.formatUrl(url, config);
|
||||
expect(result).toEqual(url);
|
||||
|
||||
config.securityLevel = 'strict';
|
||||
result = utils.formatUrl(url, config);
|
||||
expect(result).toEqual('about:blank');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user