diff --git a/demos/index.html b/demos/index.html
index f96d2f2af..904fde7df 100644
--- a/demos/index.html
+++ b/demos/index.html
@@ -879,6 +879,31 @@ Enterprise_Boundary(b0, "BankBoundary0") {
}
+
+ classDiagram
+ Interface1 ()-- Interface1Impl
+
+
+
+ classDiagram
+ direction LR
+ Animal ()-- Dog
+ Dog : bark()
+ Dog : species()
+
+
+
+ classDiagram
+ direction RL
+ Fruit ()-- Apple
+ Apple : color()
+ Apple : -int leafCount()
+ Fruit ()-- Pineapple
+ Pineapple : color()
+ Pineapple : -int leafCount()
+ Pineapple : -int spikeCount()
+
+
stateDiagram
accDescription This is a state diagram showing one state
diff --git a/src/dagre-wrapper/edges.js b/src/dagre-wrapper/edges.js
index 60ded826e..677fda9f1 100644
--- a/src/dagre-wrapper/edges.js
+++ b/src/dagre-wrapper/edges.js
@@ -510,6 +510,9 @@ export const insertEdge = function (elem, e, edge, clusterDb, diagramType, graph
case 'dependency':
svgPath.attr('marker-start', 'url(' + url + '#' + diagramType + '-dependencyStart' + ')');
break;
+ case 'lollipop':
+ svgPath.attr('marker-start', 'url(' + url + '#' + diagramType + '-lollipopStart' + ')');
+ break;
default:
}
switch (edge.arrowTypeEnd) {
@@ -537,6 +540,9 @@ export const insertEdge = function (elem, e, edge, clusterDb, diagramType, graph
case 'dependency':
svgPath.attr('marker-end', 'url(' + url + '#' + diagramType + '-dependencyEnd' + ')');
break;
+ case 'lollipop':
+ svgPath.attr('marker-end', 'url(' + url + '#' + diagramType + '-lollipopEnd' + ')');
+ break;
default:
}
let paths = {};
diff --git a/src/dagre-wrapper/markers.js b/src/dagre-wrapper/markers.js
index ca2a12200..b28be4119 100644
--- a/src/dagre-wrapper/markers.js
+++ b/src/dagre-wrapper/markers.js
@@ -119,6 +119,24 @@ const dependency = (elem, type) => {
.append('path')
.attr('d', 'M 18,7 L9,13 L14,7 L9,1 Z');
};
+const lollipop = (elem, type, id) => {
+ elem
+ .append('defs')
+ .append('marker')
+ .attr('id', type + '-lollipopStart')
+ .attr('class', 'marker lollipop ' + type)
+ .attr('refX', 0)
+ .attr('refY', 7)
+ .attr('markerWidth', 190)
+ .attr('markerHeight', 240)
+ .attr('orient', 'auto')
+ .append('circle')
+ .attr('stroke', 'black')
+ .attr('fill', 'white')
+ .attr('cx', 6)
+ .attr('cy', 7)
+ .attr('r', 6);
+};
const point = (elem, type) => {
elem
.append('marker')
@@ -250,6 +268,7 @@ const markers = {
composition,
aggregation,
dependency,
+ lollipop,
point,
circle,
cross,
diff --git a/src/diagrams/class/classDb.js b/src/diagrams/class/classDb.js
index 9f6ccde63..690849fa8 100644
--- a/src/diagrams/class/classDb.js
+++ b/src/diagrams/class/classDb.js
@@ -311,6 +311,7 @@ export const relationType = {
EXTENSION: 1,
COMPOSITION: 2,
DEPENDENCY: 3,
+ LOLLIPOP: 4,
};
const setupToolTips = function (element) {
diff --git a/src/diagrams/class/classRenderer-v2.js b/src/diagrams/class/classRenderer-v2.js
index d82365587..11c2a6dc5 100644
--- a/src/diagrams/class/classRenderer-v2.js
+++ b/src/diagrams/class/classRenderer-v2.js
@@ -338,7 +338,13 @@ export const draw = function (text, id, _version, diagObj) {
// Run the renderer. This is what draws the final graph.
const element = root.select('#' + id + ' g');
- render(element, g, ['aggregation', 'extension', 'composition', 'dependency'], 'classDiagram', id);
+ render(
+ element,
+ g,
+ ['aggregation', 'extension', 'composition', 'dependency', 'lollipop'],
+ 'classDiagram',
+ id
+ );
setupGraphViewbox(g, svg, conf.diagramPadding, conf.useMaxWidth);
@@ -420,6 +426,9 @@ function getArrowMarker(type) {
case 3:
marker = 'dependency';
break;
+ case 4:
+ marker = 'lollipop';
+ break;
default:
marker = 'none';
}
diff --git a/src/diagrams/class/parser/classDiagram.jison b/src/diagrams/class/parser/classDiagram.jison
index f6e603a3d..ba0e69fba 100644
--- a/src/diagrams/class/parser/classDiagram.jison
+++ b/src/diagrams/class/parser/classDiagram.jison
@@ -44,6 +44,7 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
"classDiagram-v2" return 'CLASS_DIAGRAM';
"classDiagram" return 'CLASS_DIAGRAM';
[{] { this.begin("struct"); /*console.log('Starting struct');*/ return 'STRUCT_START';}
+"[*]" { /*console.log('EDGE_STATE=',yytext);*/ return 'EDGE_STATE';}
<> return "EOF_IN_STRUCT";
[{] return "OPEN_IN_STRUCT";
[}] { /*console.log('Ending struct');*/this.popState(); return 'STRUCT_STOP';}}
@@ -104,6 +105,7 @@ Function arguments are optional: 'call ()' simply executes 'callb
\s*\< return 'DEPENDENCY';
\s*\* return 'COMPOSITION';
\s*o return 'AGGREGATION';
+\s*\(\) return 'LOLLIPOP';
\-\- return 'LINE';
\.\. return 'DOTTED_LINE';
":"{1}[^:\n;]+ return 'LABEL';
@@ -310,6 +312,7 @@ relationType
| EXTENSION { $$=yy.relationType.EXTENSION;}
| COMPOSITION { $$=yy.relationType.COMPOSITION;}
| DEPENDENCY { $$=yy.relationType.DEPENDENCY;}
+ | LOLLIPOP { $$=yy.relationType.LOLLIPOP;}
;
lineType
diff --git a/src/diagrams/class/styles.js b/src/diagrams/class/styles.js
index 31b82cf56..9e7665c58 100644
--- a/src/diagrams/class/styles.js
+++ b/src/diagrams/class/styles.js
@@ -128,6 +128,18 @@ g.classGroup line {
stroke-width: 1;
}
+#lollipopStart, .lollipop {
+ fill: ${options.mainBkg} !important;
+ stroke: ${options.lineColor} !important;
+ stroke-width: 1;
+}
+
+#lollipopEnd, .lollipop {
+ fill: ${options.mainBkg} !important;
+ stroke: ${options.lineColor} !important;
+ stroke-width: 1;
+}
+
.edgeTerminals {
font-size: 11px;
}
diff --git a/src/diagrams/class/svgDraw.js b/src/diagrams/class/svgDraw.js
index a6b11cd95..a3daf2a86 100644
--- a/src/diagrams/class/svgDraw.js
+++ b/src/diagrams/class/svgDraw.js
@@ -14,6 +14,8 @@ export const drawEdge = function (elem, path, relation, conf, diagObj) {
return 'composition';
case diagObj.db.DEPENDENCY:
return 'dependency';
+ case diagObj.db.LOLLIPOP:
+ return 'lollipop';
}
};