diff --git a/cypress/integration/rendering/flowchart-v2.spec.js b/cypress/integration/rendering/flowchart-v2.spec.js
index 60fba981e..10731de05 100644
--- a/cypress/integration/rendering/flowchart-v2.spec.js
+++ b/cypress/integration/rendering/flowchart-v2.spec.js
@@ -368,6 +368,7 @@ flowchart TD
I{{red text}} -->|default style| J[/blue text/]
K[\\ red text\\] -->|default style| L[/blue text\\]
M[\\ red text/] -->|default style| N[blue text];
+ O(((red text))) -->|default style| P(((blue text)));
linkStyle default color:Sienna;
style A stroke:#ff0000,fill:#ffcccc,color:#ff0000;
style B stroke:#0000ff,fill:#ccccff,color:#0000ff;
@@ -383,6 +384,8 @@ flowchart TD
style L stroke:#0000ff,fill:#ccccff,color:#0000ff;
style M stroke:#ff0000,fill:#ffcccc,color:#ff0000;
style N stroke:#0000ff,fill:#ccccff,color:#0000ff;
+ style O stroke:#ff0000,fill:#ffcccc,color:#ff0000;
+ style P stroke:#0000ff,fill:#ccccff,color:#0000ff;
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose', logLevel: 2 }
);
diff --git a/demos/flowchart.html b/demos/flowchart.html
index 1263a5b54..0ab1f6481 100644
--- a/demos/flowchart.html
+++ b/demos/flowchart.html
@@ -1047,6 +1047,7 @@
L1[/red text\] <-->|default style| L2[/blue text\]
M1[\red text/] <-->|default style| M2[\blue text/]
N1[red text] <-->|default style| N2[blue text]
+ O1(((red text))) <-->|default style| O2(((blue text)))
linkStyle default color:Sienna;
style A1 stroke:#ff0000,fill:#ffcccc,color:#ff0000
style B1 stroke:#ff0000,fill:#ffcccc,color:#ff0000
@@ -1062,6 +1063,7 @@
style L1 stroke:#ff0000,fill:#ffcccc,color:#ff0000
style M1 stroke:#ff0000,fill:#ffcccc,color:#ff0000
style N1 stroke:#ff0000,fill:#ffcccc,color:#ff0000
+ style O1 stroke:#ff0000,fill:#ffcccc,color:#ff0000
style A2 stroke:#0000ff,fill:#ccccff,color:#0000ff
style B2 stroke:#0000ff,fill:#ccccff,color:#0000ff
style C2 stroke:#0000ff,fill:#ccccff,color:#0000ff
@@ -1076,6 +1078,7 @@
style L2 stroke:#0000ff,fill:#ccccff,color:#0000ff
style M2 stroke:#0000ff,fill:#ccccff,color:#0000ff
style N2 stroke:#0000ff,fill:#ccccff,color:#0000ff
+ style O2 stroke:#0000ff,fill:#ccccff,color:#0000ff
diff --git a/docs/flowchart.md b/docs/flowchart.md
index 795d27579..f33fe39cc 100644
--- a/docs/flowchart.md
+++ b/docs/flowchart.md
@@ -141,6 +141,13 @@ flowchart TD
B[\Go shopping/]
```
+### Double circle
+
+```mermaid-example
+flowchart TD
+ id1(((This is the text in the circle)))
+```
+
## Links between nodes
Nodes can be connected with links/edges. It is possible to have different types of links or attach a text string to a link.
diff --git a/src/dagre-wrapper/nodes.js b/src/dagre-wrapper/nodes.js
index cb25f7fc0..52c6e0777 100644
--- a/src/dagre-wrapper/nodes.js
+++ b/src/dagre-wrapper/nodes.js
@@ -554,6 +554,42 @@ const circle = (parent, node) => {
return shapeSvg;
};
+const doublecircle = (parent, node) => {
+ const { shapeSvg, bbox, halfPadding } = labelHelper(parent, node, undefined, true);
+ const gap = 5;
+ const circleGroup = shapeSvg.insert('g', ':first-child');
+ const outerCircle = circleGroup.insert('circle');
+ const innerCircle = circleGroup.insert('circle');
+
+ // center the circle around its coordinate
+ outerCircle
+ .attr('style', node.style)
+ .attr('rx', node.rx)
+ .attr('ry', node.ry)
+ .attr('r', bbox.width / 2 + halfPadding + gap)
+ .attr('width', bbox.width + node.padding + gap * 2)
+ .attr('height', bbox.height + node.padding + gap * 2);
+
+ innerCircle
+ .attr('style', node.style)
+ .attr('rx', node.rx)
+ .attr('ry', node.ry)
+ .attr('r', bbox.width / 2 + halfPadding)
+ .attr('width', bbox.width + node.padding)
+ .attr('height', bbox.height + node.padding);
+
+ log.info('DoubleCircle main');
+
+ updateNodeBounds(node, outerCircle);
+
+ node.intersect = function (point) {
+ log.info('DoubleCircle intersect', node, bbox.width / 2 + halfPadding + gap, point);
+ return intersect.circle(node, bbox.width / 2 + halfPadding + gap, point);
+ };
+
+ return shapeSvg;
+};
+
const subroutine = (parent, node) => {
const { shapeSvg, bbox } = labelHelper(parent, node, undefined, true);
@@ -943,6 +979,7 @@ const shapes = {
rectWithTitle,
choice,
circle,
+ doublecircle,
stadium,
hexagon,
rect_left_inv_arrow,
diff --git a/src/diagrams/flowchart/flowRenderer-v2.js b/src/diagrams/flowchart/flowRenderer-v2.js
index 21300992c..ae58a0212 100644
--- a/src/diagrams/flowchart/flowRenderer-v2.js
+++ b/src/diagrams/flowchart/flowRenderer-v2.js
@@ -133,6 +133,9 @@ export const addVertices = function (vert, g, svgId, root, doc) {
case 'group':
_shape = 'rect';
break;
+ case 'doublecircle':
+ _shape = 'doublecircle';
+ break;
default:
_shape = 'rect';
}
diff --git a/src/diagrams/flowchart/parser/flow-singlenode.spec.js b/src/diagrams/flowchart/parser/flow-singlenode.spec.js
index acf0263fb..ee41a5c39 100644
--- a/src/diagrams/flowchart/parser/flow-singlenode.spec.js
+++ b/src/diagrams/flowchart/parser/flow-singlenode.spec.js
@@ -159,6 +159,40 @@ describe('[Singlenodes] when parsing', () => {
expect(vert['a'].text).toBe('A
end');
});
+ it('should handle a single double circle node', function () {
+ // Silly but syntactically correct
+ const res = flow.parser.parse('graph TD;a(((A)));');
+
+ const vert = flow.parser.yy.getVertices();
+ const edges = flow.parser.yy.getEdges();
+
+ expect(edges.length).toBe(0);
+ expect(vert['a'].type).toBe('doublecircle');
+ });
+
+ it('should handle a single double circle node with whitespace after it', function () {
+ // Silly but syntactically correct
+ const res = flow.parser.parse('graph TD;a(((A))) ;');
+
+ const vert = flow.parser.yy.getVertices();
+ const edges = flow.parser.yy.getEdges();
+
+ expect(edges.length).toBe(0);
+ expect(vert['a'].type).toBe('doublecircle');
+ });
+
+ it('should handle a single double circle node with html in it (SN3)', function () {
+ // Silly but syntactically correct
+ const res = flow.parser.parse('graph TD;a(((A
end)));');
+
+ const vert = flow.parser.yy.getVertices();
+ const edges = flow.parser.yy.getEdges();
+
+ expect(edges.length).toBe(0);
+ expect(vert['a'].type).toBe('doublecircle');
+ expect(vert['a'].text).toBe('A
end');
+ });
+
it('should handle a single node with alphanumerics starting on a char', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;id1;');
diff --git a/src/diagrams/flowchart/parser/flow.jison b/src/diagrams/flowchart/parser/flow.jison
index f07182395..79175307a 100644
--- a/src/diagrams/flowchart/parser/flow.jison
+++ b/src/diagrams/flowchart/parser/flow.jison
@@ -121,6 +121,8 @@ that id.
"[|" return 'VERTEX_WITH_PROPS_START';
"[(" return 'CYLINDERSTART';
")]" return 'CYLINDEREND';
+"(((" return 'DOUBLECIRCLESTART';
+")))" return 'DOUBLECIRCLEEND';
\- return 'MINUS';
"." return 'DOT';
[\_] return 'UNDERSCORE';
@@ -373,6 +375,8 @@ node: vertex
vertex: idString SQS text SQE
{$$ = $1;yy.addVertex($1,$3,'square');}
+ | idString DOUBLECIRCLESTART text DOUBLECIRCLEEND
+ {$$ = $1;yy.addVertex($1,$3,'doublecircle');}
| idString PS PS text PE PE
{$$ = $1;yy.addVertex($1,$4,'circle');}
| idString '(-' text '-)'