Compare commits

...

4 Commits

Author SHA1 Message Date
darshanr0107
eb81bdd617 Merge branch 'develop' into 6587-class-diagram-stereotype-styling 2025-07-16 17:29:22 +05:30
darshanr0107
faa03bb4b2 chore: resolve PR comments
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-07-16 15:15:13 +05:30
darshanr0107
fbf1085b57 added changeset 2025-07-10 19:16:34 +05:30
darshanr0107
e2b7f7fc84 add support for stereotype annotations for class diagrams 2025-07-10 19:03:31 +05:30
4 changed files with 133 additions and 4 deletions

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
fix: Added support for styling class diagram elements based on stereotype annotations

View File

@@ -1028,4 +1028,88 @@ class C13["With Città foreign language"]
{ logLevel: 1, htmlLabels: true }
);
});
it('should render a full class diagram using interface annotation', () => {
imgSnapshotTest(
`
classDiagram
Class01 <|-- AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class03 "0" *-- "0..n" Class04
Class05 "1" o-- "many" Class06
Class07 .. Class08
Class09 "many" --> "1" C2 : Where am i?
Class09 "0" --* "1..n" C3
Class09 --|> Class07
Class07 : equals()
Class07 : Object[] elementData
Class01 : #size()
Class01 : -int chimp
Class01 : +int gorilla
Class08 <--> C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
size()
}
`,
{ logLevel: 1, htmlLabels: true }
);
});
it('should render a full class diagram using abstract annotation', () => {
imgSnapshotTest(
`
classDiagram
Class01 <|-- AveryLongClass : Cool
&lt;&lt;abstract&gt;&gt; Class01
Class03 "0" *-- "0..n" Class04
Class05 "1" o-- "many" Class06
Class07 .. Class08
Class09 "many" --> "1" C2 : Where am i?
Class09 "0" --* "1..n" C3
Class09 --|> Class07
Class07 : equals()
Class07 : Object[] elementData
Class01 : #size()
Class01 : -int chimp
Class01 : +int gorilla
Class08 <--> C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
size()
}
`,
{ logLevel: 1, htmlLabels: true }
);
});
it('should render a full class diagram using enumeration annotation', () => {
imgSnapshotTest(
`
classDiagram
Class01 <|-- AveryLongClass : Cool
&lt;&lt;enumeration&gt;&gt; Class01
Class03 "0" *-- "0..n" Class04
Class05 "1" o-- "many" Class06
Class07 .. Class08
Class09 "many" --> "1" C2 : Where am i?
Class09 "0" --* "1..n" C3
Class09 --|> Class07
Class07 : equals()
Class07 : Object[] elementData
Class01 : #size()
Class01 : -int chimp
Class01 : +int gorilla
Class08 <--> C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
size()
}
`,
{ logLevel: 1, htmlLabels: true }
);
});
});

View File

@@ -36,15 +36,41 @@ export async function textHelper<T extends SVGGraphicsElement>(
annotationGroup = shapeSvg.insert('g').attr('class', 'annotation-group text');
if (node.annotations.length > 0) {
const annotation = node.annotations[0];
await addText(annotationGroup, { text: `«${annotation}»` } as unknown as ClassMember, 0);
await addText(annotationGroup, { text: `` } as unknown as ClassMember, 0);
const annotationGroupBBox = annotationGroup.node()!.getBBox();
annotationGroupHeight = annotationGroupBBox.height;
}
labelGroup = shapeSvg.insert('g').attr('class', 'label-group text');
await addText(labelGroup, node, 0, ['font-weight: bolder']);
// Determine styling based on annotations
let labelStyles = ['font-weight: bolder']; // Default bold style
let labelClass = '';
if (node.annotations && node.annotations.length > 0) {
const annotation = node.annotations[0].toLowerCase();
switch (annotation) {
case 'abstract':
labelClass = 'abstract';
labelStyles = [];
break;
case 'enumeration':
labelClass = 'enumeration';
labelStyles = [];
break;
case 'interface':
labelClass = 'interface';
labelStyles = [];
break;
default:
labelStyles = ['font-weight: bolder'];
break;
}
}
// Apply the CSS class to the label group
labelGroup.attr('class', `label-group text classTitle ${labelClass}`);
await addText(labelGroup, node, 0, labelStyles);
const labelGroupBBox = labelGroup.node()!.getBBox();
labelGroupHeight = labelGroupBBox.height;
@@ -71,7 +97,7 @@ export async function textHelper<T extends SVGGraphicsElement>(
// Center annotation
if (annotationGroup !== null) {
const annotationGroupBBox = annotationGroup.node()!.getBBox();
annotationGroup.attr('transform', `translate(${-annotationGroupBBox.width / 2})`);
annotationGroup.attr('transform', `translate(${-annotationGroupBBox.width / 2}, 0)`);
}
// Adjust label

View File

@@ -148,6 +148,20 @@ g.classGroup line {
stroke: ${options.lineColor} !important;
stroke-width: 1;
}
.classTitle.abstract {
font-style: italic;
font-weight: normal;
}
.classTitle.enumeration {
text-decoration: underline;
font-weight: normal;
}
.classTitle.interface {
font-weight: bold;
}
.edgeTerminals {
font-size: 11px;