mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-08-15 06:19:24 +02:00
Updated the code to include nested namespaces for class diagrams
This commit is contained in:
@@ -1 +1 @@
|
||||
./packages/mermaid/src/docs/community/contributing.md
|
||||
./packages/mermaid/src/docs/community/contributing.md
|
||||
|
BIN
cypress/downloads/downloads.htm
Normal file
BIN
cypress/downloads/downloads.htm
Normal file
Binary file not shown.
@@ -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({
|
||||
|
@@ -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(`
|
||||
[
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user