mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-05 00:26:40 +02:00
Create new type for member handling
This commit is contained in:
@@ -37,7 +37,10 @@
|
||||
"docsy",
|
||||
"doku",
|
||||
"dompurify",
|
||||
"dont",
|
||||
"doublecircle",
|
||||
"edgechromium",
|
||||
"elems",
|
||||
"elkjs",
|
||||
"faber",
|
||||
"flatmap",
|
||||
|
@@ -386,30 +386,6 @@ describe('Class diagram V2', () => {
|
||||
{ logLevel: 1, flowchart: { htmlLabels: false } }
|
||||
);
|
||||
});
|
||||
|
||||
it('18: should handle the direction statement with LR', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
classDiagram
|
||||
direction LR
|
||||
class Student {
|
||||
-idCard : IdCard
|
||||
}
|
||||
class IdCard{
|
||||
-id : int
|
||||
-name : string
|
||||
}
|
||||
class Bike{
|
||||
-id : int
|
||||
-name : string
|
||||
}
|
||||
Student "1" --o "1" IdCard : carries
|
||||
Student "1" --o "1" Bike : rides
|
||||
|
||||
`,
|
||||
{ logLevel: 1, flowchart: { htmlLabels: false } }
|
||||
);
|
||||
});
|
||||
it('17a: should handle the direction statement with BT', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
@@ -457,7 +433,31 @@ describe('Class diagram V2', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('18: should render a simple class diagram with notes', () => {
|
||||
it('18a: should handle the direction statement with LR', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
classDiagram
|
||||
direction LR
|
||||
class Student {
|
||||
-idCard : IdCard
|
||||
}
|
||||
class IdCard{
|
||||
-id : int
|
||||
-name : string
|
||||
}
|
||||
class Bike{
|
||||
-id : int
|
||||
-name : string
|
||||
}
|
||||
Student "1" --o "1" IdCard : carries
|
||||
Student "1" --o "1" Bike : rides
|
||||
|
||||
`,
|
||||
{ logLevel: 1, flowchart: { htmlLabels: false } }
|
||||
);
|
||||
});
|
||||
|
||||
it('18b: should render a simple class diagram with notes', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
classDiagram-v2
|
||||
@@ -562,4 +562,13 @@ class C13["With Città foreign language"]
|
||||
`
|
||||
);
|
||||
});
|
||||
it('should render a simple class diagram with no members', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
classDiagram-v2
|
||||
class Class10
|
||||
`,
|
||||
{ logLevel: 1, flowchart: { htmlLabels: false } }
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import { parser } from './parser/classDiagram.jison';
|
||||
import classDb from './classDb.js';
|
||||
import classParser from './classParser.js';
|
||||
|
||||
describe('class diagram, ', function () {
|
||||
describe('when parsing data from a classDiagram it', function () {
|
||||
beforeEach(function () {
|
||||
parser.yy = classDb;
|
||||
parser.yy = classParser;
|
||||
parser.yy.clear();
|
||||
});
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { DiagramDefinition } from '../../diagram-api/types.js';
|
||||
// @ts-ignore: TODO Fix ts errors
|
||||
import parser from './parser/classDiagram.jison';
|
||||
import db from './classDb.js';
|
||||
import db from './classParser.js';
|
||||
import styles from './styles.js';
|
||||
import renderer from './classRenderer-v2.js';
|
||||
|
||||
|
@@ -1,14 +1,14 @@
|
||||
// @ts-expect-error Jison doesn't export types
|
||||
import { parser } from './parser/classDiagram.jison';
|
||||
import classDb from './classDb.js';
|
||||
import classParser from './classParser.js';
|
||||
import { vi, describe, it, expect } from 'vitest';
|
||||
const spyOn = vi.spyOn;
|
||||
|
||||
describe('given a basic class diagram, ', function () {
|
||||
describe('when parsing class definition', function () {
|
||||
beforeEach(function () {
|
||||
classDb.clear();
|
||||
parser.yy = classDb;
|
||||
classParser.clear();
|
||||
parser.yy = classParser;
|
||||
});
|
||||
it('should handle accTitle and accDescr', function () {
|
||||
const str = `classDiagram
|
||||
@@ -54,7 +54,7 @@ describe('given a basic class diagram, ', function () {
|
||||
const str = 'classDiagram\n' + 'class Ca-r';
|
||||
|
||||
parser.parse(str);
|
||||
const actual = classDb.getClass('Ca-r');
|
||||
const actual = classParser.getClass('Ca-r');
|
||||
expect(actual.label).toBe('Ca-r');
|
||||
});
|
||||
|
||||
@@ -102,7 +102,7 @@ describe('given a basic class diagram, ', function () {
|
||||
|
||||
parser.parse(str);
|
||||
|
||||
const c1 = classDb.getClass('C1');
|
||||
const c1 = classParser.getClass('C1');
|
||||
expect(c1.label).toBe('Class 1 with text label');
|
||||
});
|
||||
|
||||
@@ -114,9 +114,9 @@ describe('given a basic class diagram, ', function () {
|
||||
|
||||
parser.parse(str);
|
||||
|
||||
const c1 = classDb.getClass('C1');
|
||||
const c1 = classParser.getClass('C1');
|
||||
expect(c1.label).toBe('Class 1 with text label');
|
||||
const c2 = classDb.getClass('C2');
|
||||
const c2 = classParser.getClass('C2');
|
||||
expect(c2.label).toBe('Class 2 with chars @?');
|
||||
});
|
||||
|
||||
@@ -124,7 +124,7 @@ describe('given a basic class diagram, ', function () {
|
||||
const str = 'classDiagram\n' + 'class C1["Class 1 with text label"]\n' + 'C1: member1';
|
||||
|
||||
parser.parse(str);
|
||||
const c1 = classDb.getClass('C1');
|
||||
const c1 = classParser.getClass('C1');
|
||||
expect(c1.label).toBe('Class 1 with text label');
|
||||
expect(c1.members.length).toBe(1);
|
||||
expect(c1.members[0]).toBe('member1');
|
||||
@@ -139,7 +139,7 @@ describe('given a basic class diagram, ', function () {
|
||||
|
||||
parser.parse(str);
|
||||
|
||||
const c1 = classDb.getClass('C1');
|
||||
const c1 = classParser.getClass('C1');
|
||||
expect(c1.label).toBe('Class 1 with text label');
|
||||
expect(c1.members.length).toBe(1);
|
||||
expect(c1.members[0]).toBe('int member1');
|
||||
@@ -152,7 +152,7 @@ describe('given a basic class diagram, ', function () {
|
||||
|
||||
parser.parse(str);
|
||||
|
||||
const c1 = classDb.getClass('C1');
|
||||
const c1 = classParser.getClass('C1');
|
||||
expect(c1.label).toBe('Class 1 with text label');
|
||||
expect(c1.cssClasses[0]).toBe('styleClass');
|
||||
});
|
||||
@@ -166,7 +166,7 @@ describe('given a basic class diagram, ', function () {
|
||||
|
||||
parser.parse(str);
|
||||
|
||||
const c1 = classDb.getClass('C1');
|
||||
const c1 = classParser.getClass('C1');
|
||||
expect(c1.label).toBe('Class 1 with text label');
|
||||
expect(c1.members[0]).toBe('int member1');
|
||||
expect(c1.cssClasses[0]).toBe('styleClass');
|
||||
@@ -182,11 +182,11 @@ describe('given a basic class diagram, ', function () {
|
||||
|
||||
parser.parse(str);
|
||||
|
||||
const c1 = classDb.getClass('C1');
|
||||
const c1 = classParser.getClass('C1');
|
||||
expect(c1.label).toBe('Class 1 with text label');
|
||||
expect(c1.cssClasses[0]).toBe('styleClass');
|
||||
|
||||
const c2 = classDb.getClass('C2');
|
||||
const c2 = classParser.getClass('C2');
|
||||
expect(c2.label).toBe('Long long long long long long long long long long label');
|
||||
expect(c2.cssClasses[0]).toBe('styleClass');
|
||||
});
|
||||
@@ -199,11 +199,11 @@ describe('given a basic class diagram, ', function () {
|
||||
|
||||
parser.parse(str);
|
||||
|
||||
const c1 = classDb.getClass('C1');
|
||||
const c1 = classParser.getClass('C1');
|
||||
expect(c1.label).toBe('Class 1 with text label');
|
||||
expect(c1.cssClasses[0]).toBe('styleClass1');
|
||||
|
||||
const c2 = classDb.getClass('C2');
|
||||
const c2 = classParser.getClass('C2');
|
||||
expect(c2.label).toBe('Class 2 !@#$%^&*() label');
|
||||
expect(c2.cssClasses[0]).toBe('styleClass2');
|
||||
});
|
||||
@@ -214,13 +214,13 @@ class C1["Class with text label"]
|
||||
class C2["Class with text label"]
|
||||
class C3["Class with text label"]`);
|
||||
|
||||
const c1 = classDb.getClass('C1');
|
||||
const c1 = classParser.getClass('C1');
|
||||
expect(c1.label).toBe('Class with text label');
|
||||
|
||||
const c2 = classDb.getClass('C2');
|
||||
const c2 = classParser.getClass('C2');
|
||||
expect(c2.label).toBe('Class with text label');
|
||||
|
||||
const c3 = classDb.getClass('C3');
|
||||
const c3 = classParser.getClass('C3');
|
||||
expect(c3.label).toBe('Class with text label');
|
||||
});
|
||||
|
||||
@@ -240,19 +240,19 @@ class C11["With ' single quote"]
|
||||
class C12["With ~!@#$%^&*()_+=-/?"]
|
||||
class C13["With Città foreign language"]
|
||||
`);
|
||||
expect(classDb.getClass('C1').label).toBe('OneWord');
|
||||
expect(classDb.getClass('C2').label).toBe('With, Comma');
|
||||
expect(classDb.getClass('C3').label).toBe('With (Brackets)');
|
||||
expect(classDb.getClass('C4').label).toBe('With [Brackets]');
|
||||
expect(classDb.getClass('C5').label).toBe('With {Brackets}');
|
||||
expect(classDb.getClass('C6').label).toBe(' ');
|
||||
expect(classDb.getClass('C7').label).toBe('With 1 number');
|
||||
expect(classDb.getClass('C8').label).toBe('With . period...');
|
||||
expect(classDb.getClass('C9').label).toBe('With - dash');
|
||||
expect(classDb.getClass('C10').label).toBe('With _ underscore');
|
||||
expect(classDb.getClass('C11').label).toBe("With ' single quote");
|
||||
expect(classDb.getClass('C12').label).toBe('With ~!@#$%^&*()_+=-/?');
|
||||
expect(classDb.getClass('C13').label).toBe('With Città foreign language');
|
||||
expect(classParser.getClass('C1').label).toBe('OneWord');
|
||||
expect(classParser.getClass('C2').label).toBe('With, Comma');
|
||||
expect(classParser.getClass('C3').label).toBe('With (Brackets)');
|
||||
expect(classParser.getClass('C4').label).toBe('With [Brackets]');
|
||||
expect(classParser.getClass('C5').label).toBe('With {Brackets}');
|
||||
expect(classParser.getClass('C6').label).toBe(' ');
|
||||
expect(classParser.getClass('C7').label).toBe('With 1 number');
|
||||
expect(classParser.getClass('C8').label).toBe('With . period...');
|
||||
expect(classParser.getClass('C9').label).toBe('With - dash');
|
||||
expect(classParser.getClass('C10').label).toBe('With _ underscore');
|
||||
expect(classParser.getClass('C11').label).toBe("With ' single quote");
|
||||
expect(classParser.getClass('C12').label).toBe('With ~!@#$%^&*()_+=-/?');
|
||||
expect(classParser.getClass('C13').label).toBe('With Città foreign language');
|
||||
});
|
||||
|
||||
it('should handle "note for"', function () {
|
||||
@@ -268,8 +268,8 @@ class C13["With Città foreign language"]
|
||||
|
||||
describe('when parsing class defined in brackets', function () {
|
||||
beforeEach(function () {
|
||||
classDb.clear();
|
||||
parser.yy = classDb;
|
||||
classParser.clear();
|
||||
parser.yy = classParser;
|
||||
});
|
||||
|
||||
it('should handle member definitions', function () {
|
||||
@@ -334,7 +334,7 @@ class C13["With Città foreign language"]
|
||||
const str = 'classDiagram\n' + 'class C1["Class 1 with text label"] {\n' + '+member1\n' + '}';
|
||||
|
||||
parser.parse(str);
|
||||
const c1 = classDb.getClass('C1');
|
||||
const c1 = classParser.getClass('C1');
|
||||
expect(c1.label).toBe('Class 1 with text label');
|
||||
expect(c1.members.length).toBe(1);
|
||||
expect(c1.members[0]).toBe('+member1');
|
||||
@@ -349,7 +349,7 @@ class C13["With Città foreign language"]
|
||||
'}';
|
||||
|
||||
parser.parse(str);
|
||||
const c1 = classDb.getClass('C1');
|
||||
const c1 = classParser.getClass('C1');
|
||||
expect(c1.label).toBe('Class 1 with text label');
|
||||
expect(c1.members.length).toBe(1);
|
||||
expect(c1.members[0]).toBe('+member1');
|
||||
@@ -360,8 +360,8 @@ class C13["With Città foreign language"]
|
||||
|
||||
describe('when parsing comments', function () {
|
||||
beforeEach(function () {
|
||||
classDb.clear();
|
||||
parser.yy = classDb;
|
||||
classParser.clear();
|
||||
parser.yy = classParser;
|
||||
});
|
||||
|
||||
it('should handle comments at the start', function () {
|
||||
@@ -450,16 +450,16 @@ foo()
|
||||
|
||||
describe('when parsing click statements', function () {
|
||||
beforeEach(function () {
|
||||
classDb.clear();
|
||||
parser.yy = classDb;
|
||||
classParser.clear();
|
||||
parser.yy = classParser;
|
||||
});
|
||||
it('should handle href link', function () {
|
||||
spyOn(classDb, 'setLink');
|
||||
spyOn(classParser, 'setLink');
|
||||
const str = 'classDiagram\n' + 'class Class1 \n' + 'click Class1 href "google.com" ';
|
||||
|
||||
parser.parse(str);
|
||||
|
||||
expect(classDb.setLink).toHaveBeenCalledWith('Class1', 'google.com');
|
||||
expect(classParser.setLink).toHaveBeenCalledWith('Class1', 'google.com');
|
||||
|
||||
const actual = parser.yy.getClass('Class1');
|
||||
expect(actual.link).toBe('google.com');
|
||||
@@ -467,14 +467,14 @@ foo()
|
||||
});
|
||||
|
||||
it('should handle href link with tooltip', function () {
|
||||
spyOn(classDb, 'setLink');
|
||||
spyOn(classDb, 'setTooltip');
|
||||
spyOn(classParser, 'setLink');
|
||||
spyOn(classParser, 'setTooltip');
|
||||
const str =
|
||||
'classDiagram\n' + 'class Class1 \n' + 'click Class1 href "google.com" "A Tooltip" ';
|
||||
|
||||
parser.parse(str);
|
||||
|
||||
expect(classDb.setLink).toHaveBeenCalledWith('Class1', 'google.com');
|
||||
expect(classParser.setLink).toHaveBeenCalledWith('Class1', 'google.com');
|
||||
|
||||
const actual = parser.yy.getClass('Class1');
|
||||
expect(actual.link).toBe('google.com');
|
||||
@@ -483,8 +483,8 @@ foo()
|
||||
});
|
||||
|
||||
it('should handle href link with tooltip and target', function () {
|
||||
spyOn(classDb, 'setLink');
|
||||
spyOn(classDb, 'setTooltip');
|
||||
spyOn(classParser, 'setLink');
|
||||
spyOn(classParser, 'setTooltip');
|
||||
const str =
|
||||
'classDiagram\n' +
|
||||
'class Class1\n' +
|
||||
@@ -492,8 +492,8 @@ foo()
|
||||
'click Class1 href "google.com" "A tooltip" _self';
|
||||
parser.parse(str);
|
||||
|
||||
expect(classDb.setLink).toHaveBeenCalledWith('Class1', 'google.com', '_self');
|
||||
expect(classDb.setTooltip).toHaveBeenCalledWith('Class1', 'A tooltip');
|
||||
expect(classParser.setLink).toHaveBeenCalledWith('Class1', 'google.com', '_self');
|
||||
expect(classParser.setTooltip).toHaveBeenCalledWith('Class1', 'A tooltip');
|
||||
|
||||
const actual = parser.yy.getClass('Class1');
|
||||
expect(actual.link).toBe('google.com');
|
||||
@@ -502,30 +502,30 @@ foo()
|
||||
});
|
||||
|
||||
it('should handle function call', function () {
|
||||
spyOn(classDb, 'setClickEvent');
|
||||
spyOn(classParser, 'setClickEvent');
|
||||
|
||||
const str = 'classDiagram\n' + 'class Class1 \n' + 'click Class1 call functionCall() ';
|
||||
|
||||
parser.parse(str);
|
||||
|
||||
expect(classDb.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall');
|
||||
expect(classParser.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall');
|
||||
});
|
||||
|
||||
it('should handle function call with tooltip', function () {
|
||||
spyOn(classDb, 'setClickEvent');
|
||||
spyOn(classDb, 'setTooltip');
|
||||
spyOn(classParser, 'setClickEvent');
|
||||
spyOn(classParser, 'setTooltip');
|
||||
|
||||
const str =
|
||||
'classDiagram\n' + 'class Class1 \n' + 'click Class1 call functionCall() "A Tooltip" ';
|
||||
|
||||
parser.parse(str);
|
||||
|
||||
expect(classDb.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall');
|
||||
expect(classDb.setTooltip).toHaveBeenCalledWith('Class1', 'A Tooltip');
|
||||
expect(classParser.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall');
|
||||
expect(classParser.setTooltip).toHaveBeenCalledWith('Class1', 'A Tooltip');
|
||||
});
|
||||
|
||||
it('should handle function call with an arbitrary number of args', function () {
|
||||
spyOn(classDb, 'setClickEvent');
|
||||
spyOn(classParser, 'setClickEvent');
|
||||
const str =
|
||||
'classDiagram\n' +
|
||||
'class Class1\n' +
|
||||
@@ -533,7 +533,7 @@ foo()
|
||||
'click Class1 call functionCall(test, test1, test2)';
|
||||
parser.parse(str);
|
||||
|
||||
expect(classDb.setClickEvent).toHaveBeenCalledWith(
|
||||
expect(classParser.setClickEvent).toHaveBeenCalledWith(
|
||||
'Class1',
|
||||
'functionCall',
|
||||
'test, test1, test2'
|
||||
@@ -541,8 +541,8 @@ foo()
|
||||
});
|
||||
|
||||
it('should handle function call with an arbitrary number of args and tooltip', function () {
|
||||
spyOn(classDb, 'setClickEvent');
|
||||
spyOn(classDb, 'setTooltip');
|
||||
spyOn(classParser, 'setClickEvent');
|
||||
spyOn(classParser, 'setTooltip');
|
||||
const str =
|
||||
'classDiagram\n' +
|
||||
'class Class1\n' +
|
||||
@@ -550,19 +550,19 @@ foo()
|
||||
'click Class1 call functionCall("test0", test1, test2) "A Tooltip"';
|
||||
parser.parse(str);
|
||||
|
||||
expect(classDb.setClickEvent).toHaveBeenCalledWith(
|
||||
expect(classParser.setClickEvent).toHaveBeenCalledWith(
|
||||
'Class1',
|
||||
'functionCall',
|
||||
'"test0", test1, test2'
|
||||
);
|
||||
expect(classDb.setTooltip).toHaveBeenCalledWith('Class1', 'A Tooltip');
|
||||
expect(classParser.setTooltip).toHaveBeenCalledWith('Class1', 'A Tooltip');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when parsing annotations', function () {
|
||||
beforeEach(function () {
|
||||
classDb.clear();
|
||||
parser.yy = classDb;
|
||||
classParser.clear();
|
||||
parser.yy = classParser;
|
||||
});
|
||||
|
||||
it('should handle class annotations', function () {
|
||||
@@ -625,8 +625,8 @@ foo()
|
||||
describe('given a class diagram with members and methods ', function () {
|
||||
describe('when parsing members', function () {
|
||||
beforeEach(function () {
|
||||
classDb.clear();
|
||||
parser.yy = classDb;
|
||||
classParser.clear();
|
||||
parser.yy = classParser;
|
||||
});
|
||||
|
||||
it('should handle simple member declaration', function () {
|
||||
@@ -670,8 +670,8 @@ describe('given a class diagram with members and methods ', function () {
|
||||
|
||||
describe('when parsing method definition', function () {
|
||||
beforeEach(function () {
|
||||
classDb.clear();
|
||||
parser.yy = classDb;
|
||||
classParser.clear();
|
||||
parser.yy = classParser;
|
||||
});
|
||||
|
||||
it('should handle method definition', function () {
|
||||
@@ -753,8 +753,8 @@ describe('given a class diagram with members and methods ', function () {
|
||||
describe('given a class diagram with generics, ', function () {
|
||||
describe('when parsing valid generic classes', function () {
|
||||
beforeEach(function () {
|
||||
classDb.clear();
|
||||
parser.yy = classDb;
|
||||
classParser.clear();
|
||||
parser.yy = classParser;
|
||||
});
|
||||
|
||||
it('should handle generic class', function () {
|
||||
@@ -851,8 +851,8 @@ foo()
|
||||
|
||||
describe('when parsing invalid generic classes', function () {
|
||||
beforeEach(function () {
|
||||
classDb.clear();
|
||||
parser.yy = classDb;
|
||||
classParser.clear();
|
||||
parser.yy = classParser;
|
||||
});
|
||||
|
||||
it('should break when another `{`is encountered before closing the first one while defining generic class with brackets', function () {
|
||||
@@ -900,8 +900,8 @@ foo()
|
||||
describe('given a class diagram with relationships, ', function () {
|
||||
describe('when parsing basic relationships', function () {
|
||||
beforeEach(function () {
|
||||
classDb.clear();
|
||||
parser.yy = classDb;
|
||||
classParser.clear();
|
||||
parser.yy = classParser;
|
||||
});
|
||||
|
||||
it('should handle all basic relationships', function () {
|
||||
@@ -938,9 +938,9 @@ describe('given a class diagram with relationships, ', function () {
|
||||
expect(parser.yy.getClass('Class1').id).toBe('Class1');
|
||||
expect(parser.yy.getClass('Class1').type).toBe('T');
|
||||
expect(parser.yy.getClass('Class02').id).toBe('Class02');
|
||||
expect(relations[0].relation.type1).toBe(classDb.relationType.EXTENSION);
|
||||
expect(relations[0].relation.type1).toBe(classParser.relationType.EXTENSION);
|
||||
expect(relations[0].relation.type2).toBe('none');
|
||||
expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE);
|
||||
expect(relations[0].relation.lineType).toBe(classParser.lineType.LINE);
|
||||
});
|
||||
|
||||
it('should handle relationships with labels', function () {
|
||||
@@ -963,9 +963,9 @@ describe('given a class diagram with relationships, ', function () {
|
||||
|
||||
expect(parser.yy.getClass('Class1').id).toBe('Class1');
|
||||
expect(parser.yy.getClass('Class02').id).toBe('Class02');
|
||||
expect(relations[0].relation.type1).toBe(classDb.relationType.EXTENSION);
|
||||
expect(relations[0].relation.type1).toBe(classParser.relationType.EXTENSION);
|
||||
expect(relations[0].relation.type2).toBe('none');
|
||||
expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE);
|
||||
expect(relations[0].relation.lineType).toBe(classParser.lineType.LINE);
|
||||
});
|
||||
|
||||
it('should handle relation definition of different types and directions', function () {
|
||||
@@ -1010,9 +1010,9 @@ describe('given a class diagram with relationships, ', function () {
|
||||
|
||||
expect(parser.yy.getClass('Class1').id).toBe('Class1');
|
||||
expect(parser.yy.getClass('Class02').id).toBe('Class02');
|
||||
expect(relations[0].relation.type1).toBe(classDb.relationType.AGGREGATION);
|
||||
expect(relations[0].relation.type1).toBe(classParser.relationType.AGGREGATION);
|
||||
expect(relations[0].relation.type2).toBe('none');
|
||||
expect(relations[0].relation.lineType).toBe(classDb.lineType.DOTTED_LINE);
|
||||
expect(relations[0].relation.lineType).toBe(classParser.lineType.DOTTED_LINE);
|
||||
});
|
||||
|
||||
it('should handle relation definitions COMPOSITION on both sides', function () {
|
||||
@@ -1024,9 +1024,9 @@ describe('given a class diagram with relationships, ', function () {
|
||||
|
||||
expect(parser.yy.getClass('Class1').id).toBe('Class1');
|
||||
expect(parser.yy.getClass('Class02').id).toBe('Class02');
|
||||
expect(relations[0].relation.type1).toBe(classDb.relationType.COMPOSITION);
|
||||
expect(relations[0].relation.type2).toBe(classDb.relationType.COMPOSITION);
|
||||
expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE);
|
||||
expect(relations[0].relation.type1).toBe(classParser.relationType.COMPOSITION);
|
||||
expect(relations[0].relation.type2).toBe(classParser.relationType.COMPOSITION);
|
||||
expect(relations[0].relation.lineType).toBe(classParser.lineType.LINE);
|
||||
});
|
||||
|
||||
it('should handle relation definitions with no types', function () {
|
||||
@@ -1040,7 +1040,7 @@ describe('given a class diagram with relationships, ', function () {
|
||||
expect(parser.yy.getClass('Class02').id).toBe('Class02');
|
||||
expect(relations[0].relation.type1).toBe('none');
|
||||
expect(relations[0].relation.type2).toBe('none');
|
||||
expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE);
|
||||
expect(relations[0].relation.lineType).toBe(classParser.lineType.LINE);
|
||||
});
|
||||
|
||||
it('should handle relation definitions with type only on right side', function () {
|
||||
@@ -1053,8 +1053,8 @@ describe('given a class diagram with relationships, ', function () {
|
||||
expect(parser.yy.getClass('Class1').id).toBe('Class1');
|
||||
expect(parser.yy.getClass('Class02').id).toBe('Class02');
|
||||
expect(relations[0].relation.type1).toBe('none');
|
||||
expect(relations[0].relation.type2).toBe(classDb.relationType.EXTENSION);
|
||||
expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE);
|
||||
expect(relations[0].relation.type2).toBe(classParser.relationType.EXTENSION);
|
||||
expect(relations[0].relation.lineType).toBe(classParser.lineType.LINE);
|
||||
});
|
||||
|
||||
it('should handle multiple classes and relation definitions', function () {
|
||||
@@ -1075,12 +1075,12 @@ describe('given a class diagram with relationships, ', function () {
|
||||
|
||||
expect(relations.length).toBe(5);
|
||||
|
||||
expect(relations[0].relation.type1).toBe(classDb.relationType.EXTENSION);
|
||||
expect(relations[0].relation.type1).toBe(classParser.relationType.EXTENSION);
|
||||
expect(relations[0].relation.type2).toBe('none');
|
||||
expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE);
|
||||
expect(relations[0].relation.lineType).toBe(classParser.lineType.LINE);
|
||||
expect(relations[3].relation.type1).toBe('none');
|
||||
expect(relations[3].relation.type2).toBe('none');
|
||||
expect(relations[3].relation.lineType).toBe(classDb.lineType.DOTTED_LINE);
|
||||
expect(relations[3].relation.lineType).toBe(classParser.lineType.DOTTED_LINE);
|
||||
});
|
||||
|
||||
it('should handle generic class with relation definitions', function () {
|
||||
@@ -1093,9 +1093,9 @@ describe('given a class diagram with relationships, ', function () {
|
||||
expect(parser.yy.getClass('Class01').id).toBe('Class01');
|
||||
expect(parser.yy.getClass('Class01').type).toBe('T');
|
||||
expect(parser.yy.getClass('Class02').id).toBe('Class02');
|
||||
expect(relations[0].relation.type1).toBe(classDb.relationType.EXTENSION);
|
||||
expect(relations[0].relation.type1).toBe(classParser.relationType.EXTENSION);
|
||||
expect(relations[0].relation.type2).toBe('none');
|
||||
expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE);
|
||||
expect(relations[0].relation.lineType).toBe(classParser.lineType.LINE);
|
||||
});
|
||||
|
||||
it('should handle class annotations', function () {
|
||||
@@ -1254,8 +1254,8 @@ describe('given a class diagram with relationships, ', function () {
|
||||
});
|
||||
|
||||
it('should associate click and href link with tooltip and target appropriately', function () {
|
||||
spyOn(classDb, 'setLink');
|
||||
spyOn(classDb, 'setTooltip');
|
||||
spyOn(classParser, 'setLink');
|
||||
spyOn(classParser, 'setTooltip');
|
||||
const str =
|
||||
'classDiagram\n' +
|
||||
'class Class1\n' +
|
||||
@@ -1263,12 +1263,12 @@ describe('given a class diagram with relationships, ', function () {
|
||||
'click Class1 href "google.com" "A tooltip" _self';
|
||||
parser.parse(str);
|
||||
|
||||
expect(classDb.setLink).toHaveBeenCalledWith('Class1', 'google.com', '_self');
|
||||
expect(classDb.setTooltip).toHaveBeenCalledWith('Class1', 'A tooltip');
|
||||
expect(classParser.setLink).toHaveBeenCalledWith('Class1', 'google.com', '_self');
|
||||
expect(classParser.setTooltip).toHaveBeenCalledWith('Class1', 'A tooltip');
|
||||
});
|
||||
|
||||
it('should associate click and href link appropriately', function () {
|
||||
spyOn(classDb, 'setLink');
|
||||
spyOn(classParser, 'setLink');
|
||||
const str =
|
||||
'classDiagram\n' +
|
||||
'class Class1\n' +
|
||||
@@ -1276,11 +1276,11 @@ describe('given a class diagram with relationships, ', function () {
|
||||
'click Class1 href "google.com"';
|
||||
parser.parse(str);
|
||||
|
||||
expect(classDb.setLink).toHaveBeenCalledWith('Class1', 'google.com');
|
||||
expect(classParser.setLink).toHaveBeenCalledWith('Class1', 'google.com');
|
||||
});
|
||||
|
||||
it('should associate click and href link with target appropriately', function () {
|
||||
spyOn(classDb, 'setLink');
|
||||
spyOn(classParser, 'setLink');
|
||||
const str =
|
||||
'classDiagram\n' +
|
||||
'class Class1\n' +
|
||||
@@ -1288,12 +1288,12 @@ describe('given a class diagram with relationships, ', function () {
|
||||
'click Class1 href "google.com" _self';
|
||||
parser.parse(str);
|
||||
|
||||
expect(classDb.setLink).toHaveBeenCalledWith('Class1', 'google.com', '_self');
|
||||
expect(classParser.setLink).toHaveBeenCalledWith('Class1', 'google.com', '_self');
|
||||
});
|
||||
|
||||
it('should associate link appropriately', function () {
|
||||
spyOn(classDb, 'setLink');
|
||||
spyOn(classDb, 'setTooltip');
|
||||
spyOn(classParser, 'setLink');
|
||||
spyOn(classParser, 'setTooltip');
|
||||
const str =
|
||||
'classDiagram\n' +
|
||||
'class Class1\n' +
|
||||
@@ -1301,12 +1301,12 @@ describe('given a class diagram with relationships, ', function () {
|
||||
'link Class1 "google.com" "A tooltip" _self';
|
||||
parser.parse(str);
|
||||
|
||||
expect(classDb.setLink).toHaveBeenCalledWith('Class1', 'google.com', '_self');
|
||||
expect(classDb.setTooltip).toHaveBeenCalledWith('Class1', 'A tooltip');
|
||||
expect(classParser.setLink).toHaveBeenCalledWith('Class1', 'google.com', '_self');
|
||||
expect(classParser.setTooltip).toHaveBeenCalledWith('Class1', 'A tooltip');
|
||||
});
|
||||
|
||||
it('should associate callback appropriately', function () {
|
||||
spyOn(classDb, 'setClickEvent');
|
||||
spyOn(classParser, 'setClickEvent');
|
||||
const str =
|
||||
'classDiagram\n' +
|
||||
'class Class1\n' +
|
||||
@@ -1314,11 +1314,11 @@ describe('given a class diagram with relationships, ', function () {
|
||||
'callback Class1 "functionCall"';
|
||||
parser.parse(str);
|
||||
|
||||
expect(classDb.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall');
|
||||
expect(classParser.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall');
|
||||
});
|
||||
|
||||
it('should associate click and call callback appropriately', function () {
|
||||
spyOn(classDb, 'setClickEvent');
|
||||
spyOn(classParser, 'setClickEvent');
|
||||
const str =
|
||||
'classDiagram\n' +
|
||||
'class Class1\n' +
|
||||
@@ -1326,11 +1326,11 @@ describe('given a class diagram with relationships, ', function () {
|
||||
'click Class1 call functionCall()';
|
||||
parser.parse(str);
|
||||
|
||||
expect(classDb.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall');
|
||||
expect(classParser.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall');
|
||||
});
|
||||
|
||||
it('should associate callback appropriately with an arbitrary number of args', function () {
|
||||
spyOn(classDb, 'setClickEvent');
|
||||
spyOn(classParser, 'setClickEvent');
|
||||
const str =
|
||||
'classDiagram\n' +
|
||||
'class Class1\n' +
|
||||
@@ -1338,7 +1338,7 @@ describe('given a class diagram with relationships, ', function () {
|
||||
'click Class1 call functionCall("test0", test1, test2)';
|
||||
parser.parse(str);
|
||||
|
||||
expect(classDb.setClickEvent).toHaveBeenCalledWith(
|
||||
expect(classParser.setClickEvent).toHaveBeenCalledWith(
|
||||
'Class1',
|
||||
'functionCall',
|
||||
'"test0", test1, test2'
|
||||
@@ -1346,8 +1346,8 @@ describe('given a class diagram with relationships, ', function () {
|
||||
});
|
||||
|
||||
it('should associate callback with tooltip', function () {
|
||||
spyOn(classDb, 'setClickEvent');
|
||||
spyOn(classDb, 'setTooltip');
|
||||
spyOn(classParser, 'setClickEvent');
|
||||
spyOn(classParser, 'setTooltip');
|
||||
const str =
|
||||
'classDiagram\n' +
|
||||
'class Class1\n' +
|
||||
@@ -1355,8 +1355,8 @@ describe('given a class diagram with relationships, ', function () {
|
||||
'click Class1 call functionCall() "A tooltip"';
|
||||
parser.parse(str);
|
||||
|
||||
expect(classDb.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall');
|
||||
expect(classDb.setTooltip).toHaveBeenCalledWith('Class1', 'A tooltip');
|
||||
expect(classParser.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall');
|
||||
expect(classParser.setTooltip).toHaveBeenCalledWith('Class1', 'A tooltip');
|
||||
});
|
||||
|
||||
it('should add classes namespaces', function () {
|
||||
@@ -1381,7 +1381,7 @@ class Class2
|
||||
|
||||
describe('when parsing classDiagram with text labels', () => {
|
||||
beforeEach(function () {
|
||||
parser.yy = classDb;
|
||||
parser.yy = classParser;
|
||||
parser.yy.clear();
|
||||
});
|
||||
|
||||
@@ -1390,9 +1390,9 @@ class Class2
|
||||
class C1["Class 1 with text label"]
|
||||
C1 --> C2
|
||||
`);
|
||||
const c1 = classDb.getClass('C1');
|
||||
const c1 = classParser.getClass('C1');
|
||||
expect(c1.label).toBe('Class 1 with text label');
|
||||
const c2 = classDb.getClass('C2');
|
||||
const c2 = classParser.getClass('C2');
|
||||
expect(c2.label).toBe('C2');
|
||||
});
|
||||
|
||||
@@ -1402,9 +1402,9 @@ class Class2
|
||||
class C2["Class 2 with chars @?"]
|
||||
C1 --> C2
|
||||
`);
|
||||
const c1 = classDb.getClass('C1');
|
||||
const c1 = classParser.getClass('C1');
|
||||
expect(c1.label).toBe('Class 1 with text label');
|
||||
const c2 = classDb.getClass('C2');
|
||||
const c2 = classParser.getClass('C2');
|
||||
expect(c2.label).toBe('Class 2 with chars @?');
|
||||
});
|
||||
|
||||
@@ -1415,12 +1415,12 @@ class Class2
|
||||
}
|
||||
C1 --> C2
|
||||
`);
|
||||
const c1 = classDb.getClass('C1');
|
||||
const c1 = classParser.getClass('C1');
|
||||
expect(c1.label).toBe('Class 1 with text label');
|
||||
expect(c1.members.length).toBe(1);
|
||||
expect(c1.members[0]).toBe('+member1');
|
||||
|
||||
const c2 = classDb.getClass('C2');
|
||||
const c2 = classParser.getClass('C2');
|
||||
expect(c2.label).toBe('C2');
|
||||
});
|
||||
|
||||
@@ -1432,14 +1432,14 @@ class Class2
|
||||
}
|
||||
C1 --> C2
|
||||
`);
|
||||
const c1 = classDb.getClass('C1');
|
||||
const c1 = classParser.getClass('C1');
|
||||
expect(c1.label).toBe('Class 1 with text label');
|
||||
expect(c1.members.length).toBe(1);
|
||||
expect(c1.members[0]).toBe('+member1');
|
||||
expect(c1.annotations.length).toBe(1);
|
||||
expect(c1.annotations[0]).toBe('interface');
|
||||
|
||||
const c2 = classDb.getClass('C2');
|
||||
const c2 = classParser.getClass('C2');
|
||||
expect(c2.label).toBe('C2');
|
||||
});
|
||||
|
||||
@@ -1451,7 +1451,7 @@ class C1["Class 1 with text label"]:::styleClass {
|
||||
C1 --> C2
|
||||
`);
|
||||
|
||||
const c1 = classDb.getClass('C1');
|
||||
const c1 = classParser.getClass('C1');
|
||||
expect(c1.label).toBe('Class 1 with text label');
|
||||
expect(c1.cssClasses.length).toBe(1);
|
||||
expect(c1.members[0]).toBe('+member1');
|
||||
@@ -1467,7 +1467,7 @@ C1 --> C2
|
||||
cssClass "C1" styleClass
|
||||
`);
|
||||
|
||||
const c1 = classDb.getClass('C1');
|
||||
const c1 = classParser.getClass('C1');
|
||||
expect(c1.label).toBe('Class 1 with text label');
|
||||
expect(c1.cssClasses.length).toBe(1);
|
||||
expect(c1.members[0]).toBe('+member1');
|
||||
@@ -1484,12 +1484,12 @@ C1 --> C2
|
||||
cssClass "C1,C2" styleClass
|
||||
`);
|
||||
|
||||
const c1 = classDb.getClass('C1');
|
||||
const c1 = classParser.getClass('C1');
|
||||
expect(c1.label).toBe('Class 1 with text label');
|
||||
expect(c1.cssClasses.length).toBe(1);
|
||||
expect(c1.cssClasses[0]).toBe('styleClass');
|
||||
|
||||
const c2 = classDb.getClass('C2');
|
||||
const c2 = classParser.getClass('C2');
|
||||
expect(c2.label).toBe('Long long long long long long long long long long label');
|
||||
expect(c2.cssClasses.length).toBe(1);
|
||||
expect(c2.cssClasses[0]).toBe('styleClass');
|
||||
@@ -1504,12 +1504,12 @@ class C2["Class 2 !@#$%^&*() label"]:::styleClass2
|
||||
C1 --> C2
|
||||
`);
|
||||
|
||||
const c1 = classDb.getClass('C1');
|
||||
const c1 = classParser.getClass('C1');
|
||||
expect(c1.label).toBe('Class 1 with text label');
|
||||
expect(c1.cssClasses.length).toBe(1);
|
||||
expect(c1.cssClasses[0]).toBe('styleClass1');
|
||||
|
||||
const c2 = classDb.getClass('C2');
|
||||
const c2 = classParser.getClass('C2');
|
||||
expect(c2.label).toBe('Class 2 !@#$%^&*() label');
|
||||
expect(c2.cssClasses.length).toBe(1);
|
||||
expect(c2.cssClasses[0]).toBe('styleClass2');
|
||||
@@ -1524,13 +1524,13 @@ C1 --> C2
|
||||
C3 ..> C2
|
||||
`);
|
||||
|
||||
const c1 = classDb.getClass('C1');
|
||||
const c1 = classParser.getClass('C1');
|
||||
expect(c1.label).toBe('Class with text label');
|
||||
|
||||
const c2 = classDb.getClass('C2');
|
||||
const c2 = classParser.getClass('C2');
|
||||
expect(c2.label).toBe('Class with text label');
|
||||
|
||||
const c3 = classDb.getClass('C3');
|
||||
const c3 = classParser.getClass('C3');
|
||||
expect(c3.label).toBe('Class with text label');
|
||||
});
|
||||
|
||||
@@ -1550,19 +1550,19 @@ class C11["With ' single quote"]
|
||||
class C12["With ~!@#$%^&*()_+=-/?"]
|
||||
class C13["With Città foreign language"]
|
||||
`);
|
||||
expect(classDb.getClass('C1').label).toBe('OneWord');
|
||||
expect(classDb.getClass('C2').label).toBe('With, Comma');
|
||||
expect(classDb.getClass('C3').label).toBe('With (Brackets)');
|
||||
expect(classDb.getClass('C4').label).toBe('With [Brackets]');
|
||||
expect(classDb.getClass('C5').label).toBe('With {Brackets}');
|
||||
expect(classDb.getClass('C6').label).toBe(' ');
|
||||
expect(classDb.getClass('C7').label).toBe('With 1 number');
|
||||
expect(classDb.getClass('C8').label).toBe('With . period...');
|
||||
expect(classDb.getClass('C9').label).toBe('With - dash');
|
||||
expect(classDb.getClass('C10').label).toBe('With _ underscore');
|
||||
expect(classDb.getClass('C11').label).toBe("With ' single quote");
|
||||
expect(classDb.getClass('C12').label).toBe('With ~!@#$%^&*()_+=-/?');
|
||||
expect(classDb.getClass('C13').label).toBe('With Città foreign language');
|
||||
expect(classParser.getClass('C1').label).toBe('OneWord');
|
||||
expect(classParser.getClass('C2').label).toBe('With, Comma');
|
||||
expect(classParser.getClass('C3').label).toBe('With (Brackets)');
|
||||
expect(classParser.getClass('C4').label).toBe('With [Brackets]');
|
||||
expect(classParser.getClass('C5').label).toBe('With {Brackets}');
|
||||
expect(classParser.getClass('C6').label).toBe(' ');
|
||||
expect(classParser.getClass('C7').label).toBe('With 1 number');
|
||||
expect(classParser.getClass('C8').label).toBe('With . period...');
|
||||
expect(classParser.getClass('C9').label).toBe('With - dash');
|
||||
expect(classParser.getClass('C10').label).toBe('With _ underscore');
|
||||
expect(classParser.getClass('C11').label).toBe("With ' single quote");
|
||||
expect(classParser.getClass('C12').label).toBe('With ~!@#$%^&*()_+=-/?');
|
||||
expect(classParser.getClass('C13').label).toBe('With Città foreign language');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { DiagramDefinition } from '../../diagram-api/types.js';
|
||||
// @ts-ignore: TODO Fix ts errors
|
||||
import parser from './parser/classDiagram.jison';
|
||||
import db from './classDb.js';
|
||||
import db from './classParser.js';
|
||||
import styles from './styles.js';
|
||||
import renderer from './classRenderer.js';
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { setConfig } from '../../config.js';
|
||||
import classDB from './classDb.js';
|
||||
import classParser from './classParser.js';
|
||||
// @ts-ignore - no types in jison
|
||||
import classDiagram from './parser/classDiagram.jison';
|
||||
|
||||
@@ -9,7 +9,7 @@ setConfig({
|
||||
|
||||
describe('when parsing class diagram', function () {
|
||||
beforeEach(function () {
|
||||
classDiagram.parser.yy = classDB;
|
||||
classDiagram.parser.yy = classParser;
|
||||
classDiagram.parser.yy.clear();
|
||||
});
|
||||
|
||||
@@ -30,8 +30,8 @@ describe('when parsing class diagram', function () {
|
||||
Student "1" --o "1" IdCard : carries
|
||||
Student "1" --o "1" Bike : rides`);
|
||||
|
||||
expect(Object.keys(classDB.getClasses()).length).toBe(3);
|
||||
expect(classDB.getClasses().Student).toMatchInlineSnapshot(`
|
||||
expect(Object.keys(classParser.getClasses()).length).toBe(3);
|
||||
expect(classParser.getClasses().Student).toMatchInlineSnapshot(`
|
||||
{
|
||||
"annotations": [],
|
||||
"cssClasses": [],
|
||||
@@ -45,8 +45,8 @@ describe('when parsing class diagram', function () {
|
||||
"type": "",
|
||||
}
|
||||
`);
|
||||
expect(classDB.getRelations().length).toBe(2);
|
||||
expect(classDB.getRelations()).toMatchInlineSnapshot(`
|
||||
expect(classParser.getRelations().length).toBe(2);
|
||||
expect(classParser.getRelations()).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"id1": "Student",
|
||||
|
@@ -255,6 +255,7 @@ export const getTooltip = function (id: string, namespace?: string) {
|
||||
|
||||
return classes[id].tooltip;
|
||||
};
|
||||
|
||||
/**
|
||||
* Called by parser when a link is found. Adds the URL to the vertex data.
|
||||
*
|
@@ -92,7 +92,6 @@ export const addClasses = function (
|
||||
log.info('keys:', keys);
|
||||
log.info(classes);
|
||||
|
||||
// Iterate through each item in the vertex object (containing all the vertices found) in the graph definition
|
||||
keys.forEach(function (id) {
|
||||
const vertex = classes[id];
|
||||
|
||||
@@ -157,24 +156,17 @@ export const addNotes = function (
|
||||
) {
|
||||
log.info(notes);
|
||||
|
||||
// Iterate through each item in the vertex object (containing all the vertices found) in the graph definition
|
||||
notes.forEach(function (note, i) {
|
||||
const vertex = note;
|
||||
|
||||
/**
|
||||
* Variable for storing the classes for the vertex
|
||||
*
|
||||
*/
|
||||
const cssNoteStr = '';
|
||||
|
||||
const styles = { labelStyle: '', style: '' };
|
||||
|
||||
// Use vertex id as text in the box if no text is provided by the graph definition
|
||||
const vertexText = vertex.text;
|
||||
|
||||
const radius = 0;
|
||||
const shape = 'note';
|
||||
// Add the node
|
||||
const node = {
|
||||
labelStyle: styles.labelStyle,
|
||||
shape: shape,
|
||||
@@ -302,7 +294,7 @@ export const setConf = function (cnf: any) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Draws a flowchart in the tag with id: id based on the graph definition in text.
|
||||
* Draws a class diagram in the tag with id: id based on the definition in text.
|
||||
*
|
||||
* @param text -
|
||||
* @param id -
|
||||
@@ -353,9 +345,7 @@ export const draw = async function (text: string, id: string, _version: string,
|
||||
}
|
||||
const root =
|
||||
securityLevel === 'sandbox'
|
||||
? // @ts-ignore Ignore type error for now
|
||||
|
||||
select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
: select('body');
|
||||
// @ts-ignore Ignore type error for now
|
||||
const svg = root.select(`[id="${id}"]`);
|
||||
|
211
packages/mermaid/src/diagrams/class/classTypes.spec.ts
Normal file
211
packages/mermaid/src/diagrams/class/classTypes.spec.ts
Normal file
@@ -0,0 +1,211 @@
|
||||
import { ClassMember } from './classTypes.js';
|
||||
import { vi, describe, it, expect } from 'vitest';
|
||||
const spyOn = vi.spyOn;
|
||||
|
||||
describe('given text representing member declaration, ', function () {
|
||||
describe('when text is a method with no parameters', function () {
|
||||
it('should parse simple method', function () {
|
||||
const str = `getTime()`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe(str);
|
||||
});
|
||||
|
||||
it('should parse public visibiity', function () {
|
||||
const str = `+getTime()`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe('+getTime()');
|
||||
});
|
||||
|
||||
it('should parse private visibiity', function () {
|
||||
const str = `-getTime()`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe('-getTime()');
|
||||
});
|
||||
|
||||
it('should parse protected visibiity', function () {
|
||||
const str = `#getTime()`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe('#getTime()');
|
||||
});
|
||||
|
||||
it('should parse internal visibiity', function () {
|
||||
const str = `~getTime()`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe('~getTime()');
|
||||
});
|
||||
|
||||
it('should return correct css for static classifier', function () {
|
||||
const str = `getTime()$`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe('getTime()');
|
||||
expect(classMember.getDisplayDetails().cssStyle).toBe('text-decoration:underline;');
|
||||
});
|
||||
|
||||
it('should return correct css for abstrtact', function () {
|
||||
const str = `getTime()*`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe('getTime()');
|
||||
expect(classMember.getDisplayDetails().cssStyle).toBe('font-style:italic;');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when text is a method with parameters', function () {
|
||||
it('should parse method with parameter type, as provided', function () {
|
||||
const str = `getTime(String)`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe(str);
|
||||
});
|
||||
|
||||
it('should parse method with parameter type and name, as provided', function () {
|
||||
const str = `getTime(String time)`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe(str);
|
||||
});
|
||||
|
||||
it('should parse method with parameters, as provided', function () {
|
||||
const str = `getTime(String time, date Date)`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe(str);
|
||||
});
|
||||
|
||||
it('should return correct css for static method with parameter type, as provided', function () {
|
||||
const str = `getTime(String)$`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe('getTime(String)');
|
||||
expect(classMember.getDisplayDetails().cssStyle).toBe('text-decoration:underline;');
|
||||
});
|
||||
|
||||
it('should return correct css for static method with parameter type and name, as provided', function () {
|
||||
const str = `getTime(String time)$`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe('getTime(String time)');
|
||||
expect(classMember.getDisplayDetails().cssStyle).toBe('text-decoration:underline;');
|
||||
});
|
||||
|
||||
it('should return correct css for static method with parameters, as provided', function () {
|
||||
const str = `getTime(String time, date Date)$`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe('getTime(String time, date Date)');
|
||||
expect(classMember.getDisplayDetails().cssStyle).toBe('text-decoration:underline;');
|
||||
});
|
||||
|
||||
it('should return correct css for abstract method with parameter type, as provided', function () {
|
||||
const str = `getTime(String)*`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe('getTime(String)');
|
||||
expect(classMember.getDisplayDetails().cssStyle).toBe('font-style:italic;');
|
||||
});
|
||||
|
||||
it('should return correct css for abstract method with parameter type and name, as provided', function () {
|
||||
const str = `getTime(String time)*`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe('getTime(String time)');
|
||||
expect(classMember.getDisplayDetails().cssStyle).toBe('font-style:italic;');
|
||||
});
|
||||
|
||||
it('should return correct css for abstract method with parameters, as provided', function () {
|
||||
const str = `getTime(String time, date Date)*`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe('getTime(String time, date Date)');
|
||||
expect(classMember.getDisplayDetails().cssStyle).toBe('font-style:italic;');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when text is a method with return type', function () {
|
||||
it('should parse simple method with no parameter', function () {
|
||||
const str = `getTime() String`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe(str);
|
||||
});
|
||||
|
||||
it('should parse method with parameter type, as provided', function () {
|
||||
const str = `getTime(String) String`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe(str);
|
||||
});
|
||||
|
||||
it('should parse method with parameter type and name, as provided', function () {
|
||||
const str = `getTime(String time) String`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe(str);
|
||||
});
|
||||
|
||||
it('should parse method with parameters, as provided', function () {
|
||||
const str = `getTime(String time, date Date) String`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe(str);
|
||||
});
|
||||
|
||||
it('should return correct css for static method with no parameter', function () {
|
||||
const str = `getTime() String$`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe('getTime() String');
|
||||
expect(classMember.getDisplayDetails().cssStyle).toBe('text-decoration:underline;');
|
||||
});
|
||||
|
||||
it('should return correct css for static method with parameter type and name, as provided', function () {
|
||||
const str = `getTime(String time) String$`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe('getTime(String time) String');
|
||||
expect(classMember.getDisplayDetails().cssStyle).toBe('text-decoration:underline;');
|
||||
});
|
||||
|
||||
it('should return correct css for static method with parameters, as provided', function () {
|
||||
const str = `getTime(String time, date Date)$ String`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe(
|
||||
'getTime(String time, date Date) String'
|
||||
);
|
||||
expect(classMember.getDisplayDetails().cssStyle).toBe('text-decoration:underline;');
|
||||
});
|
||||
|
||||
it('should return correct css for abstract method with parameter type, as provided', function () {
|
||||
const str = `getTime(String) String*`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe('getTime(String) String');
|
||||
expect(classMember.getDisplayDetails().cssStyle).toBe('font-style:italic;');
|
||||
});
|
||||
|
||||
it('should return correct css for abstract method with parameter type and name, as provided', function () {
|
||||
const str = `getTime(String time) String*`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe('getTime(String time) String');
|
||||
expect(classMember.getDisplayDetails().cssStyle).toBe('font-style:italic;');
|
||||
});
|
||||
|
||||
it('should return correct css for abstract method with parameters, as provided', function () {
|
||||
const str = `getTime(String time, date Date) String*`;
|
||||
|
||||
const classMember = new ClassMember(str, 'method');
|
||||
expect(classMember.getDisplayDetails().displayText).toBe(
|
||||
'getTime(String time, date Date) String'
|
||||
);
|
||||
expect(classMember.getDisplayDetails().cssStyle).toBe('font-style:italic;');
|
||||
});
|
||||
});
|
||||
});
|
@@ -1,3 +1,5 @@
|
||||
import { parseGenericTypes } from '../common/common.js';
|
||||
|
||||
export interface ClassNode {
|
||||
id: string;
|
||||
type: string;
|
||||
@@ -13,6 +15,90 @@ export interface ClassNode {
|
||||
tooltip?: string;
|
||||
}
|
||||
|
||||
export class ClassMember {
|
||||
id!: string;
|
||||
cssStyle!: string;
|
||||
memberType!: string;
|
||||
visibility!: string;
|
||||
classifier!: string;
|
||||
parameters!: string;
|
||||
returnType!: string;
|
||||
|
||||
constructor(input: string, memberType: string) {
|
||||
this.memberType = memberType;
|
||||
this.parseMember(input);
|
||||
}
|
||||
|
||||
getDisplayDetails() {
|
||||
let displayText = this.visibility + parseGenericTypes(this.id);
|
||||
if (this.memberType === 'method') {
|
||||
displayText += '(' + parseGenericTypes(this.parameters.trim()) + ')' + ' ' + this.returnType;
|
||||
}
|
||||
|
||||
displayText = displayText.trim();
|
||||
const cssStyle = this.parseClassifier();
|
||||
|
||||
return {
|
||||
displayText,
|
||||
cssStyle,
|
||||
};
|
||||
}
|
||||
|
||||
parseMember(input: string) {
|
||||
let potentialClassifier = '';
|
||||
|
||||
if (this.memberType === 'method') {
|
||||
const methodRegEx = /([#+~-])?(.+)\((.*)\)([\s$*])?(.*)([$*])?/;
|
||||
const match = input.match(methodRegEx);
|
||||
if (match) {
|
||||
this.visibility = match[1] ? match[1].trim() : '';
|
||||
this.id = match[2].trim();
|
||||
this.parameters = match[3] ? match[3].trim() : '';
|
||||
potentialClassifier = match[4] ? match[4].trim() : '';
|
||||
this.returnType = match[5] ? match[5].trim() : '';
|
||||
|
||||
if (potentialClassifier === '') {
|
||||
const lastChar = this.returnType.substring(this.returnType.length - 1);
|
||||
if (lastChar.match(/[$*]/)) {
|
||||
potentialClassifier = lastChar;
|
||||
this.returnType = this.returnType.substring(0, this.returnType.length - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const length = input.length;
|
||||
const firstChar = input.substring(0, 1);
|
||||
const lastChar = input.substring(length - 1);
|
||||
|
||||
if (firstChar.match(/[#+~-]/)) {
|
||||
this.visibility = firstChar;
|
||||
}
|
||||
|
||||
if (lastChar.match(/[*?]/)) {
|
||||
potentialClassifier = lastChar;
|
||||
}
|
||||
|
||||
this.id = input.substring(
|
||||
this.visibility === '' ? 0 : 1,
|
||||
potentialClassifier === '' ? length : length - 1
|
||||
);
|
||||
}
|
||||
|
||||
this.classifier = potentialClassifier;
|
||||
}
|
||||
|
||||
parseClassifier() {
|
||||
switch (this.classifier) {
|
||||
case '*':
|
||||
return 'font-style:italic;';
|
||||
case '$':
|
||||
return 'text-decoration:underline;';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface ClassNote {
|
||||
id: string;
|
||||
class: string;
|
||||
|
@@ -226,21 +226,14 @@ start
|
||||
| statements
|
||||
;
|
||||
|
||||
direction
|
||||
: direction_tb
|
||||
{ yy.setDirection('TB');}
|
||||
| direction_bt
|
||||
{ yy.setDirection('BT');}
|
||||
| direction_rl
|
||||
{ yy.setDirection('RL');}
|
||||
| direction_lr
|
||||
{ yy.setDirection('LR');}
|
||||
;
|
||||
|
||||
mermaidDoc
|
||||
: graphConfig
|
||||
;
|
||||
|
||||
graphConfig
|
||||
: CLASS_DIAGRAM NEWLINE statements EOF
|
||||
;
|
||||
|
||||
directive
|
||||
: openDirective typeDirective closeDirective NEWLINE
|
||||
| openDirective typeDirective ':' argDirective closeDirective NEWLINE
|
||||
@@ -262,10 +255,6 @@ closeDirective
|
||||
: close_directive { yy.parseDirective('}%%', 'close_directive', 'class'); }
|
||||
;
|
||||
|
||||
graphConfig
|
||||
: CLASS_DIAGRAM NEWLINE statements EOF
|
||||
;
|
||||
|
||||
statements
|
||||
: statement
|
||||
| statement NEWLINE
|
||||
@@ -294,7 +283,7 @@ statement
|
||||
| relationStatement LABEL { $1.title = yy.cleanupLabel($2); yy.addRelation($1); }
|
||||
| namespaceStatement
|
||||
| classStatement
|
||||
| methodStatement
|
||||
| memberStatement
|
||||
| annotationStatement
|
||||
| clickStatement
|
||||
| cssClassStatement
|
||||
@@ -341,7 +330,7 @@ members
|
||||
| MEMBER members { $2.push($1);$$=$2;}
|
||||
;
|
||||
|
||||
methodStatement
|
||||
memberStatement
|
||||
: className {/*console.log('Rel found',$1);*/}
|
||||
| className LABEL {yy.addMember($1,yy.cleanupLabel($2));}
|
||||
| MEMBER {/*console.warn('Member',$1);*/}
|
||||
@@ -360,6 +349,17 @@ noteStatement
|
||||
| NOTE noteText { yy.addNote($2); }
|
||||
;
|
||||
|
||||
direction
|
||||
: direction_tb
|
||||
{ yy.setDirection('TB');}
|
||||
| direction_bt
|
||||
{ yy.setDirection('BT');}
|
||||
| direction_rl
|
||||
{ yy.setDirection('RL');}
|
||||
| direction_lr
|
||||
{ yy.setDirection('LR');}
|
||||
;
|
||||
|
||||
relation
|
||||
: relationType lineType relationType { $$={type1:$1,type2:$3,lineType:$2}; }
|
||||
| lineType relationType { $$={type1:'none',type2:$2,lineType:$1}; }
|
||||
|
@@ -172,7 +172,6 @@ export const drawClass = function (elem, classDef, conf, diagObj) {
|
||||
// add class group
|
||||
const g = elem.append('g').attr('id', diagObj.db.lookUpDomId(id)).attr('class', 'classGroup');
|
||||
|
||||
// add title
|
||||
let title;
|
||||
if (classDef.link) {
|
||||
title = g
|
||||
@@ -209,47 +208,56 @@ export const drawClass = function (elem, classDef, conf, diagObj) {
|
||||
}
|
||||
|
||||
const titleHeight = title.node().getBBox().height;
|
||||
let membersLine;
|
||||
let membersBox;
|
||||
let methodsLine;
|
||||
|
||||
const membersLine = g
|
||||
.append('line') // text label for the x axis
|
||||
.attr('x1', 0)
|
||||
.attr('y1', conf.padding + titleHeight + conf.dividerMargin / 2)
|
||||
.attr('y2', conf.padding + titleHeight + conf.dividerMargin / 2);
|
||||
// don't draw box if no members
|
||||
if (classDef.members.length > 0) {
|
||||
membersLine = g
|
||||
.append('line') // text label for the x axis
|
||||
.attr('x1', 0)
|
||||
.attr('y1', conf.padding + titleHeight + conf.dividerMargin / 2)
|
||||
.attr('y2', conf.padding + titleHeight + conf.dividerMargin / 2);
|
||||
|
||||
const members = g
|
||||
.append('text') // text label for the x axis
|
||||
.attr('x', conf.padding)
|
||||
.attr('y', titleHeight + conf.dividerMargin + conf.textHeight)
|
||||
.attr('fill', 'white')
|
||||
.attr('class', 'classText');
|
||||
const members = g
|
||||
.append('text') // text label for the x axis
|
||||
.attr('x', conf.padding)
|
||||
.attr('y', titleHeight + conf.dividerMargin + conf.textHeight)
|
||||
.attr('fill', 'white')
|
||||
.attr('class', 'classText');
|
||||
|
||||
isFirst = true;
|
||||
classDef.members.forEach(function (member) {
|
||||
addTspan(members, member, isFirst, conf);
|
||||
isFirst = false;
|
||||
});
|
||||
isFirst = true;
|
||||
classDef.members.forEach(function (member) {
|
||||
addTspan(members, member, isFirst, conf);
|
||||
isFirst = false;
|
||||
});
|
||||
|
||||
const membersBox = members.node().getBBox();
|
||||
membersBox = members.node().getBBox();
|
||||
}
|
||||
|
||||
const methodsLine = g
|
||||
.append('line') // text label for the x axis
|
||||
.attr('x1', 0)
|
||||
.attr('y1', conf.padding + titleHeight + conf.dividerMargin + membersBox.height)
|
||||
.attr('y2', conf.padding + titleHeight + conf.dividerMargin + membersBox.height);
|
||||
// don't draw box if no methods
|
||||
if (classDef.methods.length > 0) {
|
||||
methodsLine = g
|
||||
.append('line') // text label for the x axis
|
||||
.attr('x1', 0)
|
||||
.attr('y1', conf.padding + titleHeight + conf.dividerMargin + membersBox.height)
|
||||
.attr('y2', conf.padding + titleHeight + conf.dividerMargin + membersBox.height);
|
||||
|
||||
const methods = g
|
||||
.append('text') // text label for the x axis
|
||||
.attr('x', conf.padding)
|
||||
.attr('y', titleHeight + 2 * conf.dividerMargin + membersBox.height + conf.textHeight)
|
||||
.attr('fill', 'white')
|
||||
.attr('class', 'classText');
|
||||
const methods = g
|
||||
.append('text') // text label for the x axis
|
||||
.attr('x', conf.padding)
|
||||
.attr('y', titleHeight + 2 * conf.dividerMargin + membersBox.height + conf.textHeight)
|
||||
.attr('fill', 'white')
|
||||
.attr('class', 'classText');
|
||||
|
||||
isFirst = true;
|
||||
isFirst = true;
|
||||
|
||||
classDef.methods.forEach(function (method) {
|
||||
addTspan(methods, method, isFirst, conf);
|
||||
isFirst = false;
|
||||
});
|
||||
classDef.methods.forEach(function (method) {
|
||||
addTspan(methods, method, isFirst, conf);
|
||||
isFirst = false;
|
||||
});
|
||||
}
|
||||
|
||||
const classBox = g.node().getBBox();
|
||||
var cssClassStr = ' ';
|
||||
@@ -278,8 +286,12 @@ export const drawClass = function (elem, classDef, conf, diagObj) {
|
||||
title.insert('title').text(classDef.tooltip);
|
||||
}
|
||||
|
||||
membersLine.attr('x2', rectWidth);
|
||||
methodsLine.attr('x2', rectWidth);
|
||||
if (membersLine) {
|
||||
membersLine.attr('x2', rectWidth);
|
||||
}
|
||||
if (methodsLine) {
|
||||
methodsLine.attr('x2', rectWidth);
|
||||
}
|
||||
|
||||
classInfo.width = rectWidth;
|
||||
classInfo.height = classBox.height + conf.padding + 0.5 * conf.dividerMargin;
|
||||
@@ -366,20 +378,20 @@ export const parseMember = function (text) {
|
||||
let returnType = '';
|
||||
|
||||
let visibility = '';
|
||||
let firstChar = text.substring(0, 1);
|
||||
let lastChar = text.substring(text.length - 1, text.length);
|
||||
const firstChar = text.substring(0, 1);
|
||||
const lastChar = text.substring(text.length - 1, text.length);
|
||||
|
||||
if (firstChar.match(/[#+~-]/)) {
|
||||
visibility = firstChar;
|
||||
}
|
||||
|
||||
let noClassifierRe = /[\s\w)~]/;
|
||||
const noClassifierRe = /[\s\w)~]/;
|
||||
if (!lastChar.match(noClassifierRe)) {
|
||||
cssStyle = parseClassifier(lastChar);
|
||||
}
|
||||
|
||||
const startIndex = visibility === '' ? 0 : 1;
|
||||
let endIndex = cssStyle === '' ? text.length : text.length - 1;
|
||||
const endIndex = cssStyle === '' ? text.length : text.length - 1;
|
||||
text = text.substring(startIndex, endIndex);
|
||||
|
||||
const methodStart = text.indexOf('(');
|
||||
@@ -387,8 +399,7 @@ export const parseMember = function (text) {
|
||||
const isMethod = methodStart > 1 && methodEnd > methodStart && methodEnd <= text.length;
|
||||
|
||||
if (isMethod) {
|
||||
let methodName = text.substring(0, methodStart).trim();
|
||||
|
||||
const methodName = text.substring(0, methodStart).trim();
|
||||
const parameters = text.substring(methodStart + 1, methodEnd);
|
||||
|
||||
displayText = visibility + methodName + '(' + parseGenericTypes(parameters.trim()) + ')';
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import svgDraw from './svgDraw.js';
|
||||
|
||||
describe('given a string representing class method, ', function () {
|
||||
describe('given a string representing a class, ', function () {
|
||||
it('should handle class names with generics', function () {
|
||||
const classDef = {
|
||||
id: 'Car',
|
||||
@@ -11,8 +11,18 @@ describe('given a string representing class method, ', function () {
|
||||
let actual = svgDraw.getClassTitleString(classDef);
|
||||
expect(actual).toBe('Car<T>');
|
||||
});
|
||||
it('should handle class names with nested generics', function () {
|
||||
const classDef = {
|
||||
id: 'Car',
|
||||
type: 'T~TT~',
|
||||
label: 'Car',
|
||||
};
|
||||
|
||||
describe('when parsing base method declaration', function () {
|
||||
let actual = svgDraw.getClassTitleString(classDef);
|
||||
expect(actual).toBe('Car<T<T>>');
|
||||
});
|
||||
|
||||
describe('when parsing member method', function () {
|
||||
it('should handle simple declaration', function () {
|
||||
const str = 'foo()';
|
||||
let actual = svgDraw.parseMember(str);
|
||||
@@ -116,10 +126,8 @@ describe('given a string representing class method, ', function () {
|
||||
expect(actual.displayText).toBe('+foo(List<List<int>> ids) : List<List<Item>>');
|
||||
expect(actual.cssStyle).toBe('font-style:italic;');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when parsing method visibility', function () {
|
||||
it('should correctly handle public', function () {
|
||||
it('should correctly handle public visibility', function () {
|
||||
const str = '+foo()';
|
||||
let actual = svgDraw.parseMember(str);
|
||||
|
||||
@@ -127,7 +135,7 @@ describe('given a string representing class method, ', function () {
|
||||
expect(actual.cssStyle).toBe('');
|
||||
});
|
||||
|
||||
it('should correctly handle private', function () {
|
||||
it('should correctly handle private visibility', function () {
|
||||
const str = '-foo()';
|
||||
let actual = svgDraw.parseMember(str);
|
||||
|
||||
@@ -135,7 +143,7 @@ describe('given a string representing class method, ', function () {
|
||||
expect(actual.cssStyle).toBe('');
|
||||
});
|
||||
|
||||
it('should correctly handle protected', function () {
|
||||
it('should correctly handle protected visibility', function () {
|
||||
const str = '#foo()';
|
||||
let actual = svgDraw.parseMember(str);
|
||||
|
||||
@@ -143,16 +151,14 @@ describe('given a string representing class method, ', function () {
|
||||
expect(actual.cssStyle).toBe('');
|
||||
});
|
||||
|
||||
it('should correctly handle package/internal', function () {
|
||||
it('should correctly handle package/internal visibility', function () {
|
||||
const str = '~foo()';
|
||||
let actual = svgDraw.parseMember(str);
|
||||
|
||||
expect(actual.displayText).toBe('~foo()');
|
||||
expect(actual.cssStyle).toBe('');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when parsing method classifier', function () {
|
||||
it('should handle abstract method', function () {
|
||||
const str = 'foo()*';
|
||||
let actual = svgDraw.parseMember(str);
|
||||
@@ -217,10 +223,8 @@ describe('given a string representing class method, ', function () {
|
||||
expect(actual.cssStyle).toBe('');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('given a string representing class member, ', function () {
|
||||
describe('when parsing member declaration', function () {
|
||||
describe('when parsing member field', function () {
|
||||
it('should handle simple field', function () {
|
||||
const str = 'id';
|
||||
let actual = svgDraw.parseMember(str);
|
||||
@@ -276,9 +280,7 @@ describe('given a string representing class member, ', function () {
|
||||
expect(actual.displayText).toBe('ids: List<int>');
|
||||
expect(actual.cssStyle).toBe('');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when parsing classifiers', function () {
|
||||
it('should handle static field', function () {
|
||||
const str = 'String foo$';
|
||||
let actual = svgDraw.parseMember(str);
|
||||
@@ -328,3 +330,12 @@ describe('given a string representing class member, ', function () {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('given a string representing class with no members, ', function () {
|
||||
it('should have no members', function () {
|
||||
const str = 'class Class10';
|
||||
let actual = svgDraw.drawClass(str);
|
||||
|
||||
expect(actual.displayText).toBe('');
|
||||
});
|
||||
});
|
||||
|
@@ -178,13 +178,15 @@ export const getMin = function (...values: number[]): number {
|
||||
* @returns The converted string
|
||||
*/
|
||||
export const parseGenericTypes = function (text: string): string {
|
||||
if (!text) {
|
||||
return '';
|
||||
}
|
||||
|
||||
let cleanedText = text;
|
||||
|
||||
if (text.split('~').length - 1 >= 2) {
|
||||
let newCleanedText = cleanedText;
|
||||
|
||||
// use a do...while loop instead of replaceAll to detect recursion
|
||||
// e.g. Array~Array~T~~
|
||||
do {
|
||||
cleanedText = newCleanedText;
|
||||
newCleanedText = cleanedText.replace(/~([^\s,:;]+)~/, '<$1>');
|
||||
|
Reference in New Issue
Block a user