mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-07 01:26:42 +02:00
Multiple Fixes to classes
This commit is contained in:
@@ -128,7 +128,7 @@ classDiagram
|
|||||||
Vehicle <|-- Car
|
Vehicle <|-- Car
|
||||||
```
|
```
|
||||||
|
|
||||||
Naming convention: a class name should be composed only of alphanumeric characters (including unicode), and underscores.
|
Naming convention: a class name should be composed only of alphanumeric characters (including unicode), underscores, and dashes (-).
|
||||||
|
|
||||||
### Class labels
|
### Class labels
|
||||||
|
|
||||||
@@ -283,12 +283,12 @@ To describe the visibility (or encapsulation) of an attribute or method/function
|
|||||||
- `#` Protected
|
- `#` Protected
|
||||||
- `~` Package/Internal
|
- `~` Package/Internal
|
||||||
|
|
||||||
> _note_ you can also include additional _classifiers_ to a method definition by adding the following notation to the _end_ of the method, i.e.: after the `()`:
|
> _note_ you can also include additional _classifiers_ to a method definition by adding the following notation to the _end_ of the method, i.e.: after the `()` or after the return type:
|
||||||
>
|
>
|
||||||
> - `*` Abstract e.g.: `someAbstractMethod()*`
|
> - `*` Abstract e.g.: `someAbstractMethod()*` or `someAbstractMethod() int*`
|
||||||
> - `$` Static e.g.: `someStaticMethod()$`
|
> - `$` Static e.g.: `someStaticMethod()$` or `someStaticMethod() String$`
|
||||||
|
|
||||||
> _note_ you can also include additional _classifiers_ to a field definition by adding the following notation to the end of its name:
|
> _note_ you can also include additional _classifiers_ to a field definition by adding the following notation to the very end:
|
||||||
>
|
>
|
||||||
> - `$` Static e.g.: `String someField$`
|
> - `$` Static e.g.: `String someField$`
|
||||||
|
|
||||||
|
@@ -106,6 +106,7 @@ export const clear = function () {
|
|||||||
export const getClass = function (id: string) {
|
export const getClass = function (id: string) {
|
||||||
return classes[id];
|
return classes[id];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getClasses = function () {
|
export const getClasses = function () {
|
||||||
return classes;
|
return classes;
|
||||||
};
|
};
|
||||||
@@ -170,9 +171,10 @@ export const addMember = function (className: string, member: string) {
|
|||||||
const memberString = member.trim();
|
const memberString = member.trim();
|
||||||
|
|
||||||
if (memberString.startsWith('<<') && memberString.endsWith('>>')) {
|
if (memberString.startsWith('<<') && memberString.endsWith('>>')) {
|
||||||
// Remove leading and trailing brackets
|
// its an annotation
|
||||||
theClass.annotations.push(sanitizeText(memberString.substring(2, memberString.length - 2)));
|
theClass.annotations.push(sanitizeText(memberString.substring(2, memberString.length - 2)));
|
||||||
} else if (memberString.indexOf(')') > 0) {
|
} else if (memberString.indexOf(')') > 0) {
|
||||||
|
//its a method
|
||||||
theClass.methods.push(sanitizeText(memberString));
|
theClass.methods.push(sanitizeText(memberString));
|
||||||
} else if (memberString) {
|
} else if (memberString) {
|
||||||
theClass.members.push(sanitizeText(memberString));
|
theClass.members.push(sanitizeText(memberString));
|
||||||
@@ -234,6 +236,7 @@ const setTooltip = function (ids: string, tooltip?: string) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getTooltip = function (id: string) {
|
export const getTooltip = function (id: string) {
|
||||||
return classes[id].tooltip;
|
return classes[id].tooltip;
|
||||||
};
|
};
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -259,8 +259,8 @@ className
|
|||||||
: alphaNumToken { $$=$1; }
|
: alphaNumToken { $$=$1; }
|
||||||
| classLiteralName { $$=$1; }
|
| classLiteralName { $$=$1; }
|
||||||
| alphaNumToken className { $$=$1+$2; }
|
| alphaNumToken className { $$=$1+$2; }
|
||||||
| alphaNumToken GENERICTYPE { $$=$1+'~'+$2; }
|
| alphaNumToken GENERICTYPE { $$=$1+'~'+$2+'~'; }
|
||||||
| classLiteralName GENERICTYPE { $$=$1+'~'+$2; }
|
| classLiteralName GENERICTYPE { $$=$1+'~'+$2+'~'; }
|
||||||
;
|
;
|
||||||
|
|
||||||
statement
|
statement
|
||||||
@@ -366,7 +366,7 @@ textToken : textNoTagsToken | TAGSTART | TAGEND | '==' | '--' | PCT | DEFA
|
|||||||
|
|
||||||
textNoTagsToken: alphaNumToken | SPACE | MINUS | keywords ;
|
textNoTagsToken: alphaNumToken | SPACE | MINUS | keywords ;
|
||||||
|
|
||||||
alphaNumToken : UNICODE_TEXT | NUM | ALPHA;
|
alphaNumToken : UNICODE_TEXT | NUM | ALPHA | MINUS;
|
||||||
|
|
||||||
classLiteralName : BQUOTE_STR;
|
classLiteralName : BQUOTE_STR;
|
||||||
|
|
||||||
|
@@ -199,11 +199,7 @@ export const drawClass = function (elem, classDef, conf, diagObj) {
|
|||||||
isFirst = false;
|
isFirst = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
let classTitleString = classDef.id;
|
let classTitleString = getClassTitleString(classDef);
|
||||||
|
|
||||||
if (classDef.type !== undefined && classDef.type !== '') {
|
|
||||||
classTitleString += '<' + classDef.type + '>';
|
|
||||||
}
|
|
||||||
|
|
||||||
const classTitle = title.append('tspan').text(classTitleString).attr('class', 'title');
|
const classTitle = title.append('tspan').text(classTitleString).attr('class', 'title');
|
||||||
|
|
||||||
@@ -291,6 +287,16 @@ export const drawClass = function (elem, classDef, conf, diagObj) {
|
|||||||
return classInfo;
|
return classInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getClassTitleString = function (classDef) {
|
||||||
|
let classTitleString = classDef.id;
|
||||||
|
|
||||||
|
if (classDef.type) {
|
||||||
|
classTitleString += '<' + classDef.type + '>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return classTitleString;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders a note diagram
|
* Renders a note diagram
|
||||||
*
|
*
|
||||||
@@ -355,6 +361,9 @@ export const drawNote = function (elem, note, conf, diagObj) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const parseMember = function (text) {
|
export const parseMember = function (text) {
|
||||||
|
// Note: these two regular expressions don't parse the official UML syntax for attributes
|
||||||
|
// and methods. They parse a Java-style syntax of the form
|
||||||
|
// "String name" (for attributes) and "String name(int x)" for methods
|
||||||
const fieldRegEx = /^([#+~-])?(\w+)(~\w+~|\[])?\s+(\w+) *([$*])?$/;
|
const fieldRegEx = /^([#+~-])?(\w+)(~\w+~|\[])?\s+(\w+) *([$*])?$/;
|
||||||
const methodRegEx = /^([#+|~-])?(\w+) *\( *(.*)\) *([$*])? *(\w*[[\]|~]*\s*\w*~?)$/;
|
const methodRegEx = /^([#+|~-])?(\w+) *\( *(.*)\) *([$*])? *(\w*[[\]|~]*\s*\w*~?)$/;
|
||||||
|
|
||||||
@@ -421,33 +430,48 @@ const buildLegacyDisplay = function (text) {
|
|||||||
let displayText = '';
|
let displayText = '';
|
||||||
let cssStyle = '';
|
let cssStyle = '';
|
||||||
let returnType = '';
|
let returnType = '';
|
||||||
|
|
||||||
|
let visibility = '';
|
||||||
|
let firstChar = text.substring(0, 1);
|
||||||
|
let lastChar = text.substring(text.length - 1, text.length);
|
||||||
|
|
||||||
|
if (firstChar.match(/[#+~-]/)) {
|
||||||
|
visibility = firstChar;
|
||||||
|
}
|
||||||
|
|
||||||
|
let noClassifierRe = /[\s\w)~]/;
|
||||||
|
if (!lastChar.match(noClassifierRe)) {
|
||||||
|
cssStyle = parseClassifier(lastChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
let startIndex = visibility === '' ? 0 : 1;
|
||||||
|
let endIndex = cssStyle === '' ? text.length : text.length - 1;
|
||||||
|
text = text.substring(startIndex, endIndex);
|
||||||
|
|
||||||
let methodStart = text.indexOf('(');
|
let methodStart = text.indexOf('(');
|
||||||
let methodEnd = text.indexOf(')');
|
let methodEnd = text.indexOf(')');
|
||||||
|
|
||||||
if (methodStart > 1 && methodEnd > methodStart && methodEnd <= text.length) {
|
if (methodStart > 1 && methodEnd > methodStart && methodEnd <= text.length) {
|
||||||
let visibility = '';
|
let methodName = text.substring(0, methodStart).trim();
|
||||||
let methodName = '';
|
|
||||||
|
|
||||||
let firstChar = text.substring(0, 1);
|
|
||||||
if (firstChar.match(/\w/)) {
|
|
||||||
methodName = text.substring(0, methodStart).trim();
|
|
||||||
} else {
|
|
||||||
if (firstChar.match(/[#+~-]/)) {
|
|
||||||
visibility = firstChar;
|
|
||||||
}
|
|
||||||
|
|
||||||
methodName = text.substring(1, methodStart).trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
const parameters = text.substring(methodStart + 1, methodEnd);
|
const parameters = text.substring(methodStart + 1, methodEnd);
|
||||||
const classifier = text.substring(methodEnd + 1, 1);
|
|
||||||
cssStyle = parseClassifier(text.substring(methodEnd + 1, methodEnd + 2));
|
|
||||||
|
|
||||||
displayText = visibility + methodName + '(' + parseGenericTypes(parameters.trim()) + ')';
|
displayText = visibility + methodName + '(' + parseGenericTypes(parameters.trim()) + ')';
|
||||||
|
|
||||||
if (methodEnd < text.length) {
|
if (methodEnd < text.length) {
|
||||||
returnType = text.substring(methodEnd + 2).trim();
|
// special case: classifier after the closing parenthesis
|
||||||
|
let potentialClassifier = text.substring(methodEnd + 1, methodEnd + 2);
|
||||||
|
if (cssStyle === '' && !potentialClassifier.match(noClassifierRe)) {
|
||||||
|
cssStyle = parseClassifier(potentialClassifier);
|
||||||
|
returnType = text.substring(methodEnd + 2).trim();
|
||||||
|
} else {
|
||||||
|
returnType = text.substring(methodEnd + 1).trim();
|
||||||
|
}
|
||||||
|
|
||||||
if (returnType !== '') {
|
if (returnType !== '') {
|
||||||
|
if (returnType.charAt(0) === ':') {
|
||||||
|
returnType = returnType.substring(1).trim();
|
||||||
|
}
|
||||||
returnType = ' : ' + parseGenericTypes(returnType);
|
returnType = ' : ' + parseGenericTypes(returnType);
|
||||||
displayText += returnType;
|
displayText += returnType;
|
||||||
}
|
}
|
||||||
@@ -502,6 +526,7 @@ const parseClassifier = function (classifier) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
getClassTitleString,
|
||||||
drawClass,
|
drawClass,
|
||||||
drawEdge,
|
drawEdge,
|
||||||
drawNote,
|
drawNote,
|
||||||
|
@@ -1,8 +1,19 @@
|
|||||||
import svgDraw from './svgDraw.js';
|
import svgDraw from './svgDraw.js';
|
||||||
|
|
||||||
describe('class member Renderer, ', function () {
|
describe('given a string representing class method, ', function () {
|
||||||
describe('when parsing text to build method display string', function () {
|
it('should handle class names with generics', function () {
|
||||||
it('should handle simple method declaration', function () {
|
const classDef = {
|
||||||
|
id: 'Car',
|
||||||
|
type: 'T',
|
||||||
|
label: 'Car',
|
||||||
|
};
|
||||||
|
|
||||||
|
let actual = svgDraw.getClassTitleString(classDef);
|
||||||
|
expect(actual).toBe('Car<T>');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when parsing base method declaration', function () {
|
||||||
|
it('should handle simple declaration', function () {
|
||||||
const str = 'foo()';
|
const str = 'foo()';
|
||||||
let actual = svgDraw.parseMember(str);
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
@@ -10,71 +21,7 @@ describe('class member Renderer, ', function () {
|
|||||||
expect(actual.cssStyle).toBe('');
|
expect(actual.cssStyle).toBe('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle public visibility', function () {
|
it('should handle declaration with parameters', function () {
|
||||||
const str = '+foo()';
|
|
||||||
let actual = svgDraw.parseMember(str);
|
|
||||||
|
|
||||||
expect(actual.displayText).toBe('+foo()');
|
|
||||||
expect(actual.cssStyle).toBe('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle private visibility', function () {
|
|
||||||
const str = '-foo()';
|
|
||||||
let actual = svgDraw.parseMember(str);
|
|
||||||
|
|
||||||
expect(actual.displayText).toBe('-foo()');
|
|
||||||
expect(actual.cssStyle).toBe('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle protected visibility', function () {
|
|
||||||
const str = '#foo()';
|
|
||||||
let actual = svgDraw.parseMember(str);
|
|
||||||
|
|
||||||
expect(actual.displayText).toBe('#foo()');
|
|
||||||
expect(actual.cssStyle).toBe('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle package/internal visibility', function () {
|
|
||||||
const str = '~foo()';
|
|
||||||
let actual = svgDraw.parseMember(str);
|
|
||||||
|
|
||||||
expect(actual.displayText).toBe('~foo()');
|
|
||||||
expect(actual.cssStyle).toBe('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should ignore unknown character for visibility', function () {
|
|
||||||
const str = '!foo()';
|
|
||||||
let actual = svgDraw.parseMember(str);
|
|
||||||
|
|
||||||
expect(actual.displayText).toBe('foo()');
|
|
||||||
expect(actual.cssStyle).toBe('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle abstract method classifier', function () {
|
|
||||||
const str = 'foo()*';
|
|
||||||
let actual = svgDraw.parseMember(str);
|
|
||||||
|
|
||||||
expect(actual.displayText).toBe('foo()');
|
|
||||||
expect(actual.cssStyle).toBe('font-style:italic;');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle static method classifier', function () {
|
|
||||||
const str = 'foo()$';
|
|
||||||
let actual = svgDraw.parseMember(str);
|
|
||||||
|
|
||||||
expect(actual.displayText).toBe('foo()');
|
|
||||||
expect(actual.cssStyle).toBe('text-decoration:underline;');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should ignore unknown character for classifier', function () {
|
|
||||||
const str = 'foo()!';
|
|
||||||
let actual = svgDraw.parseMember(str);
|
|
||||||
|
|
||||||
expect(actual.displayText).toBe('foo()');
|
|
||||||
expect(actual.cssStyle).toBe('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle simple method declaration with parameters', function () {
|
|
||||||
const str = 'foo(int id)';
|
const str = 'foo(int id)';
|
||||||
let actual = svgDraw.parseMember(str);
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
@@ -82,7 +29,7 @@ describe('class member Renderer, ', function () {
|
|||||||
expect(actual.cssStyle).toBe('');
|
expect(actual.cssStyle).toBe('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle simple method declaration with multiple parameters', function () {
|
it('should handle declaration with multiple parameters', function () {
|
||||||
const str = 'foo(int id, object thing)';
|
const str = 'foo(int id, object thing)';
|
||||||
let actual = svgDraw.parseMember(str);
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
@@ -90,7 +37,7 @@ describe('class member Renderer, ', function () {
|
|||||||
expect(actual.cssStyle).toBe('');
|
expect(actual.cssStyle).toBe('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle simple method declaration with single item in parameters', function () {
|
it('should handle declaration with single item in parameters', function () {
|
||||||
const str = 'foo(id)';
|
const str = 'foo(id)';
|
||||||
let actual = svgDraw.parseMember(str);
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
@@ -98,7 +45,7 @@ describe('class member Renderer, ', function () {
|
|||||||
expect(actual.cssStyle).toBe('');
|
expect(actual.cssStyle).toBe('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle simple method declaration with single item in parameters with extra spaces', function () {
|
it('should handle declaration with single item in parameters with extra spaces', function () {
|
||||||
const str = ' foo ( id) ';
|
const str = ' foo ( id) ';
|
||||||
let actual = svgDraw.parseMember(str);
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
@@ -106,22 +53,6 @@ describe('class member Renderer, ', function () {
|
|||||||
expect(actual.cssStyle).toBe('');
|
expect(actual.cssStyle).toBe('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle method declaration with return value', function () {
|
|
||||||
const str = 'foo(id) int';
|
|
||||||
let actual = svgDraw.parseMember(str);
|
|
||||||
|
|
||||||
expect(actual.displayText).toBe('foo(id) : int');
|
|
||||||
expect(actual.cssStyle).toBe('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle method declaration with generic return value', function () {
|
|
||||||
const str = 'foo(id) List~int~';
|
|
||||||
let actual = svgDraw.parseMember(str);
|
|
||||||
|
|
||||||
expect(actual.displayText).toBe('foo(id) : List<int>');
|
|
||||||
expect(actual.cssStyle).toBe('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle method declaration with generic parameter', function () {
|
it('should handle method declaration with generic parameter', function () {
|
||||||
const str = 'foo(List~int~)';
|
const str = 'foo(List~int~)';
|
||||||
let actual = svgDraw.parseMember(str);
|
let actual = svgDraw.parseMember(str);
|
||||||
@@ -130,6 +61,46 @@ describe('class member Renderer, ', function () {
|
|||||||
expect(actual.cssStyle).toBe('');
|
expect(actual.cssStyle).toBe('');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle method declaration with normal and generic parameter', function () {
|
||||||
|
const str = 'foo(int, List~int~)';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('foo(int, List<int>)');
|
||||||
|
expect(actual.cssStyle).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle declaration with return value', function () {
|
||||||
|
const str = 'foo(id) int';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('foo(id) : int');
|
||||||
|
expect(actual.cssStyle).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle declaration with colon return value', function () {
|
||||||
|
const str = 'foo(id) : int';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('foo(id) : int');
|
||||||
|
expect(actual.cssStyle).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle declaration with generic return value', function () {
|
||||||
|
const str = 'foo(id) List~int~';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('foo(id) : List<int>');
|
||||||
|
expect(actual.cssStyle).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle declaration with colon generic return value', function () {
|
||||||
|
const str = 'foo(id) : List~int~';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('foo(id) : List<int>');
|
||||||
|
expect(actual.cssStyle).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
it('should handle method declaration with all possible markup', function () {
|
it('should handle method declaration with all possible markup', function () {
|
||||||
const str = '+foo ( List~int~ ids )* List~Item~';
|
const str = '+foo ( List~int~ ids )* List~Item~';
|
||||||
let actual = svgDraw.parseMember(str);
|
let actual = svgDraw.parseMember(str);
|
||||||
@@ -138,7 +109,7 @@ describe('class member Renderer, ', function () {
|
|||||||
expect(actual.cssStyle).toBe('font-style:italic;');
|
expect(actual.cssStyle).toBe('font-style:italic;');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle method declaration with nested markup', function () {
|
it('should handle method declaration with nested generics', function () {
|
||||||
const str = '+foo ( List~List~int~~ ids )* List~List~Item~~';
|
const str = '+foo ( List~List~int~~ ids )* List~List~Item~~';
|
||||||
let actual = svgDraw.parseMember(str);
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
@@ -147,8 +118,134 @@ describe('class member Renderer, ', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when parsing text to build field display string', function () {
|
describe('when parsing method visibility', function () {
|
||||||
it('should handle simple field declaration', function () {
|
it('should correctly handle public', function () {
|
||||||
|
const str = '+foo()';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('+foo()');
|
||||||
|
expect(actual.cssStyle).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should correctly handle private', function () {
|
||||||
|
const str = '-foo()';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('-foo()');
|
||||||
|
expect(actual.cssStyle).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should correctly handle protected', function () {
|
||||||
|
const str = '#foo()';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('#foo()');
|
||||||
|
expect(actual.cssStyle).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should correctly handle package/internal', 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);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('foo()');
|
||||||
|
expect(actual.cssStyle).toBe('font-style:italic;');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle abstract method with return type', function () {
|
||||||
|
const str = 'foo(name: String) int*';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('foo(name: String) : int');
|
||||||
|
expect(actual.cssStyle).toBe('font-style:italic;');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle abstract method classifier after parenthesis with return type', function () {
|
||||||
|
const str = 'foo(name: String)* int';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('foo(name: String) : int');
|
||||||
|
expect(actual.cssStyle).toBe('font-style:italic;');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle static method classifier', function () {
|
||||||
|
const str = 'foo()$';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('foo()');
|
||||||
|
expect(actual.cssStyle).toBe('text-decoration:underline;');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle static method classifier with return type', function () {
|
||||||
|
const str = 'foo(name: String) int$';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('foo(name: String) : int');
|
||||||
|
expect(actual.cssStyle).toBe('text-decoration:underline;');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle static method classifier with colon and return type', function () {
|
||||||
|
const str = 'foo(name: String): int$';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('foo(name: String) : int');
|
||||||
|
expect(actual.cssStyle).toBe('text-decoration:underline;');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle static method classifier after parenthesis with return type', function () {
|
||||||
|
const str = 'foo(name: String)$ int';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('foo(name: String) : int');
|
||||||
|
expect(actual.cssStyle).toBe('text-decoration:underline;');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should ignore unknown character for classifier', function () {
|
||||||
|
const str = 'foo()!';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('foo()');
|
||||||
|
expect(actual.cssStyle).toBe('');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('given a string representing class member, ', function () {
|
||||||
|
describe('when parsing member declaration', function () {
|
||||||
|
it('should handle simple field', function () {
|
||||||
|
const str = 'id';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('id');
|
||||||
|
expect(actual.cssStyle).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle field with type', function () {
|
||||||
|
const str = 'int id';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('int id');
|
||||||
|
expect(actual.cssStyle).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle field with type (name first)', function () {
|
||||||
|
const str = 'id: int';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('id: int');
|
||||||
|
expect(actual.cssStyle).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle array field', function () {
|
||||||
const str = 'int[] ids';
|
const str = 'int[] ids';
|
||||||
let actual = svgDraw.parseMember(str);
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
@@ -156,7 +253,15 @@ describe('class member Renderer, ', function () {
|
|||||||
expect(actual.cssStyle).toBe('');
|
expect(actual.cssStyle).toBe('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle field declaration with generic type', function () {
|
it('should handle array field (name first)', function () {
|
||||||
|
const str = 'ids: int[]';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('ids: int[]');
|
||||||
|
expect(actual.cssStyle).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle field with generic type', function () {
|
||||||
const str = 'List~int~ ids';
|
const str = 'List~int~ ids';
|
||||||
let actual = svgDraw.parseMember(str);
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
@@ -164,12 +269,62 @@ describe('class member Renderer, ', function () {
|
|||||||
expect(actual.cssStyle).toBe('');
|
expect(actual.cssStyle).toBe('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle static field classifier', function () {
|
it('should handle field with generic type (name first)', function () {
|
||||||
|
const str = 'ids: List~int~';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
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$';
|
const str = 'String foo$';
|
||||||
let actual = svgDraw.parseMember(str);
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
expect(actual.displayText).toBe('String foo');
|
expect(actual.displayText).toBe('String foo');
|
||||||
expect(actual.cssStyle).toBe('text-decoration:underline;');
|
expect(actual.cssStyle).toBe('text-decoration:underline;');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle static field (name first)', function () {
|
||||||
|
const str = 'foo: String$';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('foo: String');
|
||||||
|
expect(actual.cssStyle).toBe('text-decoration:underline;');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle static field with generic type', function () {
|
||||||
|
const str = 'List~String~ foo$';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('List<String> foo');
|
||||||
|
expect(actual.cssStyle).toBe('text-decoration:underline;');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle static field with generic type (name first)', function () {
|
||||||
|
const str = 'foo: List~String~$';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('foo: List<String>');
|
||||||
|
expect(actual.cssStyle).toBe('text-decoration:underline;');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle field with nested generic type', function () {
|
||||||
|
const str = 'List~List~int~~ idLists';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('List<List<int>> idLists');
|
||||||
|
expect(actual.cssStyle).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle field with nested generic type (name first)', function () {
|
||||||
|
const str = 'idLists: List~List~int~~';
|
||||||
|
let actual = svgDraw.parseMember(str);
|
||||||
|
|
||||||
|
expect(actual.displayText).toBe('idLists: List<List<int>>');
|
||||||
|
expect(actual.cssStyle).toBe('');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
import DOMPurify from 'dompurify';
|
import DOMPurify from 'dompurify';
|
||||||
import { MermaidConfig } from '../../config.type.js';
|
import { MermaidConfig } from '../../config.type.js';
|
||||||
|
|
||||||
|
export const lineBreakRegex = /<br\s*\/?>/gi;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the rows of lines in a string
|
* Gets the rows of lines in a string
|
||||||
*
|
*
|
||||||
@@ -65,8 +67,6 @@ export const sanitizeTextOrArray = (
|
|||||||
return a.flat().map((x: string) => sanitizeText(x, config));
|
return a.flat().map((x: string) => sanitizeText(x, config));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const lineBreakRegex = /<br\s*\/?>/gi;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not a text has any line breaks
|
* Whether or not a text has any line breaks
|
||||||
*
|
*
|
||||||
|
@@ -74,7 +74,7 @@ classDiagram
|
|||||||
Vehicle <|-- Car
|
Vehicle <|-- Car
|
||||||
```
|
```
|
||||||
|
|
||||||
Naming convention: a class name should be composed only of alphanumeric characters (including unicode), and underscores.
|
Naming convention: a class name should be composed only of alphanumeric characters (including unicode), underscores, and dashes (-).
|
||||||
|
|
||||||
### Class labels
|
### Class labels
|
||||||
|
|
||||||
@@ -171,12 +171,12 @@ To describe the visibility (or encapsulation) of an attribute or method/function
|
|||||||
- `#` Protected
|
- `#` Protected
|
||||||
- `~` Package/Internal
|
- `~` Package/Internal
|
||||||
|
|
||||||
> _note_ you can also include additional _classifiers_ to a method definition by adding the following notation to the _end_ of the method, i.e.: after the `()`:
|
> _note_ you can also include additional _classifiers_ to a method definition by adding the following notation to the _end_ of the method, i.e.: after the `()` or after the return type:
|
||||||
>
|
>
|
||||||
> - `*` Abstract e.g.: `someAbstractMethod()*`
|
> - `*` Abstract e.g.: `someAbstractMethod()*` or `someAbstractMethod() int*`
|
||||||
> - `$` Static e.g.: `someStaticMethod()$`
|
> - `$` Static e.g.: `someStaticMethod()$` or `someStaticMethod() String$`
|
||||||
|
|
||||||
> _note_ you can also include additional _classifiers_ to a field definition by adding the following notation to the end of its name:
|
> _note_ you can also include additional _classifiers_ to a field definition by adding the following notation to the very end:
|
||||||
>
|
>
|
||||||
> - `$` Static e.g.: `String someField$`
|
> - `$` Static e.g.: `String someField$`
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user