align click on href or function syntax with other diagrams

This commit is contained in:
Matthieu MOREL
2020-12-06 22:23:13 +01:00
parent d8e57d1c01
commit 0b8561711b
6 changed files with 107 additions and 41 deletions

View File

@@ -69,7 +69,7 @@
int id int id
test() test()
} }
callback Class01 "callback" "A Tooltip" click Class01 call callback() "A Tooltip"
</div> </div>
<div class="mermaid2" style="width: 100%; height: 20%;"> <div class="mermaid2" style="width: 100%; height: 20%;">

View File

@@ -41,16 +41,16 @@
<div id="FirstLine" class="mermaid"> <div id="FirstLine" class="mermaid">
classDiagram classDiagram
class ShapeLink class ShapeLink
link ShapeLink "http://localhost:9000/webpackUsage.html" "This is a tooltip for a link" click ShapeLink href "http://localhost:9000/webpackUsage.html" "This is a tooltip for a link"
class ShapeCallback class ShapeCallback
callback ShapeCallback "clickByClass" "This is a tooltip for a callback" click ShapeCallback call clickByClass() "This is a tooltip for a callback"
</div> </div>
<div id="FirstLine" class="mermaid"> <div id="FirstLine" class="mermaid">
classDiagram-v2 classDiagram-v2
class ShapeLink2 class ShapeLink2
link ShapeLink2 "http://localhost:9000/webpackUsage.html" "This is a tooltip for a link" click ShapeLink2 href "http://localhost:9000/webpackUsage.html" "This is a tooltip for a link"
class ShapeCallback2 class ShapeCallback2
callback ShapeCallback2 "clickByClass" "This is a tooltip for a callback" click ShapeCallback2 call clickByClass() "This is a tooltip for a callback"
</div> </div>
</div> </div>

View File

@@ -30,19 +30,19 @@
classDiagram classDiagram
class Test class Test
class ShapeLink class ShapeLink
link ShapeLink "http://localhost:9000/webpackUsage.html" "This is a tooltip for a link" click ShapeLink href "http://localhost:9000/webpackUsage.html" "This is a tooltip for a link"
class ShapeCallback class ShapeCallback
callback ShapeCallback "clickByClass" "This is a tooltip for a callback" click ShapeCallback call clickByClass() "This is a tooltip for a callback"
</div> </div>
<div id="FirstLine" class="mermaid"> <div id="FirstLine" class="mermaid">
classDiagram-v2 classDiagram-v2
class ShapeCallback class ShapeCallback
callback ShapeCallback "clickByClass" "This is a tooltip for a callback" click ShapeCallback call clickByClass() "This is a tooltip for a callback"
</div> </div>
<div id="FirstLine" class="mermaid"> <div id="FirstLine" class="mermaid">
classDiagram-v2 classDiagram-v2
class ShapeLink class ShapeLink
link ShapeLink "http://localhost:9000/webpackUsage.html" "This is a tooltip for a link" click ShapeLink href "http://localhost:9000/webpackUsage.html" "This is a tooltip for a link"
</div> </div>
</div> </div>

View File

