1104-Add support to designate a method as abstract

Added logic to allow rendering of a method name with italics or underline based on modifier at beginning of name to set css style
This commit is contained in:
Justin Greywolf
2019-12-09 17:41:26 -08:00
parent cf5d7478fc
commit 6fdf30357c
4 changed files with 86 additions and 12 deletions

View File

@@ -163,4 +163,28 @@ describe('Class diagram', () => {
); );
cy.get('svg'); cy.get('svg');
}); });
it('5: should render a simple class diagram with abstract method', () => {
imgSnapshotTest(
`
classDiagram
Class01 <|-- AveryLongClass : Cool
Class01 : |someMethod()
`,
{}
);
cy.get('svg');
});
it('6: should render a simple class diagram with static method', () => {
imgSnapshotTest(
`
classDiagram
Class01 <|-- AveryLongClass : Cool
Class01 : $someMethod()
`,
{}
);
cy.get('svg');
});
}); });

View File

@@ -105,17 +105,10 @@ Naming convention: a class name should be composed of alphanumeric (unicode allo
UML provides mechanisms to represent class members, such as attributes and methods, and additional information about them. UML provides mechanisms to represent class members, such as attributes and methods, and additional information about them.
#### Visibility Mermaid distinguishes between attributes and functions/methods based on if the **parenthesis** `()` are present or not. The ones with `()` are treated as functions/methods, and others as attributes.
To specify the visibility of a class member (i.e. any attribute or method), these notations may be placed before the member's name, but is it optional:
- `+` Public
- `-` Private
- `#` Protected
- `~` Package
Mermaid distinguishes between attributes and functions/methods based on if the **parenthesis** `()` are present or not. The one with `()` are treated as functions/methods, and others as attributes. There are two ways to define the members of a class, and regardless of whichever syntax is used to define the members, the output will still be same. The two different ways are :
There are two ways to define the members of a class, and regardless of the whichever syntax is used to define the members, the output will still be same. The two different ways are :
- Associate a member of a class using **:** (colon) followed by member name, useful to define one member at a time. For example: - Associate a member of a class using **:** (colon) followed by member name, useful to define one member at a time. For example:
``` ```
@@ -125,7 +118,7 @@ There are two ways to define the members of a class, and regardless of the which
BankAccount : +deposit(amount) BankAccount : +deposit(amount)
BankAccount : +withdrawl(amount) BankAccount : +withdrawl(amount)
``` ```
```mermaid ``` mermaid
classDiagram classDiagram
class BankAccount class BankAccount
BankAccount : +String owner BankAccount : +String owner
@@ -150,7 +143,22 @@ class BankAccount{
+BigDecimal balance +BigDecimal balance
+deposit(amount) +deposit(amount)
+withdrawl(amount) +withdrawl(amount)
}``` }
```
#### Visibility
To specify the visibility of a class member (i.e. any attribute or method), these notations may be placed before the member's name, but it is optional:
- `+` Public
- `-` Private
- `#` Protected
- `~` Package
>_note_ you can also add additional _classifers_ to a method definition using the following notations (similar to visibliity above):
> - `|` Abstract e.g.: `|someAbstractMethod()`
> - `$` Static e.g.: `$someStaticMethod()`
## Defining Relationship ## Defining Relationship
A relationship is a general term covering the specific types of logical connections found on class and object diagrams. A relationship is a general term covering the specific types of logical connections found on class and object diagrams.

View File

@@ -400,5 +400,27 @@ describe('class diagram, ', function () {
expect(testClass.methods[0]).toBe('test()'); expect(testClass.methods[0]).toBe('test()');
expect(testClass.methods[1]).toBe('foo()'); expect(testClass.methods[1]).toBe('foo()');
}); });
it('should handle abstract methods', function () {
const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : |someMethod()';
parser.parse(str);
const testClass = parser.yy.getClass('Class1');
expect(testClass.annotations.length).toBe(0);
expect(testClass.members.length).toBe(0);
expect(testClass.methods.length).toBe(1);
expect(testClass.methods[0]).toBe('|someMethod()');
});
it('should handle static methods', function () {
const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : $someMethod()';
parser.parse(str);
const testClass = parser.yy.getClass('Class1');
expect(testClass.annotations.length).toBe(0);
expect(testClass.members.length).toBe(0);
expect(testClass.methods.length).toBe(1);
expect(testClass.methods[0]).toBe('$someMethod()');
});
}); });
}); });

View File

@@ -281,10 +281,30 @@ const drawClass = function(elem, classDef) {
logger.info('Rendering class ' + classDef); logger.info('Rendering class ' + classDef);
const addTspan = function(textEl, txt, isFirst) { const addTspan = function(textEl, txt, isFirst) {
let displayText = txt;
let cssStyle = '';
let classifier = txt.substring(0 , 1);
switch (classifier) {
case '|':
cssStyle = 'font-style:italic;';
displayText = txt.substring(1);
break;
case '$':
cssStyle = 'text-decoration:underline;';
displayText = txt.substring(1);
break;
}
const tSpan = textEl const tSpan = textEl
.append('tspan') .append('tspan')
.attr('x', conf.padding) .attr('x', conf.padding)
.text(txt); .text(displayText);
if (cssStyle !== '') {
tSpan.attr('style', cssStyle);
}
if (!isFirst) { if (!isFirst) {
tSpan.attr('dy', conf.textHeight); tSpan.attr('dy', conf.textHeight);
} }