diff --git a/packages/mermaid/src/diagrams/class/classDb.ts b/packages/mermaid/src/diagrams/class/classDb.ts index 48ef7ccbe..851353477 100644 --- a/packages/mermaid/src/diagrams/class/classDb.ts +++ b/packages/mermaid/src/diagrams/class/classDb.ts @@ -392,6 +392,29 @@ const setDirection = (dir: string) => { direction = dir; }; +/** + * Function called by parser when a namespace keyword has been found. + * + * @param id - Id of the namespace to add + * @public + */ +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export const addNamespace = function (id: string) { + // TODO: Implement here +}; + +/** + * Function called by parser when a namespace definition has been found. + * + * @param id - Id of the namespace to add + * @param classNames - Ids of the class to add + * @public + */ +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export const addClassesToNamespace = function (id: string, classNames: string[]) { + // TODO: Implement here +}; + export default { parseDirective, setAccTitle, @@ -425,4 +448,6 @@ export default { setDiagramTitle, getDiagramTitle, setClassLabel, + addNamespace, + addClassesToNamespace, }; diff --git a/packages/mermaid/src/diagrams/class/classDiagram.spec.ts b/packages/mermaid/src/diagrams/class/classDiagram.spec.ts index 24fbc41ea..11b556179 100644 --- a/packages/mermaid/src/diagrams/class/classDiagram.spec.ts +++ b/packages/mermaid/src/diagrams/class/classDiagram.spec.ts @@ -571,6 +571,37 @@ foo() const str = 'classDiagram\n' + 'note "test"\n'; parser.parse(str); }); + + it('should handle "namespace"', function () { + const str = `classDiagram +namespace Namespace1 { class Class1 } +namespace Namespace2 { class Class1 +} +namespace Namespace3 { +class Class1 { +int : test +string : foo +test() +foo() +} +} +namespace Namespace4 { +class Class1 { +int : test +string : foo +test() +foo() +} +class Class2 { +int : test +string : foo +test() +foo() +} +} +`; + parser.parse(str); + }); }); describe('when fetching data from a classDiagram it', function () { diff --git a/packages/mermaid/src/diagrams/class/parser/classDiagram.jison b/packages/mermaid/src/diagrams/class/parser/classDiagram.jison index 4e68372f3..1c0ccdbbe 100644 --- a/packages/mermaid/src/diagrams/class/parser/classDiagram.jison +++ b/packages/mermaid/src/diagrams/class/parser/classDiagram.jison @@ -21,6 +21,8 @@ %x acc_descr_multiline %x class %x class-body +%x namespace +%x namespace-body %% \%\%\{ { this.begin('open_directive'); return 'open_directive'; } .*direction\s+TB[^\n]* return 'direction_tb'; @@ -48,9 +50,20 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili "classDiagram" return 'CLASS_DIAGRAM'; "[*]" return 'EDGE_STATE'; -"class" { this.begin('class'); return 'CLASS';} +"namespace" { this.begin('namespace'); return 'NAMESPACE'; } +\s*(\r?\n)+ { this.popState(); return 'NEWLINE'; } +\s+ /* skip whitespace */ +[{] { this.begin("namespace-body"); return 'STRUCT_START';} +[}] { this.popState(); return 'STRUCT_STOP'; } +<> return "EOF_IN_STRUCT"; +\s*(\r?\n)+ return 'NEWLINE'; +\s+ /* skip whitespace */ +"[*]" return 'EDGE_STATE'; + +"class" { this.begin('class'); return 'CLASS';} \s*(\r?\n)+ { this.popState(); return 'NEWLINE'; } \s+ /* skip whitespace */ +[}] { this.popState(); this.popState(); return 'STRUCT_STOP';} [{] { this.begin("class-body"); return 'STRUCT_START';} [}] { this.popState(); return 'STRUCT_STOP'; } <> return "EOF_IN_STRUCT"; @@ -264,6 +277,11 @@ classLabel : SQS STR SQE { $$=$2; } ; +namespaceName + : alphaNumToken { $$=$1; } + | alphaNumToken namespaceName { $$=$1+$2; } + ; + className : alphaNumToken { $$=$1; } | classLiteralName { $$=$1; } @@ -275,6 +293,7 @@ className statement : relationStatement { yy.addRelation($1); } | relationStatement LABEL { $1.title = yy.cleanupLabel($2); yy.addRelation($1); } + | namespaceStatement | classStatement | methodStatement | annotationStatement @@ -288,6 +307,21 @@ statement | acc_descr_multiline_value { $$=$1.trim();yy.setAccDescription($$); } ; +namespaceStatement + : namespaceIdentifier STRUCT_START classStatements STRUCT_STOP {yy.addClassesToNamespace($1, $3);} + | namespaceIdentifier STRUCT_START NEWLINE classStatements STRUCT_STOP {yy.addClassesToNamespace($1, $4);} + ; + +namespaceIdentifier + : NAMESPACE namespaceName {$$=$2; yy.addNamespace($2);} + ; + +classStatements + : classStatement {$$=[$1]} + | classStatement NEWLINE {$$=[$1]} + | classStatement NEWLINE classStatements {$3.unshift($1); $$=$3} + ; + classStatement : classIdentifier | classIdentifier STYLE_SEPARATOR alphaNumToken {yy.setCssClass($1, $3);}