mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-28 07:03:17 +08:00
#1154 Flow diagram DB shape request
This commit is contained in:
parent
728e3fd2f0
commit
bc59d015e6
@ -1,7 +1,7 @@
|
||||
/* eslint-env jest */
|
||||
import { imgSnapshotTest } from '../../helpers/util';
|
||||
|
||||
describe('Flowcart', () => {
|
||||
describe('Flowchart', () => {
|
||||
it('1: should render a simple flowchart no htmlLabels', () => {
|
||||
imgSnapshotTest(
|
||||
`graph TD
|
||||
@ -57,7 +57,7 @@ describe('Flowcart', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('4: should style nodes via a class.', () => {
|
||||
it('5: should style nodes via a class.', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
graph TD
|
||||
@ -73,7 +73,7 @@ describe('Flowcart', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('5: should render a flowchart full of circles', () => {
|
||||
it('6: should render a flowchart full of circles', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
graph LR
|
||||
@ -102,7 +102,7 @@ describe('Flowcart', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('6: should render a flowchart full of icons', () => {
|
||||
it('7: should render a flowchart full of icons', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
graph TD
|
||||
@ -173,7 +173,7 @@ describe('Flowcart', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('7: should render labels with numbers at the start', () => {
|
||||
it('8: should render labels with numbers at the start', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
graph TB;subgraph "number as labels";1;end;
|
||||
@ -182,7 +182,7 @@ describe('Flowcart', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('8: should render subgraphs', () => {
|
||||
it('9: should render subgraphs', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
graph TB
|
||||
@ -194,7 +194,7 @@ describe('Flowcart', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('9: should render subgraphs with a title starting with a digit', () => {
|
||||
it('10: should render subgraphs with a title starting with a digit', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
graph TB
|
||||
@ -206,7 +206,7 @@ describe('Flowcart', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('10: should render styled subgraphs', () => {
|
||||
it('11: should render styled subgraphs', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
graph TB
|
||||
@ -241,7 +241,7 @@ describe('Flowcart', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('11: should render a flowchart with long names and class definitions', () => {
|
||||
it('12: should render a flowchart with long names and class definitions', () => {
|
||||
imgSnapshotTest(
|
||||
`graph LR
|
||||
sid-B3655226-6C29-4D00-B685-3D5C734DC7E1["
|
||||
@ -343,7 +343,7 @@ describe('Flowcart', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('12: should render color of styled nodes', () => {
|
||||
it('13: should render color of styled nodes', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
graph LR
|
||||
@ -361,7 +361,7 @@ describe('Flowcart', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('13: should render hexagons', () => {
|
||||
it('14: should render hexagons', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
graph TD
|
||||
@ -383,7 +383,7 @@ describe('Flowcart', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('14: should render a simple flowchart with comments', () => {
|
||||
it('15: should render a simple flowchart with comments', () => {
|
||||
imgSnapshotTest(
|
||||
`graph TD
|
||||
A[Christmas] -->|Get money| B(Go shopping)
|
||||
@ -396,7 +396,7 @@ describe('Flowcart', () => {
|
||||
{ flowchart: { htmlLabels: false } }
|
||||
);
|
||||
});
|
||||
it('15: Render Stadium shape', () => {
|
||||
it('16: Render Stadium shape', () => {
|
||||
imgSnapshotTest(
|
||||
` graph TD
|
||||
A([stadium shape test])
|
||||
@ -412,7 +412,7 @@ describe('Flowcart', () => {
|
||||
{ flowchart: { htmlLabels: false } }
|
||||
);
|
||||
});
|
||||
it('16: Render Stadium shape', () => {
|
||||
it('17: Render multiline texts', () => {
|
||||
imgSnapshotTest(
|
||||
`graph LR
|
||||
A1[Multi<br>Line] -->|Multi<br>Line| B1(Multi<br>Line)
|
||||
@ -428,7 +428,7 @@ describe('Flowcart', () => {
|
||||
{ flowchart: { htmlLabels: false } }
|
||||
);
|
||||
});
|
||||
it('17: Chaining of nodes', () => {
|
||||
it('18: Chaining of nodes', () => {
|
||||
imgSnapshotTest(
|
||||
`graph LR
|
||||
a --> b --> c
|
||||
@ -436,7 +436,7 @@ describe('Flowcart', () => {
|
||||
{ flowchart: { htmlLabels: false } }
|
||||
);
|
||||
});
|
||||
it('18: Multiple nodes and chaining in one statement', () => {
|
||||
it('19: Multiple nodes and chaining in one statement', () => {
|
||||
imgSnapshotTest(
|
||||
`graph LR
|
||||
a --> b c--> d
|
||||
@ -444,7 +444,7 @@ describe('Flowcart', () => {
|
||||
{ flowchart: { htmlLabels: false } }
|
||||
);
|
||||
});
|
||||
it('19: Multiple nodes and chaining in one statement', () => {
|
||||
it('20: Multiple nodes and chaining in one statement', () => {
|
||||
imgSnapshotTest(
|
||||
`graph TD
|
||||
A[ h ] -- hello --> B[" test "]:::exClass C --> D;
|
||||
@ -453,4 +453,25 @@ describe('Flowcart', () => {
|
||||
{ flowchart: { htmlLabels: false } }
|
||||
);
|
||||
});
|
||||
it('21: Render cylindrical shape', () => {
|
||||
imgSnapshotTest(
|
||||
`graph LR
|
||||
A[(cylindrical<br />shape<br />test)]
|
||||
A -->|Get money| B1[(Go shopping 1)]
|
||||
A -->|Get money| B2[(Go shopping 2)]
|
||||
A -->|Get money| B3[(Go shopping 3)]
|
||||
C[(Let me think...<br />Do I want something for work,<br />something to spend every free second with,<br />or something to get around?)]
|
||||
B1 --> C
|
||||
B2 --> C
|
||||
B3 --> C
|
||||
C -->|One| D[(Laptop)]
|
||||
C -->|Two| E[(iPhone)]
|
||||
C -->|Three| F[(Car)]
|
||||
click A "index.html#link-clicked" "link test"
|
||||
click B testClick "click test"
|
||||
classDef someclass fill:#f96;
|
||||
class A someclass;`,
|
||||
{ flowchart: { htmlLabels: false } }
|
||||
);
|
||||
});
|
||||
});
|
||||
|
18
dist/index.html
vendored
18
dist/index.html
vendored
@ -313,6 +313,24 @@ class A someclass;
|
||||
classDef someclass fill:#f96;
|
||||
class A someclass;
|
||||
</div>
|
||||
<div class="mermaid">
|
||||
graph LR
|
||||
A[(cylindrical<br />shape<br />test)]
|
||||
A -->|Get money| B1[(Go shopping 1)]
|
||||
A -->|Get money| B2[(Go shopping 2)]
|
||||
A -->|Get money| B3[(Go shopping 3)]
|
||||
C[(Let me think...<br />Do I want something for work,<br />something to spend every free second with,<br />or something to get around?)]
|
||||
B1 --> C
|
||||
B2 --> C
|
||||
B3 --> C
|
||||
C -->|One| D[(Laptop)]
|
||||
C -->|Two| E[(iPhone)]
|
||||
C -->|Three| F[(Car)]
|
||||
click A "index.html#link-clicked" "link test"
|
||||
click B testClick "click test"
|
||||
classDef someclass fill:#f96;
|
||||
class A someclass;
|
||||
</div>
|
||||
<div class="mermaid">
|
||||
graph LR
|
||||
A1[Multi<br>Line] -->|Multi<br>Line| B1(Multi<br>Line)
|
||||
|
@ -89,6 +89,17 @@ graph LR
|
||||
id1([This is the text in the box])
|
||||
```
|
||||
|
||||
### A node in a cylindrical shape
|
||||
|
||||
```
|
||||
graph LR
|
||||
id1[(Database)]
|
||||
```
|
||||
```mermaid
|
||||
graph LR
|
||||
id1[(Database)]
|
||||
```
|
||||
|
||||
### A node in the form of a circle
|
||||
|
||||
```
|
||||
|
@ -154,10 +154,74 @@ function stadium(parent, bbox, node) {
|
||||
return shapeSvg;
|
||||
}
|
||||
|
||||
function cylinder(parent, bbox, node) {
|
||||
const w = bbox.width;
|
||||
const rx = w / 2;
|
||||
const ry = rx / (2.5 + w / 50);
|
||||
const h = bbox.height + ry;
|
||||
|
||||
const shape =
|
||||
'M 0,' +
|
||||
ry +
|
||||
' a ' +
|
||||
rx +
|
||||
',' +
|
||||
ry +
|
||||
' 0,0,0 ' +
|
||||
w +
|
||||
' 0 a ' +
|
||||
rx +
|
||||
',' +
|
||||
ry +
|
||||
' 0,0,0 ' +
|
||||
-w +
|
||||
' 0 l 0,' +
|
||||
h +
|
||||
' a ' +
|
||||
rx +
|
||||
',' +
|
||||
ry +
|
||||
' 0,0,0 ' +
|
||||
w +
|
||||
' 0 l 0,' +
|
||||
-h;
|
||||
|
||||
const shapeSvg = parent
|
||||
.attr('label-offset-y', ry)
|
||||
.insert('path', ':first-child')
|
||||
.attr('d', shape)
|
||||
.attr('transform', 'translate(' + -w / 2 + ',' + -(h / 2 + ry) + ')');
|
||||
|
||||
node.intersect = function(point) {
|
||||
const pos = dagreD3.intersect.rect(node, point);
|
||||
const x = pos.x - node.x;
|
||||
|
||||
if (
|
||||
rx != 0 &&
|
||||
(Math.abs(x) < node.width / 2 ||
|
||||
(Math.abs(x) == node.width / 2 && Math.abs(pos.y - node.y) > node.height / 2 - ry))
|
||||
) {
|
||||
// ellipsis equation: x*x / a*a + y*y / b*b = 1
|
||||
// solve for y to get adjustion value for pos.y
|
||||
let y = ry * ry * (1 - (x * x) / (rx * rx));
|
||||
if (y != 0) y = Math.sqrt(y);
|
||||
y = ry - y;
|
||||
if (point.y - node.y > 0) y = -y;
|
||||
|
||||
pos.y += y;
|
||||
}
|
||||
|
||||
return pos;
|
||||
};
|
||||
|
||||
return shapeSvg;
|
||||
}
|
||||
|
||||
export function addToRender(render) {
|
||||
render.shapes().question = question;
|
||||
render.shapes().hexagon = hexagon;
|
||||
render.shapes().stadium = stadium;
|
||||
render.shapes().cylinder = cylinder;
|
||||
|
||||
// Add custom shape for box with inverted arrow on left side
|
||||
render.shapes().rect_left_inv_arrow = rect_left_inv_arrow;
|
||||
|
@ -23,6 +23,23 @@ describe('flowchart shapes', function() {
|
||||
});
|
||||
});
|
||||
|
||||
// path-based shapes
|
||||
[
|
||||
['cylinder', useWidth, useHeight]
|
||||
].forEach(function([shapeType, getW, getH]) {
|
||||
it(`should add a ${shapeType} shape that renders a properly positioned path element`, function() {
|
||||
const mockRender = MockRender();
|
||||
const mockSvg = MockSvg();
|
||||
addToRender(mockRender);
|
||||
|
||||
[[100, 100], [123, 45], [71, 300]].forEach(function([width, height]) {
|
||||
const shape = mockRender.shapes()[shapeType](mockSvg, { width, height }, {});
|
||||
expect(shape.__tag).toEqual('path');
|
||||
expect(shape.__attrs).toHaveProperty('d');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// polygon-based shapes
|
||||
[
|
||||
[
|
||||
|
@ -157,6 +157,9 @@ export const addVertices = function(vert, g, svgId) {
|
||||
case 'stadium':
|
||||
_shape = 'stadium';
|
||||
break;
|
||||
case 'cylinder':
|
||||
_shape = 'cylinder';
|
||||
break;
|
||||
case 'group':
|
||||
_shape = 'rect';
|
||||
break;
|
||||
|
@ -23,6 +23,7 @@ describe('the flowchart renderer', function() {
|
||||
['circle', 'circle'],
|
||||
['ellipse', 'ellipse'],
|
||||
['stadium', 'stadium'],
|
||||
['cylinder', 'cylinder'],
|
||||
['group', 'rect']
|
||||
].forEach(function([type, expectedShape, expectedRadios = 0]) {
|
||||
it(`should add the correct shaped node to the graph for vertex type ${type}`, function() {
|
||||
|
@ -85,6 +85,8 @@
|
||||
"-)" return '-)';
|
||||
"([" return 'STADIUMSTART';
|
||||
"])" return 'STADIUMEND';
|
||||
"[(" return 'CYLINDERSTART';
|
||||
")]" return 'CYLINDEREND';
|
||||
\- return 'MINUS';
|
||||
"." return 'DOT';
|
||||
[\_] return 'UNDERSCORE';
|
||||
@ -312,6 +314,8 @@ vertex: idString SQS text SQE
|
||||
{$$ = $1;yy.addVertex($1,$3,'ellipse');}
|
||||
| idString STADIUMSTART text STADIUMEND
|
||||
{$$ = $1;yy.addVertex($1,$3,'stadium');}
|
||||
| idString CYLINDERSTART text CYLINDEREND
|
||||
{$$ = $1;yy.addVertex($1,$3,'cylinder');}
|
||||
| idString PS text PE
|
||||
{$$ = $1;yy.addVertex($1,$3,'round');}
|
||||
| idString DIAMOND_START text DIAMOND_STOP
|
||||
@ -468,5 +472,5 @@ alphaNumToken : PUNCTUATION | UNICODE_TEXT | NUM| ALPHA | COLON | COMMA | PLUS
|
||||
|
||||
idStringToken : ALPHA|UNDERSCORE |UNICODE_TEXT | NUM| COLON | COMMA | PLUS | MINUS | DOWN |EQUALS | MULT | BRKT | DOT | PUNCTUATION;
|
||||
|
||||
graphCodeTokens: STADIUMSTART | STADIUMEND | TRAPSTART | TRAPEND | INVTRAPSTART | INVTRAPEND | PIPE | PS | PE | SQS | SQE | DIAMOND_START | DIAMOND_STOP | TAGSTART | TAGEND | ARROW_CROSS | ARROW_POINT | ARROW_CIRCLE | ARROW_OPEN | QUOTE | SEMI;
|
||||
graphCodeTokens: STADIUMSTART | STADIUMEND | CYLINDERSTART | CYLINDEREND | TRAPSTART | TRAPEND | INVTRAPSTART | INVTRAPEND | PIPE | PS | PE | SQS | SQE | DIAMOND_START | DIAMOND_STOP | TAGSTART | TAGEND | ARROW_CROSS | ARROW_POINT | ARROW_CIRCLE | ARROW_OPEN | QUOTE | SEMI;
|
||||
%%
|
||||
|
@ -11,7 +11,8 @@
|
||||
.node rect,
|
||||
.node circle,
|
||||
.node ellipse,
|
||||
.node polygon {
|
||||
.node polygon,
|
||||
.node path {
|
||||
fill: $mainBkg;
|
||||
stroke: $nodeBorder;
|
||||
stroke-width: 1px;
|
||||
|
Loading…
x
Reference in New Issue
Block a user