1181-Css for class diagrams

Initial change for supporting custom CSS for use with classDiagrams.
updated `LABEL` regex for specificity
This commit is contained in:
Justin Greywolf
2020-08-03 12:41:10 -07:00
parent 652b6ae7d2
commit 1f051d7a9f
8 changed files with 324 additions and 371 deletions

View File

@@ -26,6 +26,7 @@ const splitClassNameAndType = function(id) {
if (id.indexOf('~') > 0) {
let split = id.split('~');
className = split[0];
genericType = split[1];
}
@@ -51,6 +52,7 @@ export const addClass = function(id) {
annotations: [],
domId: MERMAID_DOM_ID_PREFIX + classId.className + '-' + classCounter
};
classCounter++;
};

View File

@@ -0,0 +1,60 @@
/* eslint-env jasmine */
import { parser } from './parser/classDiagram';
import classDb from './classDb';
describe('class diagram, ', function() {
describe('when parsing data from a classDiagram it', function() {
beforeEach(function() {
parser.yy = classDb;
parser.yy.clear();
});
it('should be possible to apply a css class to a class directly', function() {
const str = 'classDiagram\n' + 'class Class01:::exClass';
parser.parse(str);
expect(parser.yy.getClass('Class01').cssClasses[0]).toBe('exClass');
});
it('should be possible to apply a css class to a class directly with struct', function () {
const str =
'classDiagram\n' +
'class Class1:::exClass {\n' +
'int : test\n' +
'string : foo\n' +
'test()\n' +
'foo()\n' +
'}';
parser.parse(str);
const testClass = parser.yy.getClass('Class1');
expect(testClass.cssClasses[0]).toBe('exClass');
});
it('should be possible to apply a css class to a class with relations', function() {
const str = 'classDiagram\n' + 'Class01 <|-- Class02\ncssClass "Class01" exClass';
parser.parse(str);
expect(parser.yy.getClass('Class01').cssClasses[0]).toBe('exClass');
});
it('should be possible to apply a cssClass to a class', function() {
const str = 'classDiagram\n' + 'class Class01\n cssClass "Class01" exClass';
parser.parse(str);
expect(parser.yy.getClass('Class01').cssClasses[0]).toBe('exClass');
});
it('should be possible to apply a cssClass to a comma separated list of classes', function() {
const str = 'classDiagram\n' + 'class Class01\n class Class02\n cssClass "Class01,Class02" exClass';
parser.parse(str);
expect(parser.yy.getClass('Class01').cssClasses[0]).toBe('exClass');
expect(parser.yy.getClass('Class02').cssClasses[0]).toBe('exClass');
});
});
});

View File

@@ -27,10 +27,8 @@
<struct>[\n] /* nothing */
<struct>[^{}\n]* { /*console.log('lex-member: ' + yytext);*/ return "MEMBER";}
"class" return 'CLASS';
//"click" return 'CLICK';
"cssClass" return 'CSSCLASS';
"callback" return 'CALLBACK';
"link" return 'LINK';
"<<" return 'ANNOTATION_START';
@@ -51,7 +49,8 @@
\s*o return 'AGGREGATION';
\-\- return 'LINE';
\.\. return 'DOTTED_LINE';
":"[^\n;]+ return 'LABEL';
":"{1}[^:\n;]+ return 'LABEL';
":::" return 'STYLE_SEPARATOR';
\- return 'MINUS';
"." return 'DOT';
\+ return 'PLUS';
@@ -177,8 +176,8 @@ statements
;
className
: alphaNumToken className { $$=$1+$2; }
| alphaNumToken { $$=$1; }
: alphaNumToken { $$=$1; }
| alphaNumToken className { $$=$1+$2; }
| alphaNumToken GENERICTYPE className { $$=$1+'~'+$2+$3; }
| alphaNumToken GENERICTYPE { $$=$1+'~'+$2; }
;
@@ -190,12 +189,15 @@ statement
| methodStatement
| annotationStatement
| clickStatement
| cssClassStatement
| directive
;
classStatement
: CLASS className {yy.addClass($2);}
| CLASS className STYLE_SEPARATOR alphaNumToken {yy.addClass($2);yy.setCssClass($2, $4);}
| CLASS className STRUCT_START members STRUCT_STOP {/*console.log($2,JSON.stringify($4));*/yy.addClass($2);yy.addMembers($2,$4);}
| CLASS className STYLE_SEPARATOR alphaNumToken STRUCT_START members STRUCT_STOP {yy.addClass($2);yy.setCssClass($2, $4);yy.addMembers($2,$6);}
;
annotationStatement
@@ -241,10 +243,14 @@ lineType
;
clickStatement
: CALLBACK className STR {$$ = $1;yy.setClickEvent($2, $3, undefined);}
| CALLBACK className STR STR {$$ = $1;yy.setClickEvent($2, $3, $4);}
| LINK className STR {$$ = $1;yy.setLink($2, $3, undefined);}
| LINK className STR STR {$$ = $1;yy.setLink($2, $3, $4);}
: CALLBACK className STR {$$ = $1;yy.setClickEvent($2, $3, undefined);}
| CALLBACK className STR STR {$$ = $1;yy.setClickEvent($2, $3, $4);}
| LINK className STR {$$ = $1;yy.setLink($2, $3, undefined);}
| LINK className STR STR {$$ = $1;yy.setLink($2, $3, $4);}
;
cssClassStatement
: CSSCLASS STR alphaNumToken {yy.setCssClass($2, $3);}
;
commentToken : textToken | graphCodeTokens ;
@@ -254,4 +260,5 @@ textToken : textNoTagsToken | TAGSTART | TAGEND | '==' | '--' | PCT | DEFA
textNoTagsToken: alphaNumToken | SPACE | MINUS | keywords ;
alphaNumToken : UNICODE_TEXT | NUM | ALPHA;
%%

View File

@@ -147,11 +147,6 @@ export const drawEdge = function(elem, path, relation, conf) {
export const drawClass = function(elem, classDef, conf) {
logger.info('Rendering class ' + classDef);
let cssClassStr = 'classGroup ';
if (classDef.cssClasses.length > 0) {
cssClassStr = cssClassStr + classDef.cssClasses.join(' ');
}
const id = classDef.id;
const classInfo = {
id: id,
@@ -164,7 +159,7 @@ export const drawClass = function(elem, classDef, conf) {
const g = elem
.append('g')
.attr('id', lookUpDomId(id))
.attr('class', cssClassStr);
.attr('class', 'classGroup');
// add title
let title;
@@ -249,12 +244,19 @@ export const drawClass = function(elem, classDef, conf) {
});
const classBox = g.node().getBBox();
var cssClassStr = ' ';
if (classDef.cssClasses.length > 0) {
cssClassStr = cssClassStr + classDef.cssClasses.join(' ');
}
const rect = g
.insert('rect', ':first-child')
.attr('x', 0)
.attr('y', 0)
.attr('width', classBox.width + 2 * conf.padding)
.attr('height', classBox.height + conf.padding + 0.5 * conf.dividerMargin);
.attr('height', classBox.height + conf.padding + 0.5 * conf.dividerMargin)
.attr('class', cssClassStr);
const rectWidth = rect.node().getBBox().width;