mirror of
				https://github.com/mermaid-js/mermaid.git
				synced 2025-11-03 20:34:20 +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 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 {
 | 
			
		||||
  let lastChar = text.substring(text.length - 1, text.length);
 | 
			
		||||
 | 
			
		||||
  if (firstChar.match(/[#+~-]/)) {
 | 
			
		||||
    visibility = firstChar;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
      methodName = text.substring(1, methodStart).trim();
 | 
			
		||||
  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 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) {
 | 
			
		||||
      // 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