UNPKG

mermaid

Version:

Markdown-ish syntax for generating flowcharts, mindmaps, sequence diagrams, class diagrams, gantt charts, git graphs and more.

4 lines 130 kB
{ "version": 3, "sources": ["../../../src/diagrams/gantt/parser/gantt.jison", "../../../src/diagrams/gantt/ganttDb.js", "../../../src/diagrams/gantt/ganttRenderer.js", "../../../src/diagrams/gantt/styles.js", "../../../src/diagrams/gantt/ganttDiagram.ts"], "sourcesContent": ["/* parser generated by jison 0.4.18 */\n/*\n Returns a Parser object of the following structure:\n\n Parser: {\n yy: {}\n }\n\n Parser.prototype: {\n yy: {},\n trace: function(),\n symbols_: {associative list: name ==> number},\n terminals_: {associative list: number ==> name},\n productions_: [...],\n performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),\n table: [...],\n defaultActions: {...},\n parseError: function(str, hash),\n parse: function(input),\n\n lexer: {\n EOF: 1,\n parseError: function(str, hash),\n setInput: function(input),\n input: function(),\n unput: function(str),\n more: function(),\n less: function(n),\n pastInput: function(),\n upcomingInput: function(),\n showPosition: function(),\n test_match: function(regex_match_array, rule_index),\n next: function(),\n lex: function(),\n begin: function(condition),\n popState: function(),\n _currentRules: function(),\n topState: function(),\n pushState: function(condition),\n\n options: {\n ranges: boolean (optional: true ==> token location info will include a .range[] member)\n flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)\n backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code)\n },\n\n performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),\n rules: [...],\n conditions: {associative list: name ==> set},\n }\n }\n\n\n token location info (@$, _$, etc.): {\n first_line: n,\n last_line: n,\n first_column: n,\n last_column: n,\n range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based)\n }\n\n\n the parseError function receives a 'hash' object with these members for lexer and parser errors: {\n text: (matched text)\n token: (the produced terminal token, if any)\n line: (yylineno)\n }\n while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {\n loc: (yylloc)\n expected: (string describing the set of expected tokens)\n recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)\n }\n*/\nvar parser = (function(){\nvar o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[6,8,10,12,13,14,15,16,17,18,20,21,22,23,24,25,26,27,28,29,30,31,33,35,36,38,40],$V1=[1,26],$V2=[1,27],$V3=[1,28],$V4=[1,29],$V5=[1,30],$V6=[1,31],$V7=[1,32],$V8=[1,33],$V9=[1,34],$Va=[1,9],$Vb=[1,10],$Vc=[1,11],$Vd=[1,12],$Ve=[1,13],$Vf=[1,14],$Vg=[1,15],$Vh=[1,16],$Vi=[1,19],$Vj=[1,20],$Vk=[1,21],$Vl=[1,22],$Vm=[1,23],$Vn=[1,25],$Vo=[1,35];\nvar parser = {trace: function trace () { },\nyy: {},\nsymbols_: {\"error\":2,\"start\":3,\"gantt\":4,\"document\":5,\"EOF\":6,\"line\":7,\"SPACE\":8,\"statement\":9,\"NL\":10,\"weekday\":11,\"weekday_monday\":12,\"weekday_tuesday\":13,\"weekday_wednesday\":14,\"weekday_thursday\":15,\"weekday_friday\":16,\"weekday_saturday\":17,\"weekday_sunday\":18,\"weekend\":19,\"weekend_friday\":20,\"weekend_saturday\":21,\"dateFormat\":22,\"inclusiveEndDates\":23,\"topAxis\":24,\"axisFormat\":25,\"tickInterval\":26,\"excludes\":27,\"includes\":28,\"todayMarker\":29,\"title\":30,\"acc_title\":31,\"acc_title_value\":32,\"acc_descr\":33,\"acc_descr_value\":34,\"acc_descr_multiline_value\":35,\"section\":36,\"clickStatement\":37,\"taskTxt\":38,\"taskData\":39,\"click\":40,\"callbackname\":41,\"callbackargs\":42,\"href\":43,\"clickStatementDebug\":44,\"$accept\":0,\"$end\":1},\nterminals_: {2:\"error\",4:\"gantt\",6:\"EOF\",8:\"SPACE\",10:\"NL\",12:\"weekday_monday\",13:\"weekday_tuesday\",14:\"weekday_wednesday\",15:\"weekday_thursday\",16:\"weekday_friday\",17:\"weekday_saturday\",18:\"weekday_sunday\",20:\"weekend_friday\",21:\"weekend_saturday\",22:\"dateFormat\",23:\"inclusiveEndDates\",24:\"topAxis\",25:\"axisFormat\",26:\"tickInterval\",27:\"excludes\",28:\"includes\",29:\"todayMarker\",30:\"title\",31:\"acc_title\",32:\"acc_title_value\",33:\"acc_descr\",34:\"acc_descr_value\",35:\"acc_descr_multiline_value\",36:\"section\",38:\"taskTxt\",39:\"taskData\",40:\"click\",41:\"callbackname\",42:\"callbackargs\",43:\"href\"},\nproductions_: [0,[3,3],[5,0],[5,2],[7,2],[7,1],[7,1],[7,1],[11,1],[11,1],[11,1],[11,1],[11,1],[11,1],[11,1],[19,1],[19,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,2],[9,2],[9,1],[9,1],[9,1],[9,2],[37,2],[37,3],[37,3],[37,4],[37,3],[37,4],[37,2],[44,2],[44,3],[44,3],[44,4],[44,3],[44,4],[44,2]],\nperformAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {\n/* this == yyval */\n\nvar $0 = $$.length - 1;\nswitch (yystate) {\ncase 1:\n return $$[$0-1]; \nbreak;\ncase 2:\n this.$ = [] \nbreak;\ncase 3:\n$$[$0-1].push($$[$0]);this.$ = $$[$0-1]\nbreak;\ncase 4: case 5:\n this.$ = $$[$0] \nbreak;\ncase 6: case 7:\n this.$=[];\nbreak;\ncase 8:\n yy.setWeekday(\"monday\");\nbreak;\ncase 9:\n yy.setWeekday(\"tuesday\");\nbreak;\ncase 10:\n yy.setWeekday(\"wednesday\");\nbreak;\ncase 11:\n yy.setWeekday(\"thursday\");\nbreak;\ncase 12:\n yy.setWeekday(\"friday\");\nbreak;\ncase 13:\n yy.setWeekday(\"saturday\");\nbreak;\ncase 14:\n yy.setWeekday(\"sunday\");\nbreak;\ncase 15:\n yy.setWeekend(\"friday\");\nbreak;\ncase 16:\n yy.setWeekend(\"saturday\");\nbreak;\ncase 17:\nyy.setDateFormat($$[$0].substr(11));this.$=$$[$0].substr(11);\nbreak;\ncase 18:\nyy.enableInclusiveEndDates();this.$=$$[$0].substr(18);\nbreak;\ncase 19:\nyy.TopAxis();this.$=$$[$0].substr(8);\nbreak;\ncase 20:\nyy.setAxisFormat($$[$0].substr(11));this.$=$$[$0].substr(11);\nbreak;\ncase 21:\nyy.setTickInterval($$[$0].substr(13));this.$=$$[$0].substr(13);\nbreak;\ncase 22:\nyy.setExcludes($$[$0].substr(9));this.$=$$[$0].substr(9);\nbreak;\ncase 23:\nyy.setIncludes($$[$0].substr(9));this.$=$$[$0].substr(9);\nbreak;\ncase 24:\nyy.setTodayMarker($$[$0].substr(12));this.$=$$[$0].substr(12);\nbreak;\ncase 27:\nyy.setDiagramTitle($$[$0].substr(6));this.$=$$[$0].substr(6);\nbreak;\ncase 28:\n this.$=$$[$0].trim();yy.setAccTitle(this.$); \nbreak;\ncase 29: case 30:\n this.$=$$[$0].trim();yy.setAccDescription(this.$); \nbreak;\ncase 31:\n yy.addSection($$[$0].substr(8));this.$=$$[$0].substr(8); \nbreak;\ncase 33:\nyy.addTask($$[$0-1],$$[$0]);this.$='task';\nbreak;\ncase 34:\nthis.$ = $$[$0-1];yy.setClickEvent($$[$0-1], $$[$0], null);\nbreak;\ncase 35:\nthis.$ = $$[$0-2];yy.setClickEvent($$[$0-2], $$[$0-1], $$[$0]);\nbreak;\ncase 36:\nthis.$ = $$[$0-2];yy.setClickEvent($$[$0-2], $$[$0-1], null);yy.setLink($$[$0-2],$$[$0]);\nbreak;\ncase 37:\nthis.$ = $$[$0-3];yy.setClickEvent($$[$0-3], $$[$0-2], $$[$0-1]);yy.setLink($$[$0-3],$$[$0]);\nbreak;\ncase 38:\nthis.$ = $$[$0-2];yy.setClickEvent($$[$0-2], $$[$0], null);yy.setLink($$[$0-2],$$[$0-1]);\nbreak;\ncase 39:\nthis.$ = $$[$0-3];yy.setClickEvent($$[$0-3], $$[$0-1], $$[$0]);yy.setLink($$[$0-3],$$[$0-2]);\nbreak;\ncase 40:\nthis.$ = $$[$0-1];yy.setLink($$[$0-1], $$[$0]);\nbreak;\ncase 41: case 47:\nthis.$=$$[$0-1] + ' ' + $$[$0];\nbreak;\ncase 42: case 43: case 45:\nthis.$=$$[$0-2] + ' ' + $$[$0-1] + ' ' + $$[$0];\nbreak;\ncase 44: case 46:\nthis.$=$$[$0-3] + ' ' + $$[$0-2] + ' ' + $$[$0-1] + ' ' + $$[$0];\nbreak;\n}\n},\ntable: [{3:1,4:[1,2]},{1:[3]},o($V0,[2,2],{5:3}),{6:[1,4],7:5,8:[1,6],9:7,10:[1,8],11:17,12:$V1,13:$V2,14:$V3,15:$V4,16:$V5,17:$V6,18:$V7,19:18,20:$V8,21:$V9,22:$Va,23:$Vb,24:$Vc,25:$Vd,26:$Ve,27:$Vf,28:$Vg,29:$Vh,30:$Vi,31:$Vj,33:$Vk,35:$Vl,36:$Vm,37:24,38:$Vn,40:$Vo},o($V0,[2,7],{1:[2,1]}),o($V0,[2,3]),{9:36,11:17,12:$V1,13:$V2,14:$V3,15:$V4,16:$V5,17:$V6,18:$V7,19:18,20:$V8,21:$V9,22:$Va,23:$Vb,24:$Vc,25:$Vd,26:$Ve,27:$Vf,28:$Vg,29:$Vh,30:$Vi,31:$Vj,33:$Vk,35:$Vl,36:$Vm,37:24,38:$Vn,40:$Vo},o($V0,[2,5]),o($V0,[2,6]),o($V0,[2,17]),o($V0,[2,18]),o($V0,[2,19]),o($V0,[2,20]),o($V0,[2,21]),o($V0,[2,22]),o($V0,[2,23]),o($V0,[2,24]),o($V0,[2,25]),o($V0,[2,26]),o($V0,[2,27]),{32:[1,37]},{34:[1,38]},o($V0,[2,30]),o($V0,[2,31]),o($V0,[2,32]),{39:[1,39]},o($V0,[2,8]),o($V0,[2,9]),o($V0,[2,10]),o($V0,[2,11]),o($V0,[2,12]),o($V0,[2,13]),o($V0,[2,14]),o($V0,[2,15]),o($V0,[2,16]),{41:[1,40],43:[1,41]},o($V0,[2,4]),o($V0,[2,28]),o($V0,[2,29]),o($V0,[2,33]),o($V0,[2,34],{42:[1,42],43:[1,43]}),o($V0,[2,40],{41:[1,44]}),o($V0,[2,35],{43:[1,45]}),o($V0,[2,36]),o($V0,[2,38],{42:[1,46]}),o($V0,[2,37]),o($V0,[2,39])],\ndefaultActions: {},\nparseError: function parseError (str, hash) {\n if (hash.recoverable) {\n this.trace(str);\n } else {\n var error = new Error(str);\n error.hash = hash;\n throw error;\n }\n},\nparse: function parse(input) {\n var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;\n var args = lstack.slice.call(arguments, 1);\n var lexer = Object.create(this.lexer);\n var sharedState = { yy: {} };\n for (var k in this.yy) {\n if (Object.prototype.hasOwnProperty.call(this.yy, k)) {\n sharedState.yy[k] = this.yy[k];\n }\n }\n lexer.setInput(input, sharedState.yy);\n sharedState.yy.lexer = lexer;\n sharedState.yy.parser = this;\n if (typeof lexer.yylloc == 'undefined') {\n lexer.yylloc = {};\n }\n var yyloc = lexer.yylloc;\n lstack.push(yyloc);\n var ranges = lexer.options && lexer.options.ranges;\n if (typeof sharedState.yy.parseError === 'function') {\n this.parseError = sharedState.yy.parseError;\n } else {\n this.parseError = Object.getPrototypeOf(this).parseError;\n }\n function popStack(n) {\n stack.length = stack.length - 2 * n;\n vstack.length = vstack.length - n;\n lstack.length = lstack.length - n;\n }\n function lex() {\n var token;\n token = tstack.pop() || lexer.lex() || EOF;\n if (typeof token !== 'number') {\n if (token instanceof Array) {\n tstack = token;\n token = tstack.pop();\n }\n token = self.symbols_[token] || token;\n }\n return token;\n }\n var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;\n while (true) {\n state = stack[stack.length - 1];\n if (this.defaultActions[state]) {\n action = this.defaultActions[state];\n } else {\n if (symbol === null || typeof symbol == 'undefined') {\n symbol = lex();\n }\n action = table[state] && table[state][symbol];\n }\n if (typeof action === 'undefined' || !action.length || !action[0]) {\n var errStr = '';\n expected = [];\n for (p in table[state]) {\n if (this.terminals_[p] && p > TERROR) {\n expected.push('\\'' + this.terminals_[p] + '\\'');\n }\n }\n if (lexer.showPosition) {\n errStr = 'Parse error on line ' + (yylineno + 1) + ':\\n' + lexer.showPosition() + '\\nExpecting ' + expected.join(', ') + ', got \\'' + (this.terminals_[symbol] || symbol) + '\\'';\n } else {\n errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\\'' + (this.terminals_[symbol] || symbol) + '\\'');\n }\n this.parseError(errStr, {\n text: lexer.match,\n token: this.terminals_[symbol] || symbol,\n line: lexer.yylineno,\n loc: yyloc,\n expected: expected\n });\n }\n if (action[0] instanceof Array && action.length > 1) {\n throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);\n }\n switch (action[0]) {\n case 1:\n stack.push(symbol);\n vstack.push(lexer.yytext);\n lstack.push(lexer.yylloc);\n stack.push(action[1]);\n symbol = null;\n if (!preErrorSymbol) {\n yyleng = lexer.yyleng;\n yytext = lexer.yytext;\n yylineno = lexer.yylineno;\n yyloc = lexer.yylloc;\n if (recovering > 0) {\n recovering--;\n }\n } else {\n symbol = preErrorSymbol;\n preErrorSymbol = null;\n }\n break;\n case 2:\n len = this.productions_[action[1]][1];\n yyval.$ = vstack[vstack.length - len];\n yyval._$ = {\n first_line: lstack[lstack.length - (len || 1)].first_line,\n last_line: lstack[lstack.length - 1].last_line,\n first_column: lstack[lstack.length - (len || 1)].first_column,\n last_column: lstack[lstack.length - 1].last_column\n };\n if (ranges) {\n yyval._$.range = [\n lstack[lstack.length - (len || 1)].range[0],\n lstack[lstack.length - 1].range[1]\n ];\n }\n r = this.performAction.apply(yyval, [\n yytext,\n yyleng,\n yylineno,\n sharedState.yy,\n action[1],\n vstack,\n lstack\n ].concat(args));\n if (typeof r !== 'undefined') {\n return r;\n }\n if (len) {\n stack = stack.slice(0, -1 * len * 2);\n vstack = vstack.slice(0, -1 * len);\n lstack = lstack.slice(0, -1 * len);\n }\n stack.push(this.productions_[action[1]][0]);\n vstack.push(yyval.$);\n lstack.push(yyval._$);\n newState = table[stack[stack.length - 2]][stack[stack.length - 1]];\n stack.push(newState);\n break;\n case 3:\n return true;\n }\n }\n return true;\n}};\n\n/* generated by jison-lex 0.3.4 */\nvar lexer = (function(){\nvar lexer = ({\n\nEOF:1,\n\nparseError:function parseError(str, hash) {\n if (this.yy.parser) {\n this.yy.parser.parseError(str, hash);\n } else {\n throw new Error(str);\n }\n },\n\n// resets the lexer, sets new input\nsetInput:function (input, yy) {\n this.yy = yy || this.yy || {};\n this._input = input;\n this._more = this._backtrack = this.done = false;\n this.yylineno = this.yyleng = 0;\n this.yytext = this.matched = this.match = '';\n this.conditionStack = ['INITIAL'];\n this.yylloc = {\n first_line: 1,\n first_column: 0,\n last_line: 1,\n last_column: 0\n };\n if (this.options.ranges) {\n this.yylloc.range = [0,0];\n }\n this.offset = 0;\n return this;\n },\n\n// consumes and returns one char from the input\ninput:function () {\n var ch = this._input[0];\n this.yytext += ch;\n this.yyleng++;\n this.offset++;\n this.match += ch;\n this.matched += ch;\n var lines = ch.match(/(?:\\r\\n?|\\n).*/g);\n if (lines) {\n this.yylineno++;\n this.yylloc.last_line++;\n } else {\n this.yylloc.last_column++;\n }\n if (this.options.ranges) {\n this.yylloc.range[1]++;\n }\n\n this._input = this._input.slice(1);\n return ch;\n },\n\n// unshifts one char (or a string) into the input\nunput:function (ch) {\n var len = ch.length;\n var lines = ch.split(/(?:\\r\\n?|\\n)/g);\n\n this._input = ch + this._input;\n this.yytext = this.yytext.substr(0, this.yytext.length - len);\n //this.yyleng -= len;\n this.offset -= len;\n var oldLines = this.match.split(/(?:\\r\\n?|\\n)/g);\n this.match = this.match.substr(0, this.match.length - 1);\n this.matched = this.matched.substr(0, this.matched.length - 1);\n\n if (lines.length - 1) {\n this.yylineno -= lines.length - 1;\n }\n var r = this.yylloc.range;\n\n this.yylloc = {\n first_line: this.yylloc.first_line,\n last_line: this.yylineno + 1,\n first_column: this.yylloc.first_column,\n last_column: lines ?\n (lines.length === oldLines.length ? this.yylloc.first_column : 0)\n + oldLines[oldLines.length - lines.length].length - lines[0].length :\n this.yylloc.first_column - len\n };\n\n if (this.options.ranges) {\n this.yylloc.range = [r[0], r[0] + this.yyleng - len];\n }\n this.yyleng = this.yytext.length;\n return this;\n },\n\n// When called from action, caches matched text and appends it on next action\nmore:function () {\n this._more = true;\n return this;\n },\n\n// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.\nreject:function () {\n if (this.options.backtrack_lexer) {\n this._backtrack = true;\n } else {\n return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\\n' + this.showPosition(), {\n text: \"\",\n token: null,\n line: this.yylineno\n });\n\n }\n return this;\n },\n\n// retain first n characters of the match\nless:function (n) {\n this.unput(this.match.slice(n));\n },\n\n// displays already matched input, i.e. for error messages\npastInput:function () {\n var past = this.matched.substr(0, this.matched.length - this.match.length);\n return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\\n/g, \"\");\n },\n\n// displays upcoming input, i.e. for error messages\nupcomingInput:function () {\n var next = this.match;\n if (next.length < 20) {\n next += this._input.substr(0, 20-next.length);\n }\n return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\\n/g, \"\");\n },\n\n// displays the character position where the lexing error occurred, i.e. for error messages\nshowPosition:function () {\n var pre = this.pastInput();\n var c = new Array(pre.length + 1).join(\"-\");\n return pre + this.upcomingInput() + \"\\n\" + c + \"^\";\n },\n\n// test the lexed token: return FALSE when not a match, otherwise return token\ntest_match:function(match, indexed_rule) {\n var token,\n lines,\n backup;\n\n if (this.options.backtrack_lexer) {\n // save context\n backup = {\n yylineno: this.yylineno,\n yylloc: {\n first_line: this.yylloc.first_line,\n last_line: this.last_line,\n first_column: this.yylloc.first_column,\n last_column: this.yylloc.last_column\n },\n yytext: this.yytext,\n match: this.match,\n matches: this.matches,\n matched: this.matched,\n yyleng: this.yyleng,\n offset: this.offset,\n _more: this._more,\n _input: this._input,\n yy: this.yy,\n conditionStack: this.conditionStack.slice(0),\n done: this.done\n };\n if (this.options.ranges) {\n backup.yylloc.range = this.yylloc.range.slice(0);\n }\n }\n\n lines = match[0].match(/(?:\\r\\n?|\\n).*/g);\n if (lines) {\n this.yylineno += lines.length;\n }\n this.yylloc = {\n first_line: this.yylloc.last_line,\n last_line: this.yylineno + 1,\n first_column: this.yylloc.last_column,\n last_column: lines ?\n lines[lines.length - 1].length - lines[lines.length - 1].match(/\\r?\\n?/)[0].length :\n this.yylloc.last_column + match[0].length\n };\n this.yytext += match[0];\n this.match += match[0];\n this.matches = match;\n this.yyleng = this.yytext.length;\n if (this.options.ranges) {\n this.yylloc.range = [this.offset, this.offset += this.yyleng];\n }\n this._more = false;\n this._backtrack = false;\n this._input = this._input.slice(match[0].length);\n this.matched += match[0];\n token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);\n if (this.done && this._input) {\n this.done = false;\n }\n if (token) {\n return token;\n } else if (this._backtrack) {\n // recover context\n for (var k in backup) {\n this[k] = backup[k];\n }\n return false; // rule action called reject() implying the next rule should be tested instead.\n }\n return false;\n },\n\n// return next match in input\nnext:function () {\n if (this.done) {\n return this.EOF;\n }\n if (!this._input) {\n this.done = true;\n }\n\n var token,\n match,\n tempMatch,\n index;\n if (!this._more) {\n this.yytext = '';\n this.match = '';\n }\n var rules = this._currentRules();\n for (var i = 0; i < rules.length; i++) {\n tempMatch = this._input.match(this.rules[rules[i]]);\n if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {\n match = tempMatch;\n index = i;\n if (this.options.backtrack_lexer) {\n token = this.test_match(tempMatch, rules[i]);\n if (token !== false) {\n return token;\n } else if (this._backtrack) {\n match = false;\n continue; // rule action called reject() implying a rule MISmatch.\n } else {\n // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)\n return false;\n }\n } else if (!this.options.flex) {\n break;\n }\n }\n }\n if (match) {\n token = this.test_match(match, rules[index]);\n if (token !== false) {\n return token;\n }\n // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)\n return false;\n }\n if (this._input === \"\") {\n return this.EOF;\n } else {\n return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\\n' + this.showPosition(), {\n text: \"\",\n token: null,\n line: this.yylineno\n });\n }\n },\n\n// return next match that has a token\nlex:function lex () {\n var r = this.next();\n if (r) {\n return r;\n } else {\n return this.lex();\n }\n },\n\n// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)\nbegin:function begin (condition) {\n this.conditionStack.push(condition);\n },\n\n// pop the previously active lexer condition state off the condition stack\npopState:function popState () {\n var n = this.conditionStack.length - 1;\n if (n > 0) {\n return this.conditionStack.pop();\n } else {\n return this.conditionStack[0];\n }\n },\n\n// produce the lexer rule set which is active for the currently active lexer condition state\n_currentRules:function _currentRules () {\n if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {\n return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;\n } else {\n return this.conditions[\"INITIAL\"].rules;\n }\n },\n\n// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available\ntopState:function topState (n) {\n n = this.conditionStack.length - 1 - Math.abs(n || 0);\n if (n >= 0) {\n return this.conditionStack[n];\n } else {\n return \"INITIAL\";\n }\n },\n\n// alias for begin(condition)\npushState:function pushState (condition) {\n this.begin(condition);\n },\n\n// return the number of states currently on the stack\nstateStackSize:function stateStackSize() {\n return this.conditionStack.length;\n },\noptions: {\"case-insensitive\":true},\nperformAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {\nvar YYSTATE=YY_START;\nswitch($avoiding_name_collisions) {\ncase 0: this.begin('open_directive'); return 'open_directive'; \nbreak;\ncase 1: this.begin(\"acc_title\");return 31; \nbreak;\ncase 2: this.popState(); return \"acc_title_value\"; \nbreak;\ncase 3: this.begin(\"acc_descr\");return 33; \nbreak;\ncase 4: this.popState(); return \"acc_descr_value\"; \nbreak;\ncase 5: this.begin(\"acc_descr_multiline\");\nbreak;\ncase 6: this.popState(); \nbreak;\ncase 7:return \"acc_descr_multiline_value\";\nbreak;\ncase 8:/* skip comments */\nbreak;\ncase 9:/* skip comments */\nbreak;\ncase 10:/* do nothing */\nbreak;\ncase 11:return 10;\nbreak;\ncase 12:/* skip whitespace */\nbreak;\ncase 13:/* skip comments */\nbreak;\ncase 14:this.begin(\"href\");\nbreak;\ncase 15:this.popState();\nbreak;\ncase 16:return 43;\nbreak;\ncase 17:this.begin(\"callbackname\");\nbreak;\ncase 18:this.popState();\nbreak;\ncase 19:this.popState(); this.begin(\"callbackargs\");\nbreak;\ncase 20:return 41;\nbreak;\ncase 21:this.popState();\nbreak;\ncase 22:return 42;\nbreak;\ncase 23:this.begin(\"click\");\nbreak;\ncase 24:this.popState();\nbreak;\ncase 25:return 40;\nbreak;\ncase 26:return 4;\nbreak;\ncase 27:return 22;\nbreak;\ncase 28:return 23;\nbreak;\ncase 29:return 24;\nbreak;\ncase 30:return 25;\nbreak;\ncase 31:return 26;\nbreak;\ncase 32:return 28;\nbreak;\ncase 33:return 27;\nbreak;\ncase 34:return 29;\nbreak;\ncase 35:return 12\nbreak;\ncase 36:return 13\nbreak;\ncase 37:return 14\nbreak;\ncase 38:return 15\nbreak;\ncase 39:return 16\nbreak;\ncase 40:return 17\nbreak;\ncase 41:return 18\nbreak;\ncase 42:return 20\nbreak;\ncase 43:return 21\nbreak;\ncase 44:return 'date';\nbreak;\ncase 45:return 30;\nbreak;\ncase 46:return 'accDescription'\nbreak;\ncase 47:return 36;\nbreak;\ncase 48:return 38;\nbreak;\ncase 49:return 39;\nbreak;\ncase 50:return ':';\nbreak;\ncase 51:return 6;\nbreak;\ncase 52:return 'INVALID';\nbreak;\n}\n},\nrules: [/^(?:%%\\{)/i,/^(?:accTitle\\s*:\\s*)/i,/^(?:(?!\\n||)*[^\\n]*)/i,/^(?:accDescr\\s*:\\s*)/i,/^(?:(?!\\n||)*[^\\n]*)/i,/^(?:accDescr\\s*\\{\\s*)/i,/^(?:[\\}])/i,/^(?:[^\\}]*)/i,/^(?:%%(?!\\{)*[^\\n]*)/i,/^(?:[^\\}]%%*[^\\n]*)/i,/^(?:%%*[^\\n]*[\\n]*)/i,/^(?:[\\n]+)/i,/^(?:\\s+)/i,/^(?:%[^\\n]*)/i,/^(?:href[\\s]+[\"])/i,/^(?:[\"])/i,/^(?:[^\"]*)/i,/^(?:call[\\s]+)/i,/^(?:\\([\\s]*\\))/i,/^(?:\\()/i,/^(?:[^(]*)/i,/^(?:\\))/i,/^(?:[^)]*)/i,/^(?:click[\\s]+)/i,/^(?:[\\s\\n])/i,/^(?:[^\\s\\n]*)/i,/^(?:gantt\\b)/i,/^(?:dateFormat\\s[^#\\n;]+)/i,/^(?:inclusiveEndDates\\b)/i,/^(?:topAxis\\b)/i,/^(?:axisFormat\\s[^#\\n;]+)/i,/^(?:tickInterval\\s[^#\\n;]+)/i,/^(?:includes\\s[^#\\n;]+)/i,/^(?:excludes\\s[^#\\n;]+)/i,/^(?:todayMarker\\s[^\\n;]+)/i,/^(?:weekday\\s+monday\\b)/i,/^(?:weekday\\s+tuesday\\b)/i,/^(?:weekday\\s+wednesday\\b)/i,/^(?:weekday\\s+thursday\\b)/i,/^(?:weekday\\s+friday\\b)/i,/^(?:weekday\\s+saturday\\b)/i,/^(?:weekday\\s+sunday\\b)/i,/^(?:weekend\\s+friday\\b)/i,/^(?:weekend\\s+saturday\\b)/i,/^(?:\\d\\d\\d\\d-\\d\\d-\\d\\d\\b)/i,/^(?:title\\s[^\\n]+)/i,/^(?:accDescription\\s[^#\\n;]+)/i,/^(?:section\\s[^\\n]+)/i,/^(?:[^:\\n]+)/i,/^(?::[^#\\n;]+)/i,/^(?::)/i,/^(?:$)/i,/^(?:.)/i],\nconditions: {\"acc_descr_multiline\":{\"rules\":[6,7],\"inclusive\":false},\"acc_descr\":{\"rules\":[4],\"inclusive\":false},\"acc_title\":{\"rules\":[2],\"inclusive\":false},\"callbackargs\":{\"rules\":[21,22],\"inclusive\":false},\"callbackname\":{\"rules\":[18,19,20],\"inclusive\":false},\"href\":{\"rules\":[15,16],\"inclusive\":false},\"click\":{\"rules\":[24,25],\"inclusive\":false},\"INITIAL\":{\"rules\":[0,1,3,5,8,9,10,11,12,13,14,17,23,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52],\"inclusive\":true}}\n});\nreturn lexer;\n})();\nparser.lexer = lexer;\nfunction Parser () {\n this.yy = {};\n}\nParser.prototype = parser;parser.Parser = Parser;\nreturn new Parser;\n})(); \n\tparser.parser = parser;\n\texport { parser };\n\texport default parser;\n\t", "import { sanitizeUrl } from '@braintree/sanitize-url';\nimport dayjs from 'dayjs';\nimport dayjsIsoWeek from 'dayjs/plugin/isoWeek.js';\nimport dayjsCustomParseFormat from 'dayjs/plugin/customParseFormat.js';\nimport dayjsAdvancedFormat from 'dayjs/plugin/advancedFormat.js';\nimport { log } from '../../logger.js';\nimport { getConfig } from '../../diagram-api/diagramAPI.js';\nimport utils from '../../utils.js';\n\nimport {\n setAccTitle,\n getAccTitle,\n getAccDescription,\n setAccDescription,\n clear as commonClear,\n setDiagramTitle,\n getDiagramTitle,\n} from '../common/commonDb.js';\n\ndayjs.extend(dayjsIsoWeek);\ndayjs.extend(dayjsCustomParseFormat);\ndayjs.extend(dayjsAdvancedFormat);\n\nconst WEEKEND_START_DAY = { friday: 5, saturday: 6 };\nlet dateFormat = '';\nlet axisFormat = '';\nlet tickInterval = undefined;\nlet todayMarker = '';\nlet includes = [];\nlet excludes = [];\nlet links = new Map();\nlet sections = [];\nlet tasks = [];\nlet currentSection = '';\nlet displayMode = '';\nconst tags = ['active', 'done', 'crit', 'milestone', 'vert'];\nlet funs = [];\nlet inclusiveEndDates = false;\nlet topAxis = false;\nlet weekday = 'sunday';\nlet weekend = 'saturday';\n\n// The serial order of the task in the script\nlet lastOrder = 0;\n\nexport const clear = function () {\n sections = [];\n tasks = [];\n currentSection = '';\n funs = [];\n taskCnt = 0;\n lastTask = undefined;\n lastTaskID = undefined;\n rawTasks = [];\n dateFormat = '';\n axisFormat = '';\n displayMode = '';\n tickInterval = undefined;\n todayMarker = '';\n includes = [];\n excludes = [];\n inclusiveEndDates = false;\n topAxis = false;\n lastOrder = 0;\n links = new Map();\n commonClear();\n weekday = 'sunday';\n weekend = 'saturday';\n};\n\nexport const setAxisFormat = function (txt) {\n axisFormat = txt;\n};\n\nexport const getAxisFormat = function () {\n return axisFormat;\n};\n\nexport const setTickInterval = function (txt) {\n tickInterval = txt;\n};\n\nexport const getTickInterval = function () {\n return tickInterval;\n};\n\nexport const setTodayMarker = function (txt) {\n todayMarker = txt;\n};\n\nexport const getTodayMarker = function () {\n return todayMarker;\n};\n\nexport const setDateFormat = function (txt) {\n dateFormat = txt;\n};\n\nexport const enableInclusiveEndDates = function () {\n inclusiveEndDates = true;\n};\n\nexport const endDatesAreInclusive = function () {\n return inclusiveEndDates;\n};\n\nexport const enableTopAxis = function () {\n topAxis = true;\n};\n\nexport const topAxisEnabled = function () {\n return topAxis;\n};\n\nexport const setDisplayMode = function (txt) {\n displayMode = txt;\n};\n\nexport const getDisplayMode = function () {\n return displayMode;\n};\n\nexport const getDateFormat = function () {\n return dateFormat;\n};\n\nexport const setIncludes = function (txt) {\n includes = txt.toLowerCase().split(/[\\s,]+/);\n};\n\nexport const getIncludes = function () {\n return includes;\n};\nexport const setExcludes = function (txt) {\n excludes = txt.toLowerCase().split(/[\\s,]+/);\n};\n\nexport const getExcludes = function () {\n return excludes;\n};\n\nexport const getLinks = function () {\n return links;\n};\n\nexport const addSection = function (txt) {\n currentSection = txt;\n sections.push(txt);\n};\n\nexport const getSections = function () {\n return sections;\n};\n\nexport const getTasks = function () {\n let allItemsProcessed = compileTasks();\n const maxDepth = 10;\n let iterationCount = 0;\n while (!allItemsProcessed && iterationCount < maxDepth) {\n allItemsProcessed = compileTasks();\n iterationCount++;\n }\n\n tasks = rawTasks;\n\n return tasks;\n};\n\nexport const isInvalidDate = function (date, dateFormat, excludes, includes) {\n if (includes.includes(date.format(dateFormat.trim()))) {\n return false;\n }\n if (\n excludes.includes('weekends') &&\n (date.isoWeekday() === WEEKEND_START_DAY[weekend] ||\n date.isoWeekday() === WEEKEND_START_DAY[weekend] + 1)\n ) {\n return true;\n }\n if (excludes.includes(date.format('dddd').toLowerCase())) {\n return true;\n }\n return excludes.includes(date.format(dateFormat.trim()));\n};\n\nexport const setWeekday = function (txt) {\n weekday = txt;\n};\n\nexport const getWeekday = function () {\n return weekday;\n};\n\nexport const setWeekend = function (startDay) {\n weekend = startDay;\n};\n\n/**\n * TODO: fully document what this function does and what types it accepts\n *\n * @param {object} task - The task to check.\n * @param {string | Date} task.startTime - Might be a `Date` or a `string`.\n * TODO: is this always a Date?\n * @param {string | Date} task.endTime - Might be a `Date` or a `string`.\n * TODO: is this always a Date?\n * @param {string} dateFormat - Dayjs date format string.\n * @param {*} excludes\n * @param {*} includes\n */\nconst checkTaskDates = function (task, dateFormat, excludes, includes) {\n if (!excludes.length || task.manualEndTime) {\n return;\n }\n let startTime;\n if (task.startTime instanceof Date) {\n startTime = dayjs(task.startTime);\n } else {\n startTime = dayjs(task.startTime, dateFormat, true);\n }\n startTime = startTime.add(1, 'd');\n\n let originalEndTime;\n if (task.endTime instanceof Date) {\n originalEndTime = dayjs(task.endTime);\n } else {\n originalEndTime = dayjs(task.endTime, dateFormat, true);\n }\n const [fixedEndTime, renderEndTime] = fixTaskDates(\n startTime,\n originalEndTime,\n dateFormat,\n excludes,\n includes\n );\n task.endTime = fixedEndTime.toDate();\n task.renderEndTime = renderEndTime;\n};\n\n/**\n * TODO: what does this function do?\n *\n * @param {dayjs.Dayjs} startTime - The start time.\n * @param {dayjs.Dayjs} endTime - The original end time (will return a different end time if it's invalid).\n * @param {string} dateFormat - Dayjs date format string.\n * @param {*} excludes\n * @param {*} includes\n * @returns {[endTime: dayjs.Dayjs, renderEndTime: Date | null]} The new `endTime`, and the end time to render.\n * `renderEndTime` may be `null` if `startTime` is newer than `endTime`.\n */\nconst fixTaskDates = function (startTime, endTime, dateFormat, excludes, includes) {\n let invalid = false;\n let renderEndTime = null;\n while (startTime <= endTime) {\n if (!invalid) {\n renderEndTime = endTime.toDate();\n }\n invalid = isInvalidDate(startTime, dateFormat, excludes, includes);\n if (invalid) {\n endTime = endTime.add(1, 'd');\n }\n startTime = startTime.add(1, 'd');\n }\n return [endTime, renderEndTime];\n};\n\nconst getStartDate = function (prevTime, dateFormat, str) {\n str = str.trim();\n\n // Test for after\n const afterRePattern = /^after\\s+(?<ids>[\\d\\w- ]+)/;\n const afterStatement = afterRePattern.exec(str);\n\n if (afterStatement !== null) {\n // check all after ids and take the latest\n let latestTask = null;\n for (const id of afterStatement.groups.ids.split(' ')) {\n let task = findTaskById(id);\n if (task !== undefined && (!latestTask || task.endTime > latestTask.endTime)) {\n latestTask = task;\n }\n }\n\n if (latestTask) {\n return latestTask.endTime;\n }\n const today = new Date();\n today.setHours(0, 0, 0, 0);\n return today;\n }\n\n // Check for actual date set\n let mDate = dayjs(str, dateFormat.trim(), true);\n if (mDate.isValid()) {\n return mDate.toDate();\n } else {\n log.debug('Invalid date:' + str);\n log.debug('With date format:' + dateFormat.trim());\n const d = new Date(str);\n if (\n d === undefined ||\n isNaN(d.getTime()) ||\n // WebKit browsers can mis-parse invalid dates to be ridiculously\n // huge numbers, e.g. new Date('202304') gets parsed as January 1, 202304.\n // This can cause virtually infinite loops while rendering, so for the\n // purposes of Gantt charts we'll just treat any date beyond 10,000 AD/BC as\n // invalid.\n d.getFullYear() < -10000 ||\n d.getFullYear() > 10000\n ) {\n throw new Error('Invalid date:' + str);\n }\n return d;\n }\n};\n\n/**\n * Parse a string into the args for `dayjs.add()`.\n *\n * The string have to be compound by a value and a shorthand duration unit. For example `5d`\n * represents 5 days.\n *\n * Please be aware that 1 day may be 23 or 25 hours, if the user lives in an area\n * that has daylight savings time (or even 23.5/24.5 hours in Lord Howe Island!)\n *\n * Shorthand unit supported are:\n *\n * - `y` for years\n * - `M` for months\n * - `w` for weeks\n * - `d` for days\n * - `h` for hours\n * - `s` for seconds\n * - `ms` for milliseconds\n *\n * @param {string} str - A string representing the duration.\n * @returns {[value: number, unit: dayjs.ManipulateType]} Arguments to pass to `dayjs.add()`\n */\nconst parseDuration = function (str) {\n // cspell:disable-next-line\n const statement = /^(\\d+(?:\\.\\d+)?)([Mdhmswy]|ms)$/.exec(str.trim());\n if (statement !== null) {\n return [Number.parseFloat(statement[1]), statement[2]];\n }\n // NaN means an invalid duration\n return [NaN, 'ms'];\n};\n\nconst getEndDate = function (prevTime, dateFormat, str, inclusive = false) {\n str = str.trim();\n\n // test for until\n const untilRePattern = /^until\\s+(?<ids>[\\d\\w- ]+)/;\n const untilStatement = untilRePattern.exec(str);\n\n if (untilStatement !== null) {\n // check all until ids and take the earliest\n let earliestTask = null;\n for (const id of untilStatement.groups.ids.split(' ')) {\n let task = findTaskById(id);\n if (task !== undefined && (!earliestTask || task.startTime < earliestTask.startTime)) {\n earliestTask = task;\n }\n }\n\n if (earliestTask) {\n return earliestTask.startTime;\n }\n const today = new Date();\n today.setHours(0, 0, 0, 0);\n return today;\n }\n\n // check for actual date\n let parsedDate = dayjs(str, dateFormat.trim(), true);\n if (parsedDate.isValid()) {\n if (inclusive) {\n parsedDate = parsedDate.add(1, 'd');\n }\n return parsedDate.toDate();\n }\n\n let endTime = dayjs(prevTime);\n const [durationValue, durationUnit] = parseDuration(str);\n if (!Number.isNaN(durationValue)) {\n const newEndTime = endTime.add(durationValue, durationUnit);\n if (newEndTime.isValid()) {\n endTime = newEndTime;\n }\n }\n return endTime.toDate();\n};\n\nlet taskCnt = 0;\nconst parseId = function (idStr) {\n if (idStr === undefined) {\n taskCnt = taskCnt + 1;\n return 'task' + taskCnt;\n }\n return idStr;\n};\n// id, startDate, endDate\n// id, startDate, length\n// id, after x, endDate\n// id, after x, length\n// startDate, endDate\n// startDate, length\n// after x, endDate\n// after x, length\n// endDate\n// length\n\nconst compileData = function (prevTask, dataStr) {\n let ds;\n\n if (dataStr.substr(0, 1) === ':') {\n ds = dataStr.substr(1, dataStr.length);\n } else {\n ds = dataStr;\n }\n\n const data = ds.split(',');\n\n const task = {};\n\n // Get tags like active, done, crit, milestone, and vert\n getTaskTags(data, task, tags);\n\n for (let i = 0; i < data.length; i++) {\n data[i] = data[i].trim();\n }\n\n let endTimeData = '';\n switch (data.length) {\n case 1:\n task.id = parseId();\n task.startTime = prevTask.endTime;\n endTimeData = data[0];\n break;\n case 2:\n task.id = parseId();\n task.startTime = getStartDate(undefined, dateFormat, data[0]);\n endTimeData = data[1];\n break;\n case 3:\n task.id = parseId(data[0]);\n task.startTime = getStartDate(undefined, dateFormat, data[1]);\n endTimeData = data[2];\n break;\n default:\n }\n\n if (endTimeData) {\n task.endTime = getEndDate(task.startTime, dateFormat, endTimeData, inclusiveEndDates);\n task.manualEndTime = dayjs(endTimeData, 'YYYY-MM-DD', true).isValid();\n checkTaskDates(task, dateFormat, excludes, includes);\n }\n\n return task;\n};\n\nconst parseData = function (prevTaskId, dataStr) {\n let ds;\n if (dataStr.substr(0, 1) === ':') {\n ds = dataStr.substr(1, dataStr.length);\n } else {\n ds = dataStr;\n }\n\n const data = ds.split(',');\n\n const task = {};\n\n // Get tags like active, done, crit, milestone, and vert\n getTaskTags(data, task, tags);\n\n for (let i = 0; i < data.length; i++) {\n data[i] = data[i].trim();\n }\n\n switch (data.length) {\n case 1:\n task.id = parseId();\n task.startTime = {\n type: 'prevTaskEnd',\n id: prevTaskId,\n };\n task.endTime = {\n data: data[0],\n };\n break;\n case 2:\n task.id = parseId();\n task.startTime = {\n type: 'getStartDate',\n startData: data[0],\n };\n task.endTime = {\n data: data[1],\n };\n break;\n case 3:\n task.id = parseId(data[0]);\n task.startTime = {\n type: 'getStartDate',\n startData: data[1],\n };\n task.endTime = {\n data: data[2],\n };\n break;\n default:\n }\n\n return task;\n};\n\nlet lastTask;\nlet lastTaskID;\nlet rawTasks = [];\nconst taskDb = {};\nexport const addTask = function (descr, data) {\n const rawTask = {\n section: currentSection,\n type: currentSection,\n processed: false,\n manualEndTime: false,\n renderEndTime: null,\n raw: { data: data },\n task: descr,\n classes: [],\n };\n const taskInfo = parseData(lastTaskID, data);\n rawTask.raw.startTime = taskInfo.startTime;\n rawTask.raw.endTime = taskInfo.endTime;\n rawTask.id = taskInfo.id;\n rawTask.prevTaskId = lastTaskID;\n rawTask.active = taskInfo.active;\n rawTask.done = taskInfo.done;\n rawTask.crit = taskInfo.crit;\n rawTask.milestone = taskInfo.milestone;\n rawTask.vert = taskInfo.vert;\n rawTask.order = lastOrder;\n\n lastOrder++;\n\n const pos = rawTasks.push(rawTask);\n\n lastTaskID = rawTask.id;\n // Store cross ref\n taskDb[rawTask.id] = pos - 1;\n};\n\nexport const findTaskById = function (id) {\n const pos = taskDb[id];\n return rawTasks[pos];\n};\n\nexport const addTaskOrg = function (descr, data) {\n const newTask = {\n section: currentSection,\n type: currentSection,\n description: descr,\n task: descr,\n classes: [],\n };\n const taskInfo = compileData(lastTask, data);\n newTask.startTime = taskInfo.startTime;\n newTask.endTime = taskInfo.endTime;\n newTask.id = taskInfo.id;\n newTask.active = taskInfo.active;\n newTask.done = taskInfo.done;\n newTask.crit = taskInfo.crit;\n newTask.milestone = taskInfo.milestone;\n newTask.vert = taskInfo.vert;\n lastTask = newTask;\n tasks.push(newTask);\n};\n\nconst compileTasks = function () {\n const compileTask = function (pos) {\n const task = rawTasks[pos];\n let startTime = '';\n switch (rawTasks[pos].raw.startTime.type) {\n case 'prevTaskEnd': {\n const prevTask = findTaskById(task.prevTaskId);\n task.startTime = prevTask.endTime;\n break;\n }\n case 'getStartDate':\n startTime = getStartDate(undefined, dateFormat, rawTasks[pos].raw.startTime.startData);\n if (startTime) {\n rawTasks[pos].startTime = startTime;\n }\n break;\n }\n\n if (rawTasks[pos].startTime) {\n rawTasks[pos].endTime = getEndDate(\n rawTasks[pos].startTime,\n dateFormat,\n rawTasks[pos].raw.endTime.data,\n inclusiveEndDates\n );\n if (rawTasks[pos].endTime) {\n rawTasks[pos].processed = true;\n rawTasks[pos].manualEndTime = dayjs(\n rawTasks[pos].raw.endTime.data,\n 'YYYY-MM-DD',\n true\n ).isValid();\n checkTaskDates(rawTasks[pos], dateFormat, excludes, includes);\n }\n }\n\n return rawTasks[pos].processed;\n };\n\n let allProcessed = true;\n for (const [i, rawTask] of rawTasks.entries()) {\n compileTask(i);\n\n allProcessed = allProcessed && rawTask.processed;\n }\n return allProcessed;\n};\n\n/**\n * Called by parser when a link is found. Adds the URL to the vertex data.\n *\n * @param ids Comma separated list of ids\n * @param _linkStr URL to create a link for\n */\nexport const setLink = function (ids, _linkStr) {\n let linkStr = _linkStr;\n if (getConfig().securityLevel !== 'loose') {\n linkStr = sanitizeUrl(_linkStr);\n }\n ids.split(',').forEach(function (id) {\n let rawTask = findTaskById(id);\n if (rawTask !== undefined) {\n pushFun(id, () => {\n window.open(linkStr, '_self');\n });\n links.set(id, linkStr);\n }\n });\n setClass(ids, 'clickable');\n};\n\n/**\n * Called by parser when a special node is found, e.g. a clickable element.\n *\n * @param ids Comma separated list of ids\n * @param className Class to add\n */\nexport const setClass = function (ids, className) {\n ids.split(',').forEach(function (id) {\n let rawTask = findTaskById(id);\n if (rawTask !== undefined) {\n rawTask.classes.push(className);\n }\n });\n};\n\nconst setClickFun = function (id, functionName, functionArgs) {\n if (getConfig().securityLevel !== 'loose') {\n return;\n }\n if (functionName === undefined) {\n return;\n }\n\n let argList = [];\n if (typeof functionArgs === 'string') {\n /* Splits functionArgs by ',', ignoring all ',' in double quoted strings */\n argList = functionArgs.split(/,(?=(?:(?:[^\"]*\"){2})*[^\"]*$)/);\n for (let i = 0; i < argList.length; i++) {\n let item = argList[i].trim();\n /* Removes all double quotes at the start and end of an argument */\n /* This preserves all starting and ending whitespace inside */\n if (item.startsWith('\"') && item.endsWith('\"')) {\n item = item.substr(1, item.length - 2);\n }\n argList[i] = item;\n }\n }\n\n /* if no arguments passed into callback, default to passing in id */\n if (argList.length === 0) {\n argList.push(id);\n }\n\n let rawTask = findTaskById(id);\n if (rawTask !== undefined) {\n pushFun(id, () => {\n utils.runFunc(functionName, ...argList);\n });\n }\n};\n\n/**\n * The callbackFunction is executed in a click event bound to the task with the specified id or the\n * task's assigned text\n *\n * @param id The task's id\n * @param callbackFunction A function to be executed when clicked on the task or the task's text\n */\nconst pushFun = function (id, callbackFunction) {\n funs.push(\n function () {\n // const elem = d3.select(element).select(`[id=\"${id}\"]`)\n const elem = document.querySelector(`[id=\"${id}\"]`);\n if (elem !== null) {\n elem.addEventListener('click', function () {\n callbackFunction();\n });\n }\n },\n function () {\n // const elem = d3.select(element).select(`[id=\"${id}-text\"]`)\n const elem = document.querySelector(`[id=\"${id}-text\"]`);\n if (elem !== null) {\n elem.addEventListener('click', function () {\n callbackFunction();\n });\n }\n }\n );\n};\n\n/**\n * Called by parser when a click definition is found. Registers an event handler.\n *\n * @param ids Comma separated list of ids\n * @param functionName Function to be called on click\n * @param functionArgs Function args the function should be called with\n */\nexport const setClickEvent = function (ids, functionName, functionArgs) {\n ids.split(',').forEach(function (id) {\n setClickFun(id, functionName, functionArgs);\n });\n setClass(ids, 'clickable');\n};\n\n/**\n * Binds all functions previously added to fun (specified through click) to the element\n *\n * @param element\n */\nexport const bindFunctions = function (element) {\n funs.forEach(function (fun) {\n fun(element);\n })