mirror of
				https://github.com/mermaid-js/mermaid.git
				synced 2025-10-29 18:04:09 +01:00 
			
		
		
		
	Multiple Fixes to classes
This commit is contained in:
		| @@ -128,7 +128,7 @@ classDiagram | ||||
|     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 | ||||
|  | ||||
| @@ -283,12 +283,12 @@ To describe the visibility (or encapsulation) of an attribute or method/function | ||||
| - `#` Protected | ||||
| - `~` 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()*` | ||||
| > - `$` Static e.g.: `someStaticMethod()$` | ||||
| > - `*` Abstract e.g.: `someAbstractMethod()*` or `someAbstractMethod() int*` | ||||
| > - `$` 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$` | ||||
|  | ||||
|   | ||||
| @@ -106,6 +106,7 @@ export const clear = function () { | ||||
| export const getClass = function (id: string) { | ||||
|   return classes[id]; | ||||
| }; | ||||
|  | ||||
| export const getClasses = function () { | ||||
|   return classes; | ||||
| }; | ||||
| @@ -170,9 +171,10 @@ export const addMember = function (className: string, member: string) { | ||||
|     const memberString = member.trim(); | ||||
|  | ||||
|     if (memberString.startsWith('<<') && memberString.endsWith('>>')) { | ||||
|       // Remove leading and trailing brackets | ||||
|       // its an annotation | ||||
|       theClass.annotations.push(sanitizeText(memberString.substring(2, memberString.length - 2))); | ||||
|     } else if (memberString.indexOf(')') > 0) { | ||||
|       //its a method | ||||
|       theClass.methods.push(sanitizeText(memberString)); | ||||
|     } else if (memberString) { | ||||
|       theClass.members.push(sanitizeText(memberString)); | ||||
| @@ -234,6 +236,7 @@ const setTooltip = function (ids: string, tooltip?: string) { | ||||
|     } | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| export const getTooltip = function (id: string) { | ||||
|   return classes[id].tooltip; | ||||
| }; | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -259,8 +259,8 @@ className | ||||
|     : alphaNumToken { $$=$1; } | ||||
|     | classLiteralName { $$=$1; } | ||||
|     | alphaNumToken className { $$=$1+$2; } | ||||
|     | alphaNumToken GENERICTYPE { $$=$1+'~'+$2; } | ||||
|     | classLiteralName GENERICTYPE { $$=$1+'~'+$2; } | ||||
|     | alphaNumToken GENERICTYPE { $$=$1+'~'+$2+'~'; } | ||||
|     | classLiteralName GENERICTYPE { $$=$1+'~'+$2+'~'; } | ||||
|     ; | ||||
|  | ||||
| statement | ||||
| @@ -366,7 +366,7 @@ textToken      : textNoTagsToken | TAGSTART | TAGEND | '=='  | '--' | PCT | DEFA | ||||
|  | ||||
| textNoTagsToken: alphaNumToken | SPACE | MINUS | keywords ; | ||||
|  | ||||
| alphaNumToken  : UNICODE_TEXT | NUM | ALPHA; | ||||
| alphaNumToken  : UNICODE_TEXT | NUM | ALPHA | MINUS; | ||||
|  | ||||
| classLiteralName : BQUOTE_STR; | ||||
|  | ||||
|   | ||||
| @@ -199,11 +199,7 @@ export const drawClass = function (elem, classDef, conf, diagObj) { | ||||
|     isFirst = false; | ||||
|   }); | ||||
|  | ||||
|   let classTitleString = classDef.id; | ||||
|  | ||||
|   if (classDef.type !== undefined && classDef.type !== '') { | ||||
|     classTitleString += '<' + classDef.type + '>'; | ||||
|   } | ||||
|   let classTitleString = getClassTitleString(classDef); | ||||
|  | ||||
|   const classTitle = title.append('tspan').text(classTitleString).attr('class', 'title'); | ||||
|  | ||||
| @@ -291,6 +287,16 @@ export const drawClass = function (elem, classDef, conf, diagObj) { | ||||
|   return classInfo; | ||||
| }; | ||||
|  | ||||
| export const getClassTitleString = function (classDef) { | ||||
|   let classTitleString = classDef.id; | ||||
|  | ||||
|   if (classDef.type) { | ||||
|     classTitleString += '<' + classDef.type + '>'; | ||||
|   } | ||||
|  | ||||
|   return classTitleString; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Renders a note diagram | ||||
|  * | ||||
| @@ -355,6 +361,9 @@ export const drawNote = function (elem, note, conf, diagObj) { | ||||
| }; | ||||
|  | ||||
| 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 methodRegEx = /^([#+|~-])?(\w+) *\( *(.*)\) *([$*])? *(\w*[[\]|~]*\s*\w*~?)$/; | ||||
|  | ||||
| @@ -421,33 +430,48 @@ const buildLegacyDisplay = function (text) { | ||||
|   let displayText = ''; | ||||
|   let cssStyle = ''; | ||||
|   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 methodEnd = text.indexOf(')'); | ||||
|  | ||||
|   if (methodStart > 1 && methodEnd > methodStart && methodEnd <= text.length) { | ||||
|     let visibility = ''; | ||||
|     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(); | ||||
|     } | ||||
|     let methodName = text.substring(0, methodStart).trim(); | ||||
|  | ||||
|     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()) + ')'; | ||||
|  | ||||
|     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.charAt(0) === ':') { | ||||
|           returnType = returnType.substring(1).trim(); | ||||
|         } | ||||
|         returnType = ' : ' + parseGenericTypes(returnType); | ||||
|         displayText += returnType; | ||||
|       } | ||||
| @@ -502,6 +526,7 @@ const parseClassifier = function (classifier) { | ||||
| }; | ||||
|  | ||||
| export default { | ||||
|   getClassTitleString, | ||||
|   drawClass, | ||||
|   drawEdge, | ||||
|   drawNote, | ||||
|   | ||||
| @@ -1,8 +1,19 @@ | ||||
| import svgDraw from './svgDraw.js'; | ||||
|  | ||||
| describe('class member Renderer, ', function () { | ||||
|   describe('when parsing text to build method display string', function () { | ||||
|     it('should handle simple method declaration', function () { | ||||
| describe('given a string representing class method, ', function () { | ||||
|   it('should handle class names with generics', 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()'; | ||||
|       let actual = svgDraw.parseMember(str); | ||||
|  | ||||
| @@ -10,71 +21,7 @@ describe('class member Renderer, ', function () { | ||||
|       expect(actual.cssStyle).toBe(''); | ||||
|     }); | ||||
|  | ||||
|     it('should handle public visibility', 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 () { | ||||
|     it('should handle declaration with parameters', function () { | ||||
|       const str = 'foo(int id)'; | ||||
|       let actual = svgDraw.parseMember(str); | ||||
|  | ||||
| @@ -82,7 +29,7 @@ describe('class member Renderer, ', function () { | ||||
|       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)'; | ||||
|       let actual = svgDraw.parseMember(str); | ||||
|  | ||||
| @@ -90,7 +37,7 @@ describe('class member Renderer, ', function () { | ||||
|       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)'; | ||||
|       let actual = svgDraw.parseMember(str); | ||||
|  | ||||
| @@ -98,7 +45,7 @@ describe('class member Renderer, ', function () { | ||||
|       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) '; | ||||
|       let actual = svgDraw.parseMember(str); | ||||
|  | ||||
| @@ -106,22 +53,6 @@ describe('class member Renderer, ', function () { | ||||
|       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 () { | ||||
|       const str = 'foo(List~int~)'; | ||||
|       let actual = svgDraw.parseMember(str); | ||||
| @@ -130,6 +61,46 @@ describe('class member Renderer, ', function () { | ||||
|       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 () { | ||||
|       const str = '+foo (  List~int~ ids  )* List~Item~'; | ||||
|       let actual = svgDraw.parseMember(str); | ||||
| @@ -138,7 +109,7 @@ describe('class member Renderer, ', function () { | ||||
|       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~~'; | ||||
|       let actual = svgDraw.parseMember(str); | ||||
|  | ||||
| @@ -147,8 +118,134 @@ describe('class member Renderer, ', function () { | ||||
|     }); | ||||
|   }); | ||||
|  | ||||
|   describe('when parsing text to build field display string', function () { | ||||
|     it('should handle simple field declaration', function () { | ||||
|   describe('when parsing method visibility', 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'; | ||||
|       let actual = svgDraw.parseMember(str); | ||||
|  | ||||
| @@ -156,7 +253,15 @@ describe('class member Renderer, ', function () { | ||||
|       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'; | ||||
|       let actual = svgDraw.parseMember(str); | ||||
|  | ||||
| @@ -164,12 +269,62 @@ describe('class member Renderer, ', function () { | ||||
|       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$'; | ||||
|       let actual = svgDraw.parseMember(str); | ||||
|  | ||||
|       expect(actual.displayText).toBe('String foo'); | ||||
|       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 { MermaidConfig } from '../../config.type.js'; | ||||
|  | ||||
| export const lineBreakRegex = /<br\s*\/?>/gi; | ||||
|  | ||||
| /** | ||||
|  * Gets the rows of lines in a string | ||||
|  * | ||||
| @@ -65,8 +67,6 @@ export const sanitizeTextOrArray = ( | ||||
|   return a.flat().map((x: string) => sanitizeText(x, config)); | ||||
| }; | ||||
|  | ||||
| export const lineBreakRegex = /<br\s*\/?>/gi; | ||||
|  | ||||
| /** | ||||
|  * Whether or not a text has any line breaks | ||||
|  * | ||||
|   | ||||
| @@ -74,7 +74,7 @@ classDiagram | ||||
|     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 | ||||
|  | ||||
| @@ -171,12 +171,12 @@ To describe the visibility (or encapsulation) of an attribute or method/function | ||||
| - `#` Protected | ||||
| - `~` 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()*` | ||||
| > - `$` Static e.g.: `someStaticMethod()$` | ||||
| > - `*` Abstract e.g.: `someAbstractMethod()*` or `someAbstractMethod() int*` | ||||
| > - `$` 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$` | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Justin Greywolf
					Justin Greywolf