@@ -167,23 +167,29 @@ export const setCssClass = function(ids, className) {
}); });
}; };
const setTooltip = function(ids, tooltip) {
const config = configApi.getConfig();
ids.split(',').forEach(function(id) {
if (typeof tooltip !== 'undefined') {
classes[id].tooltip = common.sanitizeText(tooltip, config);
}
});
};
/** /**
* Called by parser when a link is found. Adds the URL to the vertex data. * Called by parser when a link is found. Adds the URL to the vertex data.
* @param ids Comma separated list of ids * @param ids Comma separated list of ids
* @param linkStr URL to create a link for * @param linkStr URL to create a link for
* @param tooltip Tooltip for the clickable element * @param tooltip Tooltip for the clickable element
*/ */
export const setLink = function(ids, linkStr, tooltip) { export const setLink = function(ids, linkStr) {
const config = configApi.getConfig(); const config = configApi.getConfig();
ids.split(',').forEach(function(_id) { ids.split(',').forEach(function(_id) {
let id = _id; let id = _id;
if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id; if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
if (typeof classes[id] !== 'undefined') { if (typeof classes[id] !== 'undefined') {
classes[id].link = utils.formatUrl(linkStr, config); classes[id].link = utils.formatUrl(linkStr, config);
if (tooltip) {
classes[id].tooltip = common.sanitizeText(tooltip, config);
}
} }
}); });
setCssClass(ids, 'clickable'); setCssClass(ids, 'clickable');
@@ -193,9 +199,9 @@ export const setLink = function(ids, linkStr, tooltip) {
* Called by parser when a click definition is found. Registers an event handler. * Called by parser when a click definition is found. Registers an event handler.
* @param ids Comma separated list of ids * @param ids Comma separated list of ids
* @param functionName Function to be called on click * @param functionName Function to be called on click
* @param tooltip Tooltip for the clickable element * @param functionArgs Function args the function should be called with
*/ */
export const setClickEvent = function(ids, functionName, tooltip) { export const setClickEvent = function(ids, functionName, functionArgs) {
ids.split(',').forEach(function(id) { ids.split(',').forEach(function(id) {
setClickFunc(id, functionName, tooltip); setClickFunc(id, functionName, tooltip);
classes[id].haveCallback = true; classes[id].haveCallback = true;
@@ -215,8 +221,24 @@ const setClickFunc = function(domId, functionName, tooltip) {
return; return;
} }
if (typeof classes[id] !== 'undefined') { if (typeof classes[id] !== 'undefined') {
if (tooltip) { let argList = [];
classes[id].tooltip = common.sanitizeText(tooltip, config); if (typeof functionArgs === 'string') {
/* Splits functionArgs by ',', ignoring all ',' in double quoted strings */
argList = functionArgs.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);
for (let i = 0; i < argList.length; i++) {
let item = argList[i].trim();
/* Removes all double quotes at the start and end of an argument */
/* This preserves all starting and ending whitespace inside */
if (item.charAt(0) === '"' && item.charAt(item.length - 1) === '"') {
item = item.substr(1, item.length - 2);
}
argList[i] = item;
}
}
/* if no arguments passed into callback, default to passing in id */
if (argList.length === 0) {
argList.push(elemId);
} }
funs.push(function() { funs.push(function() {
@@ -225,7 +247,7 @@ const setClickFunc = function(domId, functionName, tooltip) {
elem.addEventListener( elem.addEventListener(
'click', 'click',
function() { function() {
utils.runFunc(functionName, elemId); utils.runFunc(functionName, ...argList);
}, },
false false
); );
@@ -314,5 +336,6 @@ export default {
setClickEvent, setClickEvent,
setCssClass, setCssClass,
setLink, setLink,
setTooltip,
lookUpDomId lookUpDomId
}; };

View File

@@ -338,7 +338,7 @@ foo()
'test()\n' + 'test()\n' +
'foo()\n' + 'foo()\n' +
'}\n' + '}\n' +
'link Class01 "google.com" '; 'click Class01 href "google.com" ';
parser.parse(str); parser.parse(str);
}); });
@@ -353,7 +353,7 @@ foo()
'test()\n' + 'test()\n' +
'foo()\n' + 'foo()\n' +
'}\n' + '}\n' +
'link Class01 "google.com" "A Tooltip" '; 'click Class01 href "google.com" "A Tooltip" ';
parser.parse(str); parser.parse(str);
}); });
@@ -368,7 +368,7 @@ foo()
'test()\n' + 'test()\n' +
'foo()\n' + 'foo()\n' +
'}\n' + '}\n' +
'callback Class01 "functionCall" '; 'click Class01 call functionCall() ';
parser.parse(str); parser.parse(str);
}); });
@@ -383,7 +383,7 @@ foo()
'test()\n' + 'test()\n' +
'foo()\n' + 'foo()\n' +
'}\n' + '}\n' +
'callback Class01 "functionCall" "A Tooltip" '; 'click Class01 call functionCall() "A Tooltip" ';
parser.parse(str); parser.parse(str);
}); });
@@ -637,7 +637,7 @@ foo()
}); });
it('should associate link and css appropriately', function () { it('should associate link and css appropriately', function () {
const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()\n' + 'link Class1 "google.com"'; const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()\n' + 'click Class1 href "google.com"';
parser.parse(str); parser.parse(str);
const testClass = parser.yy.getClass('Class1'); const testClass = parser.yy.getClass('Class1');
@@ -647,7 +647,7 @@ foo()
}); });
it('should associate link with tooltip', function () { it('should associate link with tooltip', function () {
const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()\n' + 'link Class1 "google.com" "A tooltip"'; const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()\n' + 'click Class1 href "google.com" "A tooltip"';
parser.parse(str); parser.parse(str);
const testClass = parser.yy.getClass('Class1'); const testClass = parser.yy.getClass('Class1');
@@ -659,18 +659,28 @@ foo()
it('should associate callback appropriately', function () { it('should associate callback appropriately', function () {
spyOn(classDb, 'setClickEvent'); spyOn(classDb, 'setClickEvent');
const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()\n' + 'callback Class1 "functionCall"'; const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()\n' + 'click Class1 call functionCall()';
parser.parse(str); parser.parse(str);
expect(classDb.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall', undefined); expect(classDb.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall');
});
it('should associate callback appropriately with an arbitrary number of args', function () {
spyOn(classDb, 'setClickEvent');
const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()\n' + 'click Class1 call functionCall("test0", test1, test2)';
parser.parse(str);
expect(classDb.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall','"test0", test1, test2');
}); });
it('should associate callback with tooltip', function () { it('should associate callback with tooltip', function () {
spyOn(classDb, 'setClickEvent'); spyOn(classDb, 'setClickEvent');
const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()\n' + 'callback Class1 "functionCall" "A tooltip"'; spyOn(classDb, 'setTooltip');
const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()\n' + 'click Class1 functionCall() "A tooltip"';
parser.parse(str); parser.parse(str);
expect(classDb.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall', 'A tooltip'); expect(classDb.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall');
expect(classDb.setTooltip).toHaveBeenCalledWith('Class1', 'A tooltip');
}); });
}); });
}); });

View File

@@ -6,7 +6,15 @@
/* lexical grammar */ /* lexical grammar */
%lex %lex
%x string generic struct open_directive type_directive arg_directive %x string
%x generic
%x struct
%x href
%x callbackname
%x callbackargs
%x open_directive
%x type_directive
%x arg_directive
%% %%
\%\%\{ { this.begin('open_directive'); return 'open_directive'; } \%\%\{ { this.begin('open_directive'); return 'open_directive'; }
@@ -29,8 +37,7 @@
"class" return 'CLASS'; "class" return 'CLASS';
"cssClass" return 'CSSCLASS'; "cssClass" return 'CSSCLASS';
"callback" return 'CALLBACK'; "click" return 'CLICK';
"link" return 'LINK';
"<<" return 'ANNOTATION_START'; "<<" return 'ANNOTATION_START';
">>" return 'ANNOTATION_END'; ">>" return 'ANNOTATION_END';
[~] this.begin("generic"); [~] this.begin("generic");
@@ -40,6 +47,30 @@
<string>["] this.popState(); <string>["] this.popState();
<string>[^"]* return "STR"; <string>[^"]* return "STR";
/*
---interactivity command---
'href' adds a link to the specified task. 'href' can only be specified when the
line was introduced with 'click'.
'href "<link>"' attaches the specified link to the node that was specified by 'click'.
*/
"href"[\s]+["] this.begin("href");
<href>["] this.popState();
<href>[^"]* return 'HREF';
/*
---interactivity command---
'call' adds a callback to the specified task. 'call' can only be specified when
the line was introduced with 'click'.
'call <callbackname>(<args>)' attaches the function 'callbackname' with the specified
arguments to the task that was specified by 'click'.
Function arguments are optional: 'call <callbackname>()' simply executes 'callbackname' without any arguments.
*/
"call"[\s]+ this.begin("callbackname");
<callbackname>\([\s]*\) this.popState();
<callbackname>\( this.popState(); this.begin("callbackargs");
<callbackname>[^(]* return 'CALLBACKNAME';
<callbackargs>\) this.popState();
<callbackargs>[^)]* return 'CALLBACKARGS';
\s*\<\| return 'EXTENSION'; \s*\<\| return 'EXTENSION';
\s*\|\> return 'EXTENSION'; \s*\|\> return 'EXTENSION';
@@ -243,10 +274,12 @@ lineType
; ;
clickStatement clickStatement
: CALLBACK className STR {$$ = $1;yy.setClickEvent($2, $3, undefined);} : CLICK className CALLBACKNAME {$$ = $1;yy.setClickEvent($2, $3);}
| CALLBACK className STR STR {$$ = $1;yy.setClickEvent($2, $3, $4);} | CLICK className CALLBACKNAME STR {$$ = $1;yy.setClickEvent($2, $3);yy.setTooltip($2, $4);}
| LINK className STR {$$ = $1;yy.setLink($2, $3, undefined);} | CLICK className CALLBACKNAME CALLBACKARGS {$$ = $1;yy.setClickEvent($2, $3, $4);}
| LINK className STR STR {$$ = $1;yy.setLink($2, $3, $4);} | CLICK className CALLBACKNAME CALLBACKARGS STR {$$ = $1;yy.setClickEvent($2, $3, $4);yy.setTooltip($2, $5);}
| CLICK className HREF {$$ = $1;yy.setLink($2, $3);}
| CLICK className HREF STR {$$ = $1;yy.setLink($2, $3);yy.setTooltip($2, $4);}
; ;
cssClassStatement cssClassStatement