feat: add support for link statements within namespace blocks in class diagrams

Resolves #4700
This commit is contained in:
Justin Greywolf
2025-10-11 14:13:48 -07:00
parent d80a638e55
commit 709880178e
3 changed files with 58 additions and 2 deletions

View File

@@ -88,6 +88,50 @@ describe('given a basic class diagram, ', function () {
expect(relations[0].title).toBe('generates');
});
it('should handle link statements within namespaces', function () {
spyOn(classDb, 'setLink');
const str = `classDiagram
namespace MyNamespace {
class UserService {
+createUser()
+deleteUser()
}
class PaymentService {
+processPayment()
+refund()
}
link UserService "https://example.com/user-service"
link PaymentService "https://example.com/payment-service" "Payment Service Documentation"
}`;
parser.parse(str);
// Verify setLink was called for both classes
expect(classDb.setLink).toHaveBeenCalledWith(
'UserService',
'https://example.com/user-service'
);
expect(classDb.setLink).toHaveBeenCalledWith(
'PaymentService',
'https://example.com/payment-service'
);
// Verify the classes have the correct links and are in the namespace
const userService = classDb.getClass('UserService');
const paymentService = classDb.getClass('PaymentService');
expect(userService.parent).toBe('MyNamespace');
expect(userService.link).toBe('https://example.com/user-service');
expect(userService.cssClasses).toBe('default clickable');
expect(paymentService.parent).toBe('MyNamespace');
expect(paymentService.link).toBe('https://example.com/payment-service');
expect(paymentService.tooltip).toBe('Payment Service Documentation');
expect(paymentService.cssClasses).toBe('default clickable');
});
it('should handle accTitle and accDescr', function () {
const str = `classDiagram
accTitle: My Title

View File

@@ -275,14 +275,25 @@ 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 namespaceBodyStatements STRUCT_STOP { yy.addClassesToNamespace($1, $3); }
| namespaceIdentifier STRUCT_START NEWLINE namespaceBodyStatements STRUCT_STOP { yy.addClassesToNamespace($1, $4); }
;
namespaceIdentifier
: NAMESPACE namespaceName { $$=$2; yy.addNamespace($2); }
;
namespaceBodyStatements
: namespaceBodyStatement { $$=[$1].filter(s => s !== null); }
| namespaceBodyStatement NEWLINE { $$=[$1].filter(s => s !== null); }
| namespaceBodyStatement NEWLINE namespaceBodyStatements { var filtered = [$1].filter(s => s !== null); $3.unshift(...filtered); $$=$3; }
;
namespaceBodyStatement
: classStatement { $$=$1; }
| clickStatement { $$=null; /* clickStatements don't return class names, but are processed for side effects */ }
;
classStatements
: classStatement {$$=[$1]}
| classStatement NEWLINE {$$=[$1]}

View File

@@ -452,6 +452,7 @@ classDiagram
It is possible to bind a click event to a node. The click can lead to either a javascript callback or to a link which will be opened in a new browser tab. **Note**: This functionality is disabled when using `securityLevel='strict'` and enabled when using `securityLevel='loose'`.
You would define these actions on a separate line after all classes have been declared.
If you have classes defined within a namespace, you can also add interaction definitions within the namespace definition, after the class(es) is defined
```
action className "reference" "tooltip"