#2050 Adding possibility to render subgrapgs in different directions

This commit is contained in:
Knut Sveidqvist 2021-05-18 21:15:06 +02:00
parent 84ad8aabec
commit 09569301f1
8 changed files with 168 additions and 11 deletions

View File

@ -893,4 +893,26 @@ graph TD
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
);
});
it('2050: handling of different rendering direction in subgraphs', () => {
imgSnapshotTest(
`
flowchart LR
subgraph TOP
direction TB
subgraph B1
direction RL
i1 -->f1
end
subgraph B2
direction BT
i2 -->f2
end
end
A --> TOP --> B
B1 --> B2
`,
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
);
});
});

View File

@ -27,7 +27,7 @@
<div>info below</div>
<div class="flex">
<div class="mermaid" style="width: 100%; height: 20%;">
<div class="mermaid3" style="width: 100%; height: 20%;">
stateDiagram-v2
state S1 {
sub1 -->sub2
@ -65,14 +65,23 @@ stateDiagram-v2
}
</div>
<div class="mermaid3" style="width: 100%; height: 20%;">
<div class="mermaid" style="width: 100%; height: 20%;">
%%{init:{"theme":"base", "themeVariables": {"primaryColor":"#411d4e", "titleColor":"white", "darkMode":true}}}%%
flowchart LR
subgraph B1
i -->f
subgraph TOP
direction TB
subgraph B1
direction RL
i1 -->f1
end
subgraph B2
direction BT
i2 -->f2
end
end
A --> B1 --> B --> B1
A --> TOP --> B
B1 --> B2
</div>
<script src="./mermaid.js"></script>
<script>

View File

@ -50,7 +50,7 @@ export const lookUpDomId = function(id) {
* @param style
* @param classes
*/
export const addVertex = function(_id, text, type, style, classes) {
export const addVertex = function(_id, text, type, style, classes, dir) {
let txt;
let id = _id;
if (typeof id === 'undefined') {
@ -103,6 +103,9 @@ export const addVertex = function(_id, text, type, style, classes) {
});
}
}
if (typeof dir !== 'undefined') {
vertices[id].dir = dir;
}
};
/**
@ -431,6 +434,7 @@ export const defaultStyle = function() {
* Clears the internal graph db so that a new graph can be parsed.
*/
export const addSubGraph = function(_id, list, _title) {
// console.log('addSubGraph', _id, list, _title);
let id = _id.trim();
let title = _title;
if (_id === _title && _title.match(/\s/)) {
@ -440,8 +444,13 @@ export const addSubGraph = function(_id, list, _title) {
const prims = { boolean: {}, number: {}, string: {} };
const objs = [];
return a.filter(function(item) {
let dir = direction.trim();
const nodeList = a.filter(function(item) {
const type = typeof item;
if (item.stmt && item.stmt === 'dir') {
dir = item.value;
return false;
}
if (item.trim() === '') {
return false;
}
@ -451,11 +460,13 @@ export const addSubGraph = function(_id, list, _title) {
return objs.indexOf(item) >= 0 ? false : objs.push(item);
}
});
return { nodeList, dir };
}
let nodeList = [];
nodeList = uniq(nodeList.concat.apply(nodeList, list));
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++) {
@ -468,9 +479,9 @@ export const addSubGraph = function(_id, list, _title) {
title = title || '';
title = common.sanitizeText(title, config);
subCount = subCount + 1;
const subGraph = { id: id, nodes: nodeList, title: title.trim(), classes: [] };
const subGraph = { id: id, nodes: nodeList, title: title.trim(), classes: [], dir };
log.info('Adding', subGraph.id, subGraph.nodes);
log.info('Adding', subGraph.id, subGraph.nodes, subGraph.dir);
/**
* Deletes an id from all subgraphs

View File

@ -147,6 +147,7 @@ export const addVertices = function(vert, g, svgId) {
domId: flowDb.lookUpDomId(vertex.id),
haveCallback: vertex.haveCallback,
width: vertex.type === 'group' ? 500 : undefined,
dir: vertex.dir,
type: vertex.type,
padding: getConfig().flowchart.padding
});
@ -163,6 +164,7 @@ export const addVertices = function(vert, g, svgId) {
domId: flowDb.lookUpDomId(vertex.id),
width: vertex.type === 'group' ? 500 : undefined,
type: vertex.type,
dir: vertex.dir,
padding: getConfig().flowchart.padding
});
});
@ -385,7 +387,7 @@ export const draw = function(text, id) {
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);
flowDb.addVertex(subG.id, subG.title, 'group', undefined, subG.classes, subG.dir);
}
// Fetch the verices/nodes and edges/links from the parsed graph definition

View File

@ -0,0 +1,95 @@
import flowDb from '../flowDb';
import flow from './flow';
import filter from 'lodash/filter';
import { setConfig } from '../../../config';
setConfig({
securityLevel: 'strict'
});
describe('when parsing directions', function() {
beforeEach(function() {
flow.parser.yy = flowDb;
flow.parser.yy.clear();
flow.parser.yy.setGen('gen-2');
});
fit('should use default direction from top level', function() {
const res = flow.parser.parse(`flowchart TB
subgraph A
a --> b
end`);
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(1);
const subgraph = subgraphs[0];
expect(subgraph.nodes.length).toBe(2);
expect(subgraph.nodes[0]).toBe('b');
expect(subgraph.nodes[1]).toBe('a');
expect(subgraph.id).toBe('A');
expect(subgraph.dir).toBe('TB');
});
fit('should handle a subgraph with a direction', function() {
const res = flow.parser.parse(`flowchart TB
subgraph A
direction BT
a --> b
end`);
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(1);
const subgraph = subgraphs[0];
expect(subgraph.nodes.length).toBe(2);
expect(subgraph.nodes[0]).toBe('b');
expect(subgraph.nodes[1]).toBe('a');
expect(subgraph.id).toBe('A');
expect(subgraph.dir).toBe('BT');
});
fit('should use the last defined direction', function() {
const res = flow.parser.parse(`flowchart TB
subgraph A
direction BT
a --> b
direction RL
end`);
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(1);
const subgraph = subgraphs[0];
expect(subgraph.nodes.length).toBe(2);
expect(subgraph.nodes[0]).toBe('b');
expect(subgraph.nodes[1]).toBe('a');
expect(subgraph.id).toBe('A');
expect(subgraph.dir).toBe('RL');
});
fit('should handle nested subgraphs 1', function() {
const res = flow.parser.parse(`flowchart TB
subgraph A
direction RL
b-->B
a
end
a-->c
subgraph B
direction LR
c
end`);
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(2);
const subgraphA = filter(subgraphs,o => o.id === 'A')[0];
const subgraphB = filter(subgraphs,o => o.id === 'B')[0];
expect(subgraphB.nodes[0]).toBe('c');
expect(subgraphB.dir).toBe('LR');
expect(subgraphA.nodes).toContain('B');
expect(subgraphA.nodes).toContain('b');
expect(subgraphA.nodes).toContain('a');
expect(subgraphA.nodes).not.toContain('c');
expect(subgraphA.dir).toBe('RL');
});
});

View File

@ -92,6 +92,12 @@ that id.
<dir>\s*">" { this.popState(); return 'DIR'; }
<dir>\s*"^" { this.popState(); return 'DIR'; }
<dir>\s*"v" { this.popState(); return 'DIR'; }
.*direction\s+TB[^\n]* return 'direction_tb';
.*direction\s+BT[^\n]* return 'direction_bt';
.*direction\s+RL[^\n]* return 'direction_rl';
.*direction\s+LR[^\n]* return 'direction_lr';
[0-9]+ { return 'NUM';}
\# return 'BRKT';
":::" return 'STYLE_SEPARATOR';
@ -327,6 +333,7 @@ statement
// {$$=yy.addSubGraph($3,$5,$3);}
| subgraph separator document end
{$$=yy.addSubGraph(undefined,$3,undefined);}
| direction
;
separator: NEWLINE | SEMI | EOF ;
@ -537,6 +544,17 @@ alphaNumStatement
{$$='-';}
;
direction
: direction_tb
{ $$={stmt:'dir', value:'TB'};}
| direction_bt
{ $$={stmt:'dir', value:'BT'};}
| direction_rl
{ $$={stmt:'dir', value:'RL'};}
| direction_lr
{ $$={stmt:'dir', value:'LR'};}
;
alphaNumToken : PUNCTUATION | AMP | UNICODE_TEXT | NUM| ALPHA | COLON | COMMA | PLUS | EQUALS | MULT | DOT | BRKT| UNDERSCORE ;
idStringToken : ALPHA|UNDERSCORE |UNICODE_TEXT | NUM| COLON | COMMA | PLUS | MINUS | DOWN |EQUALS | MULT | BRKT | DOT | PUNCTUATION | AMP;