Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated the code to include nested namespaces for class diagrams #5849

Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
cf45a35
Updated the code to include nested namespaces for class diagrams
ReneLombard Sep 9, 2024
2b8ef76
executed 'pnpm -w run lint:fix' and checked in fixed files
ReneLombard Sep 10, 2024
e8fdc96
Update downloads.htm
ReneLombard Sep 11, 2024
6de7f1b
Updated the package.json files
ReneLombard Sep 11, 2024
88607e8
Merge branch 'bug/5487-add-support-for-nested-classes' of https://git…
ReneLombard Sep 12, 2024
bff9f65
Merge branch 'develop' into bug/5487-add-support-for-nested-classes
ReneLombard Sep 12, 2024
6c5b7ce
Updated the changelog
ReneLombard Sep 12, 2024
aae9db9
Merge branch 'bug/5487-add-support-for-nested-classes' of https://git…
ReneLombard Sep 12, 2024
a3145a3
Updated the downloads.html
ReneLombard Sep 12, 2024
c97716e
Update CONTRIBUTING.md
ReneLombard Sep 12, 2024
3c49c00
Update package.json
ReneLombard Sep 12, 2024
a6b8776
Reverted pnpm-lock
ReneLombard Sep 12, 2024
59991b7
Reverted pnpm-lock
ReneLombard Sep 12, 2024
1d8f524
Manually updated the classchart
ReneLombard Sep 12, 2024
92aa285
Removed comment from classDiagram.jison
ReneLombard Sep 12, 2024
e26a38b
Reverted teh CONTRIBUTING.md
ReneLombard Sep 12, 2024
af2340d
Merge branch 'develop' into bug/5487-add-support-for-nested-classes
ReneLombard Sep 17, 2024
4fc9028
Merge branch 'develop' into bug/5487-add-support-for-nested-classes
ReneLombard Sep 23, 2024
3e807e0
Merge branch 'develop' into bug/5487-add-support-for-nested-classes
ReneLombard Sep 25, 2024
c5bcd2f
Reworked code comments
ReneLombard Oct 2, 2024
a4878d0
Merge branch 'bug/5487-add-support-for-nested-classes' of https://git…
ReneLombard Oct 2, 2024
07d7704
Merge branch 'develop' into bug/5487-add-support-for-nested-classes
ReneLombard Oct 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .changeset/add-nested-namespaces.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
'@mermaid': patch
---

Fixed an issue when the mermaid classdiagram crashes when adding a . to the namespace.
Forexample

```mermaid
classDiagram
namespace Company.Project.Module {
class GenericClass~T~ {
+addItem(item: T)
+getItem() T
}
}
```
Empty file added cypress/downloads/downloads.htm
sidharthv96 marked this conversation as resolved.
Show resolved Hide resolved
Empty file.
85 changes: 71 additions & 14 deletions demos/classchart.html
Original file line number Diff line number Diff line change
Expand Up @@ -159,30 +159,87 @@ <h1>Class diagram demos</h1>
class People List~List~Person~~
</pre>
<hr />

<pre class="mermaid">
classDiagram
A1 --> B1
namespace A {
class A1 {
+foo : string
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)
}
class A2 {
+bar : int
}
namespace Company.Project.Module {
class Admin {
+generateReport()
}
}
namespace B {
class B1 {
+foo : bool
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 B2 {
+bar : float
class Report {
+generatePDF(reportData: List)
+generateCSV(reportData: List)
}
}
A2 --> B2
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({
Expand Down
124 changes: 104 additions & 20 deletions packages/mermaid/src/diagrams/class/classDiagram.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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`';

Expand Down Expand Up @@ -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(`
[
Expand Down
8 changes: 5 additions & 3 deletions packages/mermaid/src/diagrams/class/parser/classDiagram.jison
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
| classLiteralName { $$=$1; }
| alphaNumToken className { $$=$1+$2; }
| alphaNumToken GENERICTYPE { $$=$1+'~'+$2+'~'; }
Expand All @@ -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
Expand Down
Loading