mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-28 07:03:17 +08:00
Merge pull request #3647 from DKurilo/feat/1414-notes-to-class-diagram
add the way to add notes to class diagram
This commit is contained in:
commit
27a68819bc
@ -164,6 +164,7 @@ Class01 <|-- AveryLongClass : Cool
|
|||||||
Class09 --> C2 : Where am I?
|
Class09 --> C2 : Where am I?
|
||||||
Class09 --* C3
|
Class09 --* C3
|
||||||
Class09 --|> Class07
|
Class09 --|> Class07
|
||||||
|
note "I love this diagram!\nDo you love it?"
|
||||||
Class07 : equals()
|
Class07 : equals()
|
||||||
Class07 : Object[] elementData
|
Class07 : Object[] elementData
|
||||||
Class01 : size()
|
Class01 : size()
|
||||||
@ -174,6 +175,7 @@ class Class10 {
|
|||||||
int id
|
int id
|
||||||
size()
|
size()
|
||||||
}
|
}
|
||||||
|
note for Class10 "Cool class\nI said it's very cool class!"
|
||||||
```
|
```
|
||||||
|
|
||||||
### State diagram [<a href="https://mermaid-js.github.io/mermaid/#/stateDiagram">docs</a> - <a href="https://mermaid.live/edit#pako:eNpdkEFvgzAMhf8K8nEqpYSNthx22Xbcqcexg0sCiZQQlDhIFeK_L8A6TfXp6fOz9ewJGssFVOAJSbwr7ByadGR1n8T6evpO0vQ1uZDSekOrXGFsPqJPO6q-2-imH8f_0TeHXm50lfelsAMjnEHFY6xpMdRAUhhRQxUlFy0GTTXU_RytYeAx-AdXZB1ULWovdoCB7OXWN1CRC-Ju-r3uz6UtchGHJqDbsPygU57iysb2reoWHpyOWBINvsqypb3vFMlw3TfWZF5xiY7keC6zkpUnZIUojwW-FAVvrvn51LLnvOXHQ84Q5nn-AVtLcwk">live editor</a>]
|
### State diagram [<a href="https://mermaid-js.github.io/mermaid/#/stateDiagram">docs</a> - <a href="https://mermaid.live/edit#pako:eNpdkEFvgzAMhf8K8nEqpYSNthx22Xbcqcexg0sCiZQQlDhIFeK_L8A6TfXp6fOz9ewJGssFVOAJSbwr7ByadGR1n8T6evpO0vQ1uZDSekOrXGFsPqJPO6q-2-imH8f_0TeHXm50lfelsAMjnEHFY6xpMdRAUhhRQxUlFy0GTTXU_RytYeAx-AdXZB1ULWovdoCB7OXWN1CRC-Ju-r3uz6UtchGHJqDbsPygU57iysb2reoWHpyOWBINvsqypb3vFMlw3TfWZF5xiY7keC6zkpUnZIUojwW-FAVvrvn51LLnvOXHQ84Q5nn-AVtLcwk">live editor</a>]
|
||||||
|
@ -478,4 +478,22 @@ describe('Class diagram V2', () => {
|
|||||||
);
|
);
|
||||||
cy.get('svg');
|
cy.get('svg');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('18: should render a simple class diagram with notes', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`
|
||||||
|
classDiagram-v2
|
||||||
|
note "I love this diagram!\nDo you love it?"
|
||||||
|
class Class10 {
|
||||||
|
<<service>>
|
||||||
|
int id
|
||||||
|
size()
|
||||||
|
}
|
||||||
|
note for Class10 "Cool class\nI said it's very cool class!"
|
||||||
|
|
||||||
|
`,
|
||||||
|
{ logLevel: 1, flowchart: { htmlLabels: false } }
|
||||||
|
);
|
||||||
|
cy.get('svg');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -407,4 +407,21 @@ describe('Class diagram', () => {
|
|||||||
// // expect(svg).to.not.have.attr('style');
|
// // expect(svg).to.not.have.attr('style');
|
||||||
// });
|
// });
|
||||||
// });
|
// });
|
||||||
|
|
||||||
|
it('19: should render a simple class diagram with notes', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`
|
||||||
|
classDiagram
|
||||||
|
note "I love this diagram!\nDo you love it?"
|
||||||
|
class Class10 {
|
||||||
|
<<service>>
|
||||||
|
int id
|
||||||
|
size()
|
||||||
|
}
|
||||||
|
note for Class10 "Cool class\nI said it's very cool class!"
|
||||||
|
`,
|
||||||
|
{ logLevel: 1 }
|
||||||
|
);
|
||||||
|
cy.get('svg');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -11,7 +11,9 @@ Mermaid can render class diagrams.
|
|||||||
|
|
||||||
```mermaid-example
|
```mermaid-example
|
||||||
classDiagram
|
classDiagram
|
||||||
|
note "From Duck till Zebra"
|
||||||
Animal <|-- Duck
|
Animal <|-- Duck
|
||||||
|
note for Duck "can fly\ncan swim\ncan dive\ncan help in debugging"
|
||||||
Animal <|-- Fish
|
Animal <|-- Fish
|
||||||
Animal <|-- Zebra
|
Animal <|-- Zebra
|
||||||
Animal : +int age
|
Animal : +int age
|
||||||
@ -35,7 +37,9 @@ classDiagram
|
|||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
classDiagram
|
classDiagram
|
||||||
|
note "From Duck till Zebra"
|
||||||
Animal <|-- Duck
|
Animal <|-- Duck
|
||||||
|
note for Duck "can fly\ncan swim\ncan dive\ncan help in debugging"
|
||||||
Animal <|-- Fish
|
Animal <|-- Fish
|
||||||
Animal <|-- Zebra
|
Animal <|-- Zebra
|
||||||
Animal : +int age
|
Animal : +int age
|
||||||
@ -549,6 +553,10 @@ You would define these actions on a separate line after all classes have been de
|
|||||||
- (_optional_) tooltip is a string to be displayed when hovering over element (note: The styles of the tooltip are set by the class .mermaidTooltip.)
|
- (_optional_) tooltip is a string to be displayed when hovering over element (note: The styles of the tooltip are set by the class .mermaidTooltip.)
|
||||||
- note: callback function will be called with the nodeId as parameter.
|
- note: callback function will be called with the nodeId as parameter.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
It is possible to add notes on digram using `note "line1\nline2"` or note for class using `note for class "line1\nline2"`
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
_URL Link:_
|
_URL Link:_
|
||||||
|
@ -16,6 +16,7 @@ const MERMAID_DOM_ID_PREFIX = 'classid-';
|
|||||||
|
|
||||||
let relations = [];
|
let relations = [];
|
||||||
let classes = {};
|
let classes = {};
|
||||||
|
let notes = [];
|
||||||
let classCounter = 0;
|
let classCounter = 0;
|
||||||
|
|
||||||
let funs = [];
|
let funs = [];
|
||||||
@ -84,6 +85,7 @@ export const lookUpDomId = function (id) {
|
|||||||
export const clear = function () {
|
export const clear = function () {
|
||||||
relations = [];
|
relations = [];
|
||||||
classes = {};
|
classes = {};
|
||||||
|
notes = [];
|
||||||
funs = [];
|
funs = [];
|
||||||
funs.push(setupToolTips);
|
funs.push(setupToolTips);
|
||||||
commonClear();
|
commonClear();
|
||||||
@ -100,6 +102,10 @@ export const getRelations = function () {
|
|||||||
return relations;
|
return relations;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getNotes = function () {
|
||||||
|
return notes;
|
||||||
|
};
|
||||||
|
|
||||||
export const addRelation = function (relation) {
|
export const addRelation = function (relation) {
|
||||||
log.debug('Adding relation: ' + JSON.stringify(relation));
|
log.debug('Adding relation: ' + JSON.stringify(relation));
|
||||||
addClass(relation.id1);
|
addClass(relation.id1);
|
||||||
@ -170,6 +176,15 @@ export const addMembers = function (className, members) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const addNote = function (text, className) {
|
||||||
|
const note = {
|
||||||
|
id: `note${notes.length}`,
|
||||||
|
class: className,
|
||||||
|
text: text,
|
||||||
|
};
|
||||||
|
notes.push(note);
|
||||||
|
};
|
||||||
|
|
||||||
export const cleanupLabel = function (label) {
|
export const cleanupLabel = function (label) {
|
||||||
if (label.substring(0, 1) === ':') {
|
if (label.substring(0, 1) === ':') {
|
||||||
return common.sanitizeText(label.substr(1).trim(), configApi.getConfig());
|
return common.sanitizeText(label.substr(1).trim(), configApi.getConfig());
|
||||||
@ -375,7 +390,9 @@ export default {
|
|||||||
clear,
|
clear,
|
||||||
getClass,
|
getClass,
|
||||||
getClasses,
|
getClasses,
|
||||||
|
getNotes,
|
||||||
addAnnotation,
|
addAnnotation,
|
||||||
|
addNote,
|
||||||
getRelations,
|
getRelations,
|
||||||
addRelation,
|
addRelation,
|
||||||
getDirection,
|
getDirection,
|
||||||
|
@ -529,6 +529,16 @@ foo()
|
|||||||
|
|
||||||
parser.parse(str);
|
parser.parse(str);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle "note for"', function () {
|
||||||
|
const str = 'classDiagram\n' + 'Class11 <|.. Class12\n' + 'note for Class11 "test"\n';
|
||||||
|
parser.parse(str);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle "note"', function () {
|
||||||
|
const str = 'classDiagram\n' + 'note "test"\n';
|
||||||
|
parser.parse(str);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when fetching data from a classDiagram graph it', function () {
|
describe('when fetching data from a classDiagram graph it', function () {
|
||||||
|
@ -134,6 +134,99 @@ export const addClasses = function (classes, g, _id, diagObj) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function that adds the additional vertices (notes) found during parsing to the graph to be rendered.
|
||||||
|
*
|
||||||
|
* @param {{text: string; class: string; placement: number}[]} notes
|
||||||
|
* Object containing the additional vertices (notes).
|
||||||
|
* @param {SVGGElement} g The graph that is to be drawn.
|
||||||
|
* @param {number} startEdgeId starting index for note edge
|
||||||
|
* @param classes
|
||||||
|
*/
|
||||||
|
export const addNotes = function (notes, g, startEdgeId, classes) {
|
||||||
|
log.info(notes);
|
||||||
|
|
||||||
|
// Iterate through each item in the vertex object (containing all the vertices found) in the graph definition
|
||||||
|
notes.forEach(function (note, i) {
|
||||||
|
const vertex = note;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variable for storing the classes for the vertex
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
let cssNoteStr = '';
|
||||||
|
|
||||||
|
const styles = { labelStyle: '', style: '' };
|
||||||
|
|
||||||
|
// Use vertex id as text in the box if no text is provided by the graph definition
|
||||||
|
let vertexText = vertex.text;
|
||||||
|
|
||||||
|
let radious = 0;
|
||||||
|
let _shape = 'note';
|
||||||
|
// Add the node
|
||||||
|
g.setNode(vertex.id, {
|
||||||
|
labelStyle: styles.labelStyle,
|
||||||
|
shape: _shape,
|
||||||
|
labelText: sanitizeText(vertexText),
|
||||||
|
noteData: vertex,
|
||||||
|
rx: radious,
|
||||||
|
ry: radious,
|
||||||
|
class: cssNoteStr,
|
||||||
|
style: styles.style,
|
||||||
|
id: vertex.id,
|
||||||
|
domId: vertex.id,
|
||||||
|
tooltip: '',
|
||||||
|
type: 'note',
|
||||||
|
padding: getConfig().flowchart.padding,
|
||||||
|
});
|
||||||
|
|
||||||
|
log.info('setNode', {
|
||||||
|
labelStyle: styles.labelStyle,
|
||||||
|
shape: _shape,
|
||||||
|
labelText: vertexText,
|
||||||
|
rx: radious,
|
||||||
|
ry: radious,
|
||||||
|
style: styles.style,
|
||||||
|
id: vertex.id,
|
||||||
|
type: 'note',
|
||||||
|
padding: getConfig().flowchart.padding,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!vertex.class || !(vertex.class in classes)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const edgeId = startEdgeId + i;
|
||||||
|
const edgeData = {};
|
||||||
|
//Set relationship style and line type
|
||||||
|
edgeData.classes = 'relation';
|
||||||
|
edgeData.pattern = 'dotted';
|
||||||
|
|
||||||
|
edgeData.id = `edgeNote${edgeId}`;
|
||||||
|
// Set link type for rendering
|
||||||
|
edgeData.arrowhead = 'none';
|
||||||
|
|
||||||
|
log.info(`Note edge: ${JSON.stringify(edgeData)}, ${JSON.stringify(vertex)}`);
|
||||||
|
//Set edge extra labels
|
||||||
|
edgeData.startLabelRight = '';
|
||||||
|
edgeData.endLabelLeft = '';
|
||||||
|
|
||||||
|
//Set relation arrow types
|
||||||
|
edgeData.arrowTypeStart = 'none';
|
||||||
|
edgeData.arrowTypeEnd = 'none';
|
||||||
|
let style = 'fill:none';
|
||||||
|
let labelStyle = '';
|
||||||
|
|
||||||
|
edgeData.style = style;
|
||||||
|
edgeData.labelStyle = labelStyle;
|
||||||
|
|
||||||
|
edgeData.curve = interpolateToCurve(conf.curve, curveLinear);
|
||||||
|
|
||||||
|
// Add the edge to the graph
|
||||||
|
g.setEdge(vertex.id, vertex.class, edgeData, edgeId);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add edges to graph based on parsed graph definition
|
* Add edges to graph based on parsed graph definition
|
||||||
*
|
*
|
||||||
@ -305,10 +398,12 @@ export const draw = function (text, id, _version, diagObj) {
|
|||||||
// Fetch the vertices/nodes and edges/links from the parsed graph definition
|
// Fetch the vertices/nodes and edges/links from the parsed graph definition
|
||||||
const classes = diagObj.db.getClasses();
|
const classes = diagObj.db.getClasses();
|
||||||
const relations = diagObj.db.getRelations();
|
const relations = diagObj.db.getRelations();
|
||||||
|
const notes = diagObj.db.getNotes();
|
||||||
|
|
||||||
log.info(relations);
|
log.info(relations);
|
||||||
addClasses(classes, g, id, diagObj);
|
addClasses(classes, g, id, diagObj);
|
||||||
addRelations(relations, g);
|
addRelations(relations, g);
|
||||||
|
addNotes(notes, g, relations.length + 1, classes);
|
||||||
|
|
||||||
// Add custom shapes
|
// Add custom shapes
|
||||||
// flowChartShapes.addToRenderV2(addShape);
|
// flowChartShapes.addToRenderV2(addShape);
|
||||||
|
@ -208,12 +208,42 @@ export const draw = function (text, id, _version, diagObj) {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const notes = diagObj.db.getNotes();
|
||||||
|
notes.forEach(function (note) {
|
||||||
|
log.debug(`Adding note: ${JSON.stringify(note)}`);
|
||||||
|
const node = svgDraw.drawNote(diagram, note, conf, diagObj);
|
||||||
|
idCache[node.id] = node;
|
||||||
|
|
||||||
|
// Add nodes to the graph. The first argument is the node id. The second is
|
||||||
|
// metadata about the node. In this case we're going to add labels to each of
|
||||||
|
// our nodes.
|
||||||
|
g.setNode(node.id, node);
|
||||||
|
if (note.class && note.class in classes) {
|
||||||
|
g.setEdge(
|
||||||
|
note.id,
|
||||||
|
getGraphId(note.class),
|
||||||
|
{
|
||||||
|
relation: {
|
||||||
|
id1: note.id,
|
||||||
|
id2: note.class,
|
||||||
|
relation: {
|
||||||
|
type1: 'none',
|
||||||
|
type2: 'none',
|
||||||
|
lineType: 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'DEFAULT'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
dagre.layout(g);
|
dagre.layout(g);
|
||||||
g.nodes().forEach(function (v) {
|
g.nodes().forEach(function (v) {
|
||||||
if (typeof v !== 'undefined' && typeof g.node(v) !== 'undefined') {
|
if (typeof v !== 'undefined' && typeof g.node(v) !== 'undefined') {
|
||||||
log.debug('Node ' + v + ': ' + JSON.stringify(g.node(v)));
|
log.debug('Node ' + v + ': ' + JSON.stringify(g.node(v)));
|
||||||
root
|
root
|
||||||
.select('#' + diagObj.db.lookUpDomId(v))
|
.select('#' + (diagObj.db.lookUpDomId(v) || v))
|
||||||
.attr(
|
.attr(
|
||||||
'transform',
|
'transform',
|
||||||
'translate(' +
|
'translate(' +
|
||||||
|
@ -56,6 +56,8 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
|
|||||||
"callback" return 'CALLBACK';
|
"callback" return 'CALLBACK';
|
||||||
"link" return 'LINK';
|
"link" return 'LINK';
|
||||||
"click" return 'CLICK';
|
"click" return 'CLICK';
|
||||||
|
"note for" return 'NOTE_FOR';
|
||||||
|
"note" return 'NOTE';
|
||||||
"<<" return 'ANNOTATION_START';
|
"<<" return 'ANNOTATION_START';
|
||||||
">>" return 'ANNOTATION_END';
|
">>" return 'ANNOTATION_END';
|
||||||
[~] this.begin("generic");
|
[~] this.begin("generic");
|
||||||
@ -263,6 +265,7 @@ statement
|
|||||||
| annotationStatement
|
| annotationStatement
|
||||||
| clickStatement
|
| clickStatement
|
||||||
| cssClassStatement
|
| cssClassStatement
|
||||||
|
| noteStatement
|
||||||
| directive
|
| directive
|
||||||
| direction
|
| direction
|
||||||
| acc_title acc_title_value { $$=$2.trim();yy.setAccTitle($$); }
|
| acc_title acc_title_value { $$=$2.trim();yy.setAccTitle($$); }
|
||||||
@ -300,6 +303,11 @@ relationStatement
|
|||||||
| className STR relation STR className { $$ = {id1:$1, id2:$5, relation:$3, relationTitle1:$2, relationTitle2:$4} }
|
| className STR relation STR className { $$ = {id1:$1, id2:$5, relation:$3, relationTitle1:$2, relationTitle2:$4} }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
noteStatement
|
||||||
|
: NOTE_FOR className noteText { yy.addNote($3, $2); }
|
||||||
|
| NOTE noteText { yy.addNote($2); }
|
||||||
|
;
|
||||||
|
|
||||||
relation
|
relation
|
||||||
: relationType lineType relationType { $$={type1:$1,type2:$3,lineType:$2}; }
|
: relationType lineType relationType { $$={type1:$1,type2:$3,lineType:$2}; }
|
||||||
| lineType relationType { $$={type1:'none',type2:$2,lineType:$1}; }
|
| lineType relationType { $$={type1:'none',type2:$2,lineType:$1}; }
|
||||||
@ -351,4 +359,6 @@ alphaNumToken : UNICODE_TEXT | NUM | ALPHA;
|
|||||||
|
|
||||||
classLiteralName : BQUOTE_STR;
|
classLiteralName : BQUOTE_STR;
|
||||||
|
|
||||||
|
noteText : STR;
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
@ -80,6 +80,10 @@ g.classGroup line {
|
|||||||
stroke-dasharray: 3;
|
stroke-dasharray: 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dotted-line{
|
||||||
|
stroke-dasharray: 1 2;
|
||||||
|
}
|
||||||
|
|
||||||
#compositionStart, .composition {
|
#compositionStart, .composition {
|
||||||
fill: ${options.lineColor} !important;
|
fill: ${options.lineColor} !important;
|
||||||
stroke: ${options.lineColor} !important;
|
stroke: ${options.lineColor} !important;
|
||||||
|
@ -9,13 +9,13 @@ export const drawEdge = function (elem, path, relation, conf, diagObj) {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case diagObj.db.relationType.AGGREGATION:
|
case diagObj.db.relationType.AGGREGATION:
|
||||||
return 'aggregation';
|
return 'aggregation';
|
||||||
case diagObj.db.EXTENSION:
|
case diagObj.db.relationType.EXTENSION:
|
||||||
return 'extension';
|
return 'extension';
|
||||||
case diagObj.db.COMPOSITION:
|
case diagObj.db.relationType.COMPOSITION:
|
||||||
return 'composition';
|
return 'composition';
|
||||||
case diagObj.db.DEPENDENCY:
|
case diagObj.db.relationType.DEPENDENCY:
|
||||||
return 'dependency';
|
return 'dependency';
|
||||||
case diagObj.db.LOLLIPOP:
|
case diagObj.db.relationType.LOLLIPOP:
|
||||||
return 'lollipop';
|
return 'lollipop';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -55,6 +55,9 @@ export const drawEdge = function (elem, path, relation, conf, diagObj) {
|
|||||||
if (relation.relation.lineType == 1) {
|
if (relation.relation.lineType == 1) {
|
||||||
svgPath.attr('class', 'relation dashed-line');
|
svgPath.attr('class', 'relation dashed-line');
|
||||||
}
|
}
|
||||||
|
if (relation.relation.lineType == 10) {
|
||||||
|
svgPath.attr('class', 'relation dotted-line');
|
||||||
|
}
|
||||||
if (relation.relation.type1 !== 'none') {
|
if (relation.relation.type1 !== 'none') {
|
||||||
svgPath.attr(
|
svgPath.attr(
|
||||||
'marker-start',
|
'marker-start',
|
||||||
@ -288,6 +291,69 @@ export const drawClass = function (elem, classDef, conf, diagObj) {
|
|||||||
return classInfo;
|
return classInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a note diagram
|
||||||
|
*
|
||||||
|
* @param {SVGSVGElement} elem The element to draw it into
|
||||||
|
* @param {{id: string; text: string; class: string;}} note
|
||||||
|
* @param conf
|
||||||
|
* @param diagObj
|
||||||
|
* @todo Add more information in the JSDOC here
|
||||||
|
*/
|
||||||
|
export const drawNote = function (elem, note, conf, diagObj) {
|
||||||
|
log.debug('Rendering note ', note, conf);
|
||||||
|
|
||||||
|
const id = note.id;
|
||||||
|
const noteInfo = {
|
||||||
|
id: id,
|
||||||
|
text: note.text,
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
// add class group
|
||||||
|
const g = elem.append('g').attr('id', id).attr('class', 'classGroup');
|
||||||
|
|
||||||
|
// add text
|
||||||
|
let text = g
|
||||||
|
.append('text')
|
||||||
|
.attr('y', conf.textHeight + conf.padding)
|
||||||
|
.attr('x', 0);
|
||||||
|
|
||||||
|
const lines = JSON.parse(`"${note.text}"`).split('\n');
|
||||||
|
|
||||||
|
lines.forEach(function (line) {
|
||||||
|
log.debug(`Adding line: ${line}`);
|
||||||
|
text.append('tspan').text(line).attr('class', 'title').attr('dy', conf.textHeight);
|
||||||
|
});
|
||||||
|
|
||||||
|
const noteBox = g.node().getBBox();
|
||||||
|
|
||||||
|
const rect = g
|
||||||
|
.insert('rect', ':first-child')
|
||||||
|
.attr('x', 0)
|
||||||
|
.attr('y', 0)
|
||||||
|
.attr('width', noteBox.width + 2 * conf.padding)
|
||||||
|
.attr(
|
||||||
|
'height',
|
||||||
|
noteBox.height + lines.length * conf.textHeight + conf.padding + 0.5 * conf.dividerMargin
|
||||||
|
);
|
||||||
|
|
||||||
|
const rectWidth = rect.node().getBBox().width;
|
||||||
|
|
||||||
|
// Center title
|
||||||
|
// We subtract the width of each text element from the class box width and divide it by 2
|
||||||
|
text.node().childNodes.forEach(function (x) {
|
||||||
|
x.setAttribute('x', (rectWidth - x.getBBox().width) / 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
noteInfo.width = rectWidth;
|
||||||
|
noteInfo.height =
|
||||||
|
noteBox.height + lines.length * conf.textHeight + conf.padding + 0.5 * conf.dividerMargin;
|
||||||
|
|
||||||
|
return noteInfo;
|
||||||
|
};
|
||||||
|
|
||||||
export const parseMember = function (text) {
|
export const parseMember = function (text) {
|
||||||
const fieldRegEx = /^(\+|-|~|#)?(\w+)(~\w+~|\[\])?\s+(\w+) *(\*|\$)?$/;
|
const fieldRegEx = /^(\+|-|~|#)?(\w+)(~\w+~|\[\])?\s+(\w+) *(\*|\$)?$/;
|
||||||
const methodRegEx = /^([+|\-|~|#])?(\w+) *\( *(.*)\) *(\*|\$)? *(\w*[~|[\]]*\s*\w*~?)$/;
|
const methodRegEx = /^([+|\-|~|#])?(\w+) *\( *(.*)\) *(\*|\$)? *(\w*[~|[\]]*\s*\w*~?)$/;
|
||||||
@ -439,5 +505,6 @@ const parseClassifier = function (classifier) {
|
|||||||
export default {
|
export default {
|
||||||
drawClass,
|
drawClass,
|
||||||
drawEdge,
|
drawEdge,
|
||||||
|
drawNote,
|
||||||
parseMember,
|
parseMember,
|
||||||
};
|
};
|
||||||
|
@ -9,7 +9,9 @@ Mermaid can render class diagrams.
|
|||||||
|
|
||||||
```mermaid-example
|
```mermaid-example
|
||||||
classDiagram
|
classDiagram
|
||||||
|
note "From Duck till Zebra"
|
||||||
Animal <|-- Duck
|
Animal <|-- Duck
|
||||||
|
note for Duck "can fly\ncan swim\ncan dive\ncan help in debugging"
|
||||||
Animal <|-- Fish
|
Animal <|-- Fish
|
||||||
Animal <|-- Zebra
|
Animal <|-- Zebra
|
||||||
Animal : +int age
|
Animal : +int age
|
||||||
@ -375,6 +377,10 @@ click className href "url" "tooltip"
|
|||||||
- (_optional_) tooltip is a string to be displayed when hovering over element (note: The styles of the tooltip are set by the class .mermaidTooltip.)
|
- (_optional_) tooltip is a string to be displayed when hovering over element (note: The styles of the tooltip are set by the class .mermaidTooltip.)
|
||||||
- note: callback function will be called with the nodeId as parameter.
|
- note: callback function will be called with the nodeId as parameter.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
It is possible to add notes on digram using `note "line1\nline2"` or note for class using `note for class "line1\nline2"`
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
_URL Link:_
|
_URL Link:_
|
||||||
|
@ -322,15 +322,10 @@ function calcLabelPosition(points: Point[]): Point {
|
|||||||
|
|
||||||
const calcCardinalityPosition = (isRelationTypePresent, points, initialPosition) => {
|
const calcCardinalityPosition = (isRelationTypePresent, points, initialPosition) => {
|
||||||
let prevPoint;
|
let prevPoint;
|
||||||
log.info('our points', points);
|
log.info(`our points ${JSON.stringify(points)}`);
|
||||||
if (points[0] !== initialPosition) {
|
if (points[0] !== initialPosition) {
|
||||||
points = points.reverse();
|
points = points.reverse();
|
||||||
}
|
}
|
||||||
points.forEach((point) => {
|
|
||||||
totalDistance += distance(point, prevPoint);
|
|
||||||
prevPoint = point;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Traverse only 25 total distance along points to find cardinality point
|
// Traverse only 25 total distance along points to find cardinality point
|
||||||
const distanceToCardinalityPoint = 25;
|
const distanceToCardinalityPoint = 25;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user