Updated the code to include nested namespaces for class diagrams

This commit is contained in:
René Lombard
2024-09-09 17:20:25 +02:00
parent dd0304387e
commit cf45a35971
5 changed files with 190 additions and 45 deletions

View File

@@ -1 +1 @@
./packages/mermaid/src/docs/community/contributing.md
./packages/mermaid/src/docs/community/contributing.md

Binary file not shown.

View File

@@ -159,30 +159,89 @@
class People List~List~Person~~
</pre>
<hr />
<pre class="mermaid">
classDiagram
A1 --> B1
namespace A {
class A1 {
+foo : string
}
class A2 {
+bar : int
}
}
namespace B {
class B1 {
+foo : bool
}
class B2 {
+bar : float
}
}
A2 --> B2
classDiagram
namespace Company.Project.Module {
class GenericClass~T~ {
+addItem(item: T)
+getItem() T
}
}
</pre>
<hr />
<pre class="mermaid">
classDiagram
namespace Company.Project.Module.SubModule {
class Report {
+generatePDF(data: List)
+generateCSV(data: List)
}
}
namespace Company.Project.Module {
class Admin {
+generateReport()
}
}
Admin --> Report : generates
</pre>
<pre class="mermaid">
classDiagram
namespace Company.Project.Module {
class User {
+login(username: String, password: String)
+logout()
}
class Admin {
+addUser(user: User)
+removeUser(user: User)
+generateReport()
}
class Report {
+generatePDF(reportData: List)
+generateCSV(reportData: List)
}
}
Admin --> User : manages
Admin --> Report : generates
</pre>
<hr />
<pre class="mermaid">
classDiagram
namespace Shapes {
class Shape {
+calculateArea() double
}
class Circle {
+double radius
}
class Square {
+double side
}
}
Shape <|-- Circle
Shape <|-- Square
namespace Vehicles {
class Vehicle {
+String brand
}
class Car {
+int horsepower
}
class Bike {
+boolean hasGears
}
}
Vehicle <|-- Car
Vehicle <|-- Bike
Car --> Circle : "Logo Shape"
Bike --> Square : "Logo Shape"
</pre>
<script type="module">
import mermaid from './mermaid.esm.mjs';
mermaid.initialize({

View File

@@ -14,6 +14,78 @@ describe('given a basic class diagram, ', function () {
classDb.clear();
parser.yy = classDb;
});
it('should handle classes within namespaces', () => {
const str = `classDiagram
namespace Company.Project {
class User {
+login(username: String, password: String)
+logout()
}
}
namespace Company.Project.Module {
class Admin {
+addUser(user: User)
+removeUser(user: User)
}
}`;
parser.parse(str);
const user = classDb.getClass('User');
const admin = classDb.getClass('Admin');
// Check if the classes are correctly registered under their respective namespaces
expect(user.parent).toBe('Company.Project');
expect(admin.parent).toBe('Company.Project.Module');
expect(user.methods.length).toBe(2);
expect(admin.methods.length).toBe(2);
});
it('should handle generic classes within namespaces', () => {
const str = `classDiagram
namespace Company.Project.Module {
class GenericClass~T~ {
+addItem(item: T)
+getItem() T
}
}`;
parser.parse(str);
const genericClass = classDb.getClass('GenericClass');
expect(genericClass.type).toBe('T');
expect(genericClass.methods[0].getDisplayDetails().displayText).toBe('+addItem(item: T)');
expect(genericClass.methods[1].getDisplayDetails().displayText).toBe('+getItem() : T');
});
it('should handle nested namespaces and relationships', () => {
const str = ` classDiagram
namespace Company.Project.Module.SubModule {
class Report {
+generatePDF(data: List)
+generateCSV(data: List)
}
}
namespace Company.Project.Module {
class Admin {
+generateReport()
}
}
Admin --> Report : generates`;
parser.parse(str);
const report = classDb.getClass('Report');
const admin = classDb.getClass('Admin');
const relations = classDb.getRelations();
expect(report.parent).toBe('Company.Project.Module.SubModule');
expect(admin.parent).toBe('Company.Project.Module');
expect(relations[0].id1).toBe('Admin');
expect(relations[0].id2).toBe('Report');
expect(relations[0].title).toBe('generates');
});
it('should handle accTitle and accDescr', function () {
const str = `classDiagram
accTitle: My Title
@@ -48,6 +120,22 @@ describe('given a basic class diagram, ', function () {
}
});
it('should handle fully qualified class names in relationships', () => {
const str = `classDiagram
namespace Company.Project.Module {
class User
class Admin
}
Admin --> User : manages`;
parser.parse(str);
const relations = classDb.getRelations();
expect(relations[0].id1).toBe('Admin');
expect(relations[0].id2).toBe('User');
expect(relations[0].title).toBe('manages');
});
it('should handle backquoted class names', function () {
const str = 'classDiagram\n' + 'class `Car`';
@@ -393,27 +481,23 @@ class C13["With Città foreign language"]
Student "1" --o "1" IdCard : carries
Student "1" --o "1" Bike : rides`);
const studentClass = classDb.getClasses().get('Student');
// Check that the important properties match, but ignore the domId
expect(studentClass).toMatchObject({
id: 'Student',
label: 'Student',
members: [
expect.objectContaining({
id: 'idCard : IdCard',
visibility: '-',
}),
],
methods: [],
annotations: [],
cssClasses: [],
});
expect(classDb.getClasses().size).toBe(3);
expect(classDb.getClasses().get('Student')).toMatchInlineSnapshot(`
{
"annotations": [],
"cssClasses": [],
"domId": "classId-Student-134",
"id": "Student",
"label": "Student",
"members": [
ClassMember {
"classifier": "",
"id": "idCard : IdCard",
"memberType": "attribute",
"visibility": "-",
},
],
"methods": [],
"styles": [],
"type": "",
}
`);
expect(classDb.getRelations().length).toBe(2);
expect(classDb.getRelations()).toMatchInlineSnapshot(`
[

View File

@@ -241,11 +241,13 @@ classLabel
namespaceName
: alphaNumToken { $$=$1; }
| alphaNumToken DOT namespaceName { $$=$1+'.'+$3; }
| alphaNumToken namespaceName { $$=$1+$2; }
;
className
: alphaNumToken { $$=$1; }
| alphaNumToken DOT className { $$=$1+'.'+$3; } // Allow class names with dots
| classLiteralName { $$=$1; }
| alphaNumToken className { $$=$1+$2; }
| alphaNumToken GENERICTYPE { $$=$1+'~'+$2+'~'; }
@@ -270,12 +272,12 @@ statement
;
namespaceStatement
: namespaceIdentifier STRUCT_START classStatements STRUCT_STOP {yy.addClassesToNamespace($1, $3);}
| namespaceIdentifier STRUCT_START NEWLINE classStatements STRUCT_STOP {yy.addClassesToNamespace($1, $4);}
: namespaceIdentifier STRUCT_START classStatements STRUCT_STOP { yy.addClassesToNamespace($1, $3); }
| namespaceIdentifier STRUCT_START NEWLINE classStatements STRUCT_STOP { yy.addClassesToNamespace($1, $4); }
;
namespaceIdentifier
: NAMESPACE namespaceName {$$=$2; yy.addNamespace($2);}
: NAMESPACE namespaceName { $$=$2; yy.addNamespace($2); }
;
classStatements