From 4c30e03f1ea1a26292a248794b207e596615593e Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Mon, 18 Jul 2022 16:00:03 +0200 Subject: [PATCH] Using diagram api to add gitGraph --- cypress/platform/knsv.html | 5 +- docs/Setup.md | 69 ++- src/Diagram.js | 218 ++------ src/assignWithDepth.js | 74 +++ src/config.js | 2 +- src/diagram-api/detectType.js | 100 ++++ src/diagram-api/diagram-orchestration.js | 31 ++ src/diagram-api/diagramAPI.js | 172 +++++- src/diagrams/c4/c4Renderer.js | 9 +- src/diagrams/flowchart/flowRenderer.spec.js | 1 - src/diagrams/git/gitGraphDetector.js | 8 + src/diagrams/mindmap/info.spc.js | 14 + src/diagrams/mindmap/infoDb.js | 34 ++ src/diagrams/mindmap/infoRenderer.js | 59 ++ src/diagrams/mindmap/mindamapDetector.js | 8 + src/diagrams/mindmap/parser/mindamap.jison | 48 ++ src/diagrams/mindmap/styles.js | 3 + src/diagrams/sequence/sequenceDb.js | 9 +- src/diagrams/sequence/sequenceDiagram.spec.js | 523 +++++++++--------- src/diagrams/sequence/sequenceRenderer.js | 3 +- src/diagrams/user-journey/journeyRenderer.js | 1 - src/mermaid.js | 2 +- src/mermaidAPI.js | 49 +- src/mermaidAPI.spec.js | 2 +- src/utils.js | 160 +----- src/utils.spec.js | 43 +- test.js | 5 + 27 files changed, 946 insertions(+), 706 deletions(-) create mode 100644 src/assignWithDepth.js create mode 100644 src/diagram-api/detectType.js create mode 100644 src/diagram-api/diagram-orchestration.js create mode 100644 src/diagrams/git/gitGraphDetector.js create mode 100644 src/diagrams/mindmap/info.spc.js create mode 100644 src/diagrams/mindmap/infoDb.js create mode 100644 src/diagrams/mindmap/infoRenderer.js create mode 100644 src/diagrams/mindmap/mindamapDetector.js create mode 100644 src/diagrams/mindmap/parser/mindamap.jison create mode 100644 src/diagrams/mindmap/styles.js create mode 100644 test.js diff --git a/cypress/platform/knsv.html b/cypress/platform/knsv.html index 8bc9f88e22..0632913e4b 100644 --- a/cypress/platform/knsv.html +++ b/cypress/platform/knsv.html @@ -64,7 +64,7 @@ commit commit -
+
sequenceDiagram title: My Sequence Diagram Title accTitle: My Acc Sequence Diagram @@ -283,6 +283,9 @@ class: { // defaultRenderer: 'dagre-d3', htmlLabels: true, + }, + sequence: { + mirrorActors: false, }, // gantt: { axisFormat: '%m/%d/%Y' }, // sequence: { diff --git a/docs/Setup.md b/docs/Setup.md index 04026f5d88..4a3575d2cf 100644 --- a/docs/Setup.md +++ b/docs/Setup.md @@ -1401,6 +1401,15 @@ This sets the auto-wrap padding for the diagram (sides only) **Notes:** Default value: 0. +## parse + +### Parameters + +- `text` +- `dia` + +Returns **any** + ## setSiteConfig ## setSiteConfig @@ -1420,14 +1429,6 @@ function _Default value: At default, will mirror Global Config_ Returns **[object][5]** The siteConfig -## parse - -### Parameters - -- `text` - -Returns **any** - ## getSiteConfig ## getSiteConfig @@ -1485,30 +1486,6 @@ options in-place - `options` **any** The potential setConfig parameter -## addDirective - -Pushes in a directive to the configuration - -### Parameters - -- `directive` **[object][5]** The directive to push in - -## reset - -## reset - -| Function | Description | Type | Required | Values | -| -------- | ---------------------------- | ----------- | -------- | ------ | -| reset | Resets currentConfig to conf | Put Request | Required | None | - -## conf - -| Parameter | Description | Type | Required | Values | -| --------- | -------------------------------------------------------------- | ---------- | -------- | -------------------------------------------- | -| conf | base set of values, which currentConfig could be **reset** to. | Dictionary | Required | Any Values, with respect to the secure Array | - -**Notes**: (default: current siteConfig ) (optional, default `getSiteConfig()`) - ## render Function that renders an svg with a graph from a chart definition. Usage example below. @@ -1537,15 +1514,35 @@ $(function () { Returns **any** -## updateRendererConfigs +## addDirective + +Pushes in a directive to the configuration ### Parameters -- `conf` **any** +- `directive` **[object][5]** The directive to push in -## reinitialize +## reset + +## reset -To be removed +| Function | Description | Type | Required | Values | +| -------- | ---------------------------- | ----------- | -------- | ------ | +| reset | Resets currentConfig to conf | Put Request | Required | None | + +## conf + +| Parameter | Description | Type | Required | Values | +| --------- | -------------------------------------------------------------- | ---------- | -------- | -------------------------------------------- | +| conf | base set of values, which currentConfig could be **reset** to. | Dictionary | Required | Any Values, with respect to the secure Array | + +**Notes**: (default: current siteConfig ) (optional, default `getSiteConfig()`) + +## updateRendererConfigs + +### Parameters + +- `conf` **any** ## initialize diff --git a/src/Diagram.js b/src/Diagram.js index b1fa1dc412..a87ed42fb5 100644 --- a/src/Diagram.js +++ b/src/Diagram.js @@ -1,191 +1,32 @@ -import c4Db from './diagrams/c4/c4Db'; -import c4Renderer from './diagrams/c4/c4Renderer'; -import c4Parser from './diagrams/c4/parser/c4Diagram'; -import classDb from './diagrams/class/classDb'; -import classRenderer from './diagrams/class/classRenderer'; -import classRendererV2 from './diagrams/class/classRenderer-v2'; -import classParser from './diagrams/class/parser/classDiagram'; -import erDb from './diagrams/er/erDb'; -import erRenderer from './diagrams/er/erRenderer'; -import erParser from './diagrams/er/parser/erDiagram'; -import flowDb from './diagrams/flowchart/flowDb'; -import flowRenderer from './diagrams/flowchart/flowRenderer'; -import flowRendererV2 from './diagrams/flowchart/flowRenderer-v2'; -import flowParser from './diagrams/flowchart/parser/flow'; -import ganttDb from './diagrams/gantt/ganttDb'; -import ganttRenderer from './diagrams/gantt/ganttRenderer'; -import ganttParser from './diagrams/gantt/parser/gantt'; -import gitGraphAst from './diagrams/git/gitGraphAst'; -import gitGraphRenderer from './diagrams/git/gitGraphRenderer'; -import gitGraphParser from './diagrams/git/parser/gitGraph'; -import infoDb from './diagrams/info/infoDb'; -import infoRenderer from './diagrams/info/infoRenderer'; -import infoParser from './diagrams/info/parser/info'; -import pieParser from './diagrams/pie/parser/pie'; -import pieDb from './diagrams/pie/pieDb'; -import pieRenderer from './diagrams/pie/pieRenderer'; -import requirementParser from './diagrams/requirement/parser/requirementDiagram'; -import requirementDb from './diagrams/requirement/requirementDb'; -import requirementRenderer from './diagrams/requirement/requirementRenderer'; -import sequenceParser from './diagrams/sequence/parser/sequenceDiagram'; -import sequenceDb from './diagrams/sequence/sequenceDb'; -import sequenceRenderer from './diagrams/sequence/sequenceRenderer'; -import stateParser from './diagrams/state/parser/stateDiagram'; -import stateDb from './diagrams/state/stateDb'; -import stateRenderer from './diagrams/state/stateRenderer'; -import stateRendererV2 from './diagrams/state/stateRenderer-v2'; -import journeyDb from './diagrams/user-journey/journeyDb'; -import journeyRenderer from './diagrams/user-journey/journeyRenderer'; -import journeyParser from './diagrams/user-journey/parser/journey'; import utils from './utils'; import * as configApi from './config'; import { log } from './logger'; - +import { getDiagrams } from './diagram-api/diagramAPI'; +import detectType from './diagram-api/detectType'; class Diagram { type = 'graph'; parser; renderer; db; constructor(txt) { + const diagrams = getDiagrams(); const cnf = configApi.getConfig(); this.txt = txt; - this.type = utils.detectType(txt, cnf); + this.type = detectType(txt, cnf); log.debug('Type ' + this.type); - switch (this.type) { - case 'c4': - this.parser = c4Parser; - this.parser.parser.yy = c4Db; - this.db = c4Db; - this.renderer = c4Renderer; - this.renderer.setConf(cnf.c4); - break; - case 'gitGraph': - this.parser = gitGraphParser; - this.parser.parser.yy = gitGraphAst; - this.db = gitGraphAst; - this.renderer = gitGraphRenderer; - this.txt = this.txt + '\n'; - break; - case 'flowchart': - flowRenderer.setConf(cnf.flowchart); - cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - flowDb.clear(); - flowDb.setGen('gen-1'); - this.parser = flowParser; - this.parser.parser.yy = flowDb; - this.db = flowDb; - this.renderer = flowRenderer; - break; - case 'flowchart-v2': - flowRendererV2.setConf(cnf.flowchart); - cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - flowDb.clear(); - flowDb.setGen('gen-2'); - this.parser = flowParser; - this.parser.parser.yy = flowDb; - this.db = flowDb; - this.renderer = flowRendererV2; - break; - case 'sequenceDiagram': - case 'sequence': - cnf.sequence.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - if (cnf.sequenceDiagram) { - // backwards compatibility - sequenceRenderer.setConf(Object.assign(cnf.sequence, cnf.sequenceDiagram)); - console.error( - '`mermaid config.sequenceDiagram` has been renamed to `config.sequence`. Please update your mermaid config.' - ); - } - this.parser = sequenceParser; - this.parser.parser.yy = sequenceDb; - this.db = sequenceDb; - this.db.setWrap(cnf.wrap); - this.renderer = sequenceRenderer; - this.renderer.setConf(cnf.sequence); - this.txt = this.txt + '\n'; - break; - case 'gantt': - cnf.gantt.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - this.parser = ganttParser; - this.parser.parser.yy = ganttDb; - this.db = ganttDb; - this.renderer = ganttRenderer; - ganttRenderer.setConf(cnf.gantt); - break; - case 'class': - cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - this.parser = classParser; - this.parser.parser.yy = classDb; - this.db = classDb; - this.db.clear(); - this.renderer = classRenderer; - break; - case 'classDiagram': - cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - this.parser = classParser; - this.parser.parser.yy = classDb; - this.db = classDb; - this.db.clear(); - this.renderer = classRendererV2; - break; - case 'state': - cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - this.parser = stateParser; - this.parser.parser.yy = stateDb; - this.db = stateDb; - this.db.clear(); - this.renderer = stateRenderer; - break; - case 'stateDiagram': - cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - this.parser = stateParser; - this.parser.parser.yy = stateDb; - this.db = stateDb; - this.db.clear(); - this.renderer = stateRendererV2; - break; - case 'info': - log.debug('info info info'); - this.parser = infoParser; - this.parser.parser.yy = infoDb; - this.db = infoDb; - this.renderer = infoRenderer; - break; - case 'pie': - log.debug('pie'); - this.parser = pieParser; - this.parser.parser.yy = pieDb; - this.db = pieDb; - this.renderer = pieRenderer; - break; - case 'er': - log.debug('er'); - this.parser = erParser; - this.parser.parser.yy = erDb; - this.db = erDb; - this.renderer = erRenderer; - break; - case 'journey': - log.debug('Journey'); - journeyRenderer.setConf(cnf.journey); - this.parser = journeyParser; - this.parser.parser.yy = journeyDb; - this.db = journeyDb; - this.db.clear(); - this.renderer = journeyRenderer; - break; - case 'requirement': - case 'requirementDiagram': - log.debug('RequirementDiagram'); - this.parser = requirementParser; - this.parser.parser.yy = requirementDb; - this.db = requirementDb; - this.renderer = requirementRenderer; - break; - default: - log.error('Unkown graphtype'); - throw new Error('Unkown graphtype'); + + // console.log('this.type', this.type, diagrams[this.type]); + // Setup diagram + this.db = diagrams[this.type].db; + this.renderer = diagrams[this.type].renderer; + this.parser = diagrams[this.type].parser; + this.parser.parser.yy = this.db; + if (typeof diagrams[this.type].init === 'function') { + diagrams[this.type].init(cnf); + log.debug('Initialized diagram ' + this.type, cnf); } + this.txt = this.txt + '\n'; + this.parser.parser.yy.graphType = this.type; this.parser.parser.yy.parseError = (str, hash) => { const error = { str, hash }; @@ -193,6 +34,33 @@ class Diagram { }; this.parser.parse(this.txt); } + parse(text) { + var parseEncounteredException = false; + try { + text = text + '\n'; + this.db.clear(); + + this.parser.parse(text); + } catch (error) { + parseEncounteredException = true; + // Is this the correct way to access mermiad's parseError() + // method ? (or global.mermaid.parseError()) ? + if (global.mermaid.parseError) { + if (error.str != undefined) { + // handle case where error string and hash were + // wrapped in object like`const error = { str, hash };` + global.mermaid.parseError(error.str, error.hash); + } else { + // assume it is just error string and pass it on + global.mermaid.parseError(error); + } + } else { + // No mermaid.parseError() handler defined, so re-throw it + throw error; + } + } + return !parseEncounteredException; + } getParser() { return this.parser; } diff --git a/src/assignWithDepth.js b/src/assignWithDepth.js new file mode 100644 index 0000000000..a74c479457 --- /dev/null +++ b/src/assignWithDepth.js @@ -0,0 +1,74 @@ +/** + * @function assignWithDepth Extends the functionality of {@link ObjectConstructor.assign} with the + * ability to merge arbitrary-depth objects For each key in src with path `k` (recursively) + * performs an Object.assign(dst[`k`], src[`k`]) with a slight change from the typical handling of + * undefined for dst[`k`]: instead of raising an error, dst[`k`] is auto-initialized to {} and + * effectively merged with src[`k`]

Additionally, dissimilar types will not clobber unless the + * config.clobber parameter === true. Example: + * + * ```js + * let config_0 = { foo: { bar: 'bar' }, bar: 'foo' }; + * let config_1 = { foo: 'foo', bar: 'bar' }; + * let result = assignWithDepth(config_0, config_1); + * console.log(result); + * //-> result: { foo: { bar: 'bar' }, bar: 'bar' } + * ``` + * + * Traditional Object.assign would have clobbered foo in config_0 with foo in config_1. If src is a + * destructured array of objects and dst is not an array, assignWithDepth will apply each element + * of src to dst in order. + * @param dst + * @param src + * @param config + * @param dst + * @param src + * @param config + * @param dst + * @param src + * @param config + * @param {any} dst - The destination of the merge + * @param {any} src - The source object(s) to merge into destination + * @param {{ depth: number; clobber: boolean }} [config={ depth: 2, clobber: false }] - Depth: depth + * to traverse within src and dst for merging - clobber: should dissimilar types clobber (default: + * { depth: 2, clobber: false }). Default is `{ depth: 2, clobber: false }` + * @returns {any} + */ +const assignWithDepth = function (dst, src, config) { + const { depth, clobber } = Object.assign({ depth: 2, clobber: false }, config); + if (Array.isArray(src) && !Array.isArray(dst)) { + src.forEach((s) => assignWithDepth(dst, s, config)); + return dst; + } else if (Array.isArray(src) && Array.isArray(dst)) { + src.forEach((s) => { + if (dst.indexOf(s) === -1) { + dst.push(s); + } + }); + return dst; + } + if (typeof dst === 'undefined' || depth <= 0) { + if (dst !== undefined && dst !== null && typeof dst === 'object' && typeof src === 'object') { + return Object.assign(dst, src); + } else { + return src; + } + } + if (typeof src !== 'undefined' && typeof dst === 'object' && typeof src === 'object') { + Object.keys(src).forEach((key) => { + if ( + typeof src[key] === 'object' && + (dst[key] === undefined || typeof dst[key] === 'object') + ) { + if (dst[key] === undefined) { + dst[key] = Array.isArray(src[key]) ? [] : {}; + } + dst[key] = assignWithDepth(dst[key], src[key], { depth: depth - 1, clobber }); + } else if (clobber || (typeof dst[key] !== 'object' && typeof src[key] !== 'object')) { + dst[key] = src[key]; + } + }); + } + return dst; +}; + +export default assignWithDepth; diff --git a/src/config.js b/src/config.js index f438318c7c..59c6c18cba 100644 --- a/src/config.js +++ b/src/config.js @@ -1,4 +1,4 @@ -import { assignWithDepth } from './utils'; +import assignWithDepth from './assignWithDepth'; import { log } from './logger'; import theme from './themes'; import config from './defaultConfig'; diff --git a/src/diagram-api/detectType.js b/src/diagram-api/detectType.js new file mode 100644 index 0000000000..a5f074e3e1 --- /dev/null +++ b/src/diagram-api/detectType.js @@ -0,0 +1,100 @@ +const directive = + /[%]{2}[{]\s*(?:(?:(\w+)\s*:|(\w+))\s*(?:(?:(\w+))|((?:(?![}][%]{2}).|\r?\n)*))?\s*)(?:[}][%]{2})?/gi; +const anyComment = /\s*%%.*\n/gm; +const detectors = {}; +/** + * @function detectType Detects the type of the graph text. Takes into consideration the possible + * existence of an %%init directive + * + * ```mermaid + * %%{initialize: {"startOnLoad": true, logLevel: "fatal" }}%% + * graph LR + * a-->b + * b-->c + * c-->d + * d-->e + * e-->f + * f-->g + * g-->h + * ``` + * @param {string} text The text defining the graph + * @param {{ + * class: { defaultRenderer: string } | undefined; + * state: { defaultRenderer: string } | undefined; + * flowchart: { defaultRenderer: string } | undefined; + * }} [cnf] + * @returns {string} A graph definition key + */ +const detectType = function (text, cnf) { + text = text.replace(directive, '').replace(anyComment, '\n'); + if (text.match(/^\s*C4Context|C4Container|C4Component|C4Dynamic|C4Deployment/)) { + return 'c4'; + } + + if (text.match(/^\s*sequenceDiagram/)) { + return 'sequence'; + } + + if (text.match(/^\s*gantt/)) { + return 'gantt'; + } + if (text.match(/^\s*classDiagram-v2/)) { + return 'classDiagram'; + } + if (text.match(/^\s*classDiagram/)) { + if (cnf && cnf.class && cnf.class.defaultRenderer === 'dagre-wrapper') return 'classDiagram'; + return 'class'; + } + + if (text.match(/^\s*stateDiagram-v2/)) { + return 'stateDiagram'; + } + + if (text.match(/^\s*stateDiagram/)) { + if (cnf && cnf.class && cnf.state.defaultRenderer === 'dagre-wrapper') return 'stateDiagram'; + return 'state'; + } + + // if (text.match(/^\s*gitGraph/)) { + // return 'gitGraph'; + // } + if (text.match(/^\s*flowchart/)) { + return 'flowchart-v2'; + } + + if (text.match(/^\s*info/)) { + return 'info'; + } + if (text.match(/^\s*pie/)) { + return 'pie'; + } + + if (text.match(/^\s*erDiagram/)) { + return 'er'; + } + + if (text.match(/^\s*journey/)) { + return 'journey'; + } + + if (text.match(/^\s*requirement/) || text.match(/^\s*requirementDiagram/)) { + return 'requirement'; + } + if (cnf && cnf.flowchart && cnf.flowchart.defaultRenderer === 'dagre-wrapper') + return 'flowchart-v2'; + const k = Object.keys(detectors); + for (let i = 0; i < k.length; i++) { + const key = k[i]; + const dia = detectors[key]; + if (dia && dia.detector(text)) { + return key; + } + } + return 'flowchart'; +}; +export const addDetector = (key, detector) => { + detectors[key] = { + detector, + }; +}; +export default detectType; diff --git a/src/diagram-api/diagram-orchestration.js b/src/diagram-api/diagram-orchestration.js new file mode 100644 index 0000000000..51f1c43db9 --- /dev/null +++ b/src/diagram-api/diagram-orchestration.js @@ -0,0 +1,31 @@ +import { registerDiagram } from './diagramAPI.js'; +// import mindmapDb from '../diagrams/mindmap/mindmapDb'; +// import mindmapRenderer from '../diagrams/mindmap/mindmapRenderer'; +// import mindmapParser from '../diagrams/mindmap/parser/mindmapDiagram'; +// import mindmapDetector from '../diagrams/mindmap/mindmapDetector'; + +import gitGraphDb from '../diagrams/git/gitGraphAst'; +import gitGraphRenderer from '../diagrams/git/gitGraphRenderer'; +import gitGraphParser from '../diagrams/git/parser/gitGraph'; +import gitGraphDetector from '../diagrams/git/gitGraphDetector'; + +// Register mindmap and other built-in diagrams +// registerDiagram( +// 'mindmap', +// mindmapParser, +// mindmapDb, +// mindmapRenderer, +// undefined, +// mindmapRenderer, +// mindmapDetector +// ); +registerDiagram( + 'gitGraph', + gitGraphParser, + gitGraphDb, + gitGraphRenderer, + undefined, + gitGraphDetector +); +const apa = { apa: 1 }; +export default apa; diff --git a/src/diagram-api/diagramAPI.js b/src/diagram-api/diagramAPI.js index a695de5bfa..176a2bef9d 100644 --- a/src/diagram-api/diagramAPI.js +++ b/src/diagram-api/diagramAPI.js @@ -1,9 +1,175 @@ -const diagrams = {}; +import c4Db from '../diagrams/c4/c4Db'; +import c4Renderer from '../diagrams/c4/c4Renderer'; +import c4Parser from '../diagrams/c4/parser/c4Diagram'; +import classDb from '../diagrams/class/classDb'; +import classRenderer from '../diagrams/class/classRenderer'; +import classRendererV2 from '../diagrams/class/classRenderer-v2'; +import classParser from '../diagrams/class/parser/classDiagram'; +import erDb from '../diagrams/er/erDb'; +import erRenderer from '../diagrams/er/erRenderer'; +import erParser from '../diagrams/er/parser/erDiagram'; +import flowDb from '../diagrams/flowchart/flowDb'; +import flowRenderer from '../diagrams/flowchart/flowRenderer'; +import flowRendererV2 from '../diagrams/flowchart/flowRenderer-v2'; +import flowParser from '../diagrams/flowchart/parser/flow'; +import ganttDb from '../diagrams/gantt/ganttDb'; +import ganttRenderer from '../diagrams/gantt/ganttRenderer'; +import ganttParser from '../diagrams/gantt/parser/gantt'; +import infoDb from '../diagrams/info/infoDb'; +import infoRenderer from '../diagrams/info/infoRenderer'; +import infoParser from '../diagrams/info/parser/info'; +import pieParser from '../diagrams/pie/parser/pie'; +import pieDb from '../diagrams/pie/pieDb'; +import pieRenderer from '../diagrams/pie/pieRenderer'; +import requirementParser from '../diagrams/requirement/parser/requirementDiagram'; +import requirementDb from '../diagrams/requirement/requirementDb'; +import requirementRenderer from '../diagrams/requirement/requirementRenderer'; +import sequenceParser from '../diagrams/sequence/parser/sequenceDiagram'; +import sequenceDb from '../diagrams/sequence/sequenceDb'; +import sequenceRenderer from '../diagrams/sequence/sequenceRenderer'; +import stateParser from '../diagrams/state/parser/stateDiagram'; +import stateDb from '../diagrams/state/stateDb'; +import stateRenderer from '../diagrams/state/stateRenderer'; +import stateRendererV2 from '../diagrams/state/stateRenderer-v2'; +import journeyDb from '../diagrams/user-journey/journeyDb'; +import journeyRenderer from '../diagrams/user-journey/journeyRenderer'; +import journeyParser from '../diagrams/user-journey/parser/journey'; +import { addDetector } from './detectType'; -export const registerDiagram = (id, parser, identifier, renderer) => { - diagrams[id] = { parser, identifier, renderer }; +const diagrams = { + c4: { + db: c4Db, + renderer: c4Renderer, + parser: c4Parser, + init: (cnf) => { + c4Renderer.setConf(cnf.c4); + }, + }, + class: { + db: classDb, + renderer: classRenderer, + parser: classParser, + init: (cnf) => { + cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + classDb.clear(); + }, + }, + classDiagram: { + db: classDb, + renderer: classRendererV2, + parser: classParser, + init: (cnf) => { + cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + classDb.clear(); + }, + }, + er: { + db: erDb, + renderer: erRenderer, + parser: erParser, + }, + flowchart: { + db: flowDb, + renderer: flowRenderer, + parser: flowParser, + init: (cnf) => { + flowRenderer.setConf(cnf.flowchart); + cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + flowDb.clear(); + flowDb.setGen('gen-1'); + }, + }, + flowchartV2: { + db: flowDb, + renderer: flowRendererV2, + parser: flowParser, + init: (cnf) => { + flowRendererV2.setConf(cnf.flowchart); + cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + flowDb.clear(); + flowDb.setGen('gen-2'); + }, + }, + gantt: { + db: ganttDb, + renderer: ganttRenderer, + parser: ganttParser, + init: (cnf) => { + ganttRenderer.setConf(cnf.gantt); + }, + }, + // git: { + // db: gitGraphAst, + // renderer: gitGraphRenderer, + // parser: gitGraphParser, + // }, + info: { + db: infoDb, + renderer: infoRenderer, + parser: infoParser, + }, + pie: { + db: pieDb, + renderer: pieRenderer, + parser: pieParser, + }, + requirement: { + db: requirementDb, + renderer: requirementRenderer, + parser: requirementParser, + }, + sequence: { + db: sequenceDb, + renderer: sequenceRenderer, + parser: sequenceParser, + init: (cnf) => { + cnf.sequence.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + if (cnf.sequenceDiagram) { + // backwards compatibility + sequenceRenderer.setConf(Object.assign(cnf.sequence, cnf.sequenceDiagram)); + console.error( + '`mermaid config.sequenceDiagram` has been renamed to `config.sequence`. Please update your mermaid config.' + ); + } + sequenceDb.setWrap(cnf.wrap); + sequenceRenderer.setConf(cnf.sequence); + }, + }, + state: { + db: stateDb, + renderer: stateRenderer, + parser: stateParser, + init: (cnf) => { + cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + stateDb.clear(); + }, + }, + stateDiagram: { + db: stateDb, + renderer: stateRendererV2, + parser: stateParser, + init: (cnf) => { + cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + stateDb.clear(); + }, + }, + journey: { + db: journeyDb, + renderer: journeyRenderer, + parser: journeyParser, + init: (cnf) => { + journeyRenderer.setConf(cnf.journey); + journeyDb.clear(); + }, + }, +}; +// console.log(sequenceDb); +export const registerDiagram = (id, parser, db, renderer, init, detector) => { + diagrams[id] = { parser, db, renderer, init }; + addDetector(id, detector); }; export const getDiagrams = () => { + // console.log('diagrams', diagrams); return diagrams; }; diff --git a/src/diagrams/c4/c4Renderer.js b/src/diagrams/c4/c4Renderer.js index acd39fa477..6af59bb928 100644 --- a/src/diagrams/c4/c4Renderer.js +++ b/src/diagrams/c4/c4Renderer.js @@ -5,13 +5,8 @@ import { parser } from './parser/c4Diagram'; import common from '../common/common'; import c4Db from './c4Db'; import * as configApi from '../../config'; -import utils, { - wrapLabel, - calculateTextWidth, - calculateTextHeight, - assignWithDepth, - configureSvgSize, -} from '../../utils'; +import assignWithDepth from '../../assignWithDepth'; +import { wrapLabel, calculateTextWidth, calculateTextHeight, configureSvgSize } from '../../utils'; import addSVGAccessibilityFields from '../../accessibility'; let globalBoundaryMaxX = 0, diff --git a/src/diagrams/flowchart/flowRenderer.spec.js b/src/diagrams/flowchart/flowRenderer.spec.js index 356b3688a9..4e1ce10193 100644 --- a/src/diagrams/flowchart/flowRenderer.spec.js +++ b/src/diagrams/flowchart/flowRenderer.spec.js @@ -1,6 +1,5 @@ import { addVertices, addEdges } from './flowRenderer'; import { setConfig } from '../../config'; -import Diagram from '../../Diagram'; setConfig({ flowchart: { diff --git a/src/diagrams/git/gitGraphDetector.js b/src/diagrams/git/gitGraphDetector.js new file mode 100644 index 0000000000..3707a33047 --- /dev/null +++ b/src/diagrams/git/gitGraphDetector.js @@ -0,0 +1,8 @@ +const detector = (txt) => { + if (txt.match(/^\s*gitGraph/)) { + return 'gitGraph'; + } + return null; +}; + +export default detector; diff --git a/src/diagrams/mindmap/info.spc.js b/src/diagrams/mindmap/info.spc.js new file mode 100644 index 0000000000..69a969fb13 --- /dev/null +++ b/src/diagrams/mindmap/info.spc.js @@ -0,0 +1,14 @@ +describe('when parsing an info graph it', function () { + var ex; + beforeEach(function () { + ex = require('./parser/info').parser; + ex.yy = require('./infoDb'); + }); + + it('should handle an info definition', function () { + var str = `info + showInfo`; + + ex.parse(str); + }); +}); diff --git a/src/diagrams/mindmap/infoDb.js b/src/diagrams/mindmap/infoDb.js new file mode 100644 index 0000000000..5a324fbb45 --- /dev/null +++ b/src/diagrams/mindmap/infoDb.js @@ -0,0 +1,34 @@ +/** Created by knut on 15-01-14. */ +import { log } from '../../logger'; + +var message = ''; +var info = false; + +export const setMessage = (txt) => { + log.debug('Setting message to: ' + txt); + message = txt; +}; + +export const getMessage = () => { + return message; +}; + +export const setInfo = (inf) => { + info = inf; +}; + +export const getInfo = () => { + return info; +}; + +// export const parseError = (err, hash) => { +// global.mermaidAPI.parseError(err, hash) +// } + +export default { + setMessage, + getMessage, + setInfo, + getInfo, + // parseError +}; diff --git a/src/diagrams/mindmap/infoRenderer.js b/src/diagrams/mindmap/infoRenderer.js new file mode 100644 index 0000000000..cbe3c52f8f --- /dev/null +++ b/src/diagrams/mindmap/infoRenderer.js @@ -0,0 +1,59 @@ +/** Created by knut on 14-12-11. */ +import { select } from 'd3'; +import { log } from '../../logger'; +import { getConfig } from '../../config'; + +/** + * Draws a an info picture in the tag with id: id based on the graph definition in text. + * + * @param {any} text + * @param {any} id + * @param {any} version + * @param diagObj + */ +export const draw = (text, id, version, diagObj) => { + try { + // const parser = infoParser.parser; + // parser.yy = db; + log.debug('Renering info diagram\n' + text); + + const securityLevel = getConfig().securityLevel; + // Handle root and Document for when rendering in sanbox mode + let sandboxElement; + if (securityLevel === 'sandbox') { + sandboxElement = select('#i' + id); + } + const root = + securityLevel === 'sandbox' + ? select(sandboxElement.nodes()[0].contentDocument.body) + : select('body'); + const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; + + // Parse the graph definition + // parser.parse(text); + // log.debug('Parsed info diagram'); + // Fetch the default direction, use TD if none was found + const svg = root.select('#' + id); + + const g = svg.append('g'); + + g.append('text') // text label for the x axis + .attr('x', 100) + .attr('y', 40) + .attr('class', 'version') + .attr('font-size', '32px') + .style('text-anchor', 'middle') + .text('v ' + version); + + svg.attr('height', 100); + svg.attr('width', 400); + // svg.attr('viewBox', '0 0 300 150'); + } catch (e) { + log.error('Error while rendering info diagram'); + log.error(e.message); + } +}; + +export default { + draw, +}; diff --git a/src/diagrams/mindmap/mindamapDetector.js b/src/diagrams/mindmap/mindamapDetector.js new file mode 100644 index 0000000000..341e3968cf --- /dev/null +++ b/src/diagrams/mindmap/mindamapDetector.js @@ -0,0 +1,8 @@ +const detector = (txt) => { + if (txt.match(/^\s*mindmap/)) { + return 'mindmap'; + } + return null; +}; + +export default detector; diff --git a/src/diagrams/mindmap/parser/mindamap.jison b/src/diagrams/mindmap/parser/mindamap.jison new file mode 100644 index 0000000000..473b63fcfc --- /dev/null +++ b/src/diagrams/mindmap/parser/mindamap.jison @@ -0,0 +1,48 @@ +/** mermaid + * https://knsv.github.io/mermaid + * (c) 2015 Knut Sveidqvist + * MIT license. + */ +%lex + +%options case-insensitive + +%{ + // Pre-lexer code can go here +%} + +%% + +"info" return 'info' ; +[\s\n\r]+ return 'NL' ; +[\s]+ return 'space'; +"showInfo" return 'showInfo'; +<> return 'EOF' ; +. return 'TXT' ; + +/lex + +%start start + +%% /* language grammar */ + +start +// %{ : info document 'EOF' { return yy; } } + : info document 'EOF' { return yy; } + ; + +document + : /* empty */ + | document line + ; + +line + : statement { } + | 'NL' + ; + +statement + : showInfo { yy.setInfo(true); } + ; + +%% diff --git a/src/diagrams/mindmap/styles.js b/src/diagrams/mindmap/styles.js new file mode 100644 index 0000000000..0b0729813d --- /dev/null +++ b/src/diagrams/mindmap/styles.js @@ -0,0 +1,3 @@ +const getStyles = () => ``; + +export default getStyles; diff --git a/src/diagrams/sequence/sequenceDb.js b/src/diagrams/sequence/sequenceDb.js index 7d68c97238..8ae5fe8f10 100644 --- a/src/diagrams/sequence/sequenceDb.js +++ b/src/diagrams/sequence/sequenceDb.js @@ -140,7 +140,14 @@ export const setWrap = function (wrapSetting) { wrapEnabled = wrapSetting; }; -export const autoWrap = () => wrapEnabled; +export const autoWrap = () => { + // if setWrap has been called, use that value, otherwise use the value from the config + // TODO: refactor, always use the config value let setWrap update the config value + if (typeof wrapEnabled !== 'undefined') { + return wrapEnabled; + } + return configApi.getConfig().sequence.wrap; +}; export const clear = function () { actors = {}; diff --git a/src/diagrams/sequence/sequenceDiagram.spec.js b/src/diagrams/sequence/sequenceDiagram.spec.js index 5f77c90291..5f09e0e2d2 100644 --- a/src/diagrams/sequence/sequenceDiagram.spec.js +++ b/src/diagrams/sequence/sequenceDiagram.spec.js @@ -1,9 +1,12 @@ -import sequence from './parser/sequenceDiagram'; -import sequenceDb from './sequenceDb'; +// import sequence from './parser/sequenceDiagram'; +// import sequenceDb from './sequenceDb'; import * as configApi from '../../config'; -import renderer from './sequenceRenderer'; +// import renderer from './sequenceRenderer'; import mermaidAPI from '../../mermaidAPI'; +// import '../../diagram-api/diagramAPI'; import Diagram from '../../Diagram'; + +// console.log('sequenceDiagram', sequenceDb); /** * @param conf * @param key @@ -16,29 +19,33 @@ function addConf(conf, key, value) { return conf; } -const parser = sequence.parser; +// const parser = sequence.parser; +let diagram; describe('when parsing a sequenceDiagram', function () { beforeEach(function () { - parser.yy = sequenceDb; - parser.yy.clear(); + // diagram.db = sequenceDb; + // diagram.db.clear(); + diagram = new Diagram(` +sequenceDiagram +Alice->Bob:Hello Bob, how are you? +Note right of Bob: Bob thinks +Bob-->Alice: I am good thanks!`); + diagram.db.clear(); }); - fit('should handle a sequenceDiagram definition', function () { + it('should handle a sequenceDiagram definition', function () { const str = ` sequenceDiagram Alice->Bob:Hello Bob, how are you? Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`; - // const dia = new Diagram(str); - // console.log('Type = ' + dia.type); - - mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + mermaidAPI.parse(str, diagram); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); actors.Bob.description = 'Bob'; - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(3); expect(messages[0].from).toBe('Alice'); @@ -52,8 +59,8 @@ Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`; mermaidAPI.parse(str); - renderer.draw(str, 'tst'); // needs to be rendered for the correct value of visibility autonumbers - expect(parser.yy.showSequenceNumbers()).toBe(false); + diagram.renderer.draw(str, 'tst', '1.2.3', diagram); // needs to be rendered for the correct value of visibility autonumbers + expect(diagram.db.showSequenceNumbers()).toBe(false); }); it('it should show sequence numbers when autonumber is enabled', function () { const str = ` @@ -64,8 +71,8 @@ Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`; mermaidAPI.parse(str); - renderer.draw(str, 'tst'); // needs to be rendered for the correct value of visibility autonumbers - expect(parser.yy.showSequenceNumbers()).toBe(true); + diagram.renderer.draw(str, 'tst', '1.2.3', diagram); // needs to be rendered for the correct value of visibility autonumbers + expect(diagram.db.showSequenceNumbers()).toBe(true); }); it('it should handle a sequenceDiagram definition with a title:', function () { const str = ` @@ -76,13 +83,13 @@ Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); actors.Bob.description = 'Bob'; - expect(parser.yy.getAccDescription()).toBe(''); - const messages = parser.yy.getMessages(); - const title = parser.yy.getDiagramTitle(); + expect(diagram.db.getAccDescription()).toBe(''); + const messages = diagram.db.getMessages(); + const title = diagram.db.getDiagramTitle(); expect(messages.length).toBe(3); expect(messages[0].from).toBe('Alice'); @@ -99,13 +106,13 @@ Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); actors.Bob.description = 'Bob'; - expect(parser.yy.getAccDescription()).toBe(''); - const messages = parser.yy.getMessages(); - const title = parser.yy.getDiagramTitle(); + expect(diagram.db.getAccDescription()).toBe(''); + const messages = diagram.db.getMessages(); + const title = diagram.db.getDiagramTitle(); expect(messages.length).toBe(3); expect(messages[0].from).toBe('Alice'); @@ -123,10 +130,10 @@ Alice->Bob:Hello Bob, how are you? `; mermaidAPI.parse(str); - expect(parser.yy.getDiagramTitle()).toBe('Diagram Title'); - expect(parser.yy.getAccTitle()).toBe('This is the title'); - expect(parser.yy.getAccDescription()).toBe('Accessibility Description'); - const messages = parser.yy.getMessages(); + expect(diagram.db.getDiagramTitle()).toBe('Diagram Title'); + expect(diagram.db.getAccTitle()).toBe('This is the title'); + expect(diagram.db.getAccDescription()).toBe('Accessibility Description'); + const messages = diagram.db.getMessages(); }); it('it should handle a sequenceDiagram definition with a accessibility title and multiline description (accDescr)', function () { const str = ` @@ -140,9 +147,9 @@ Alice->Bob:Hello Bob, how are you? `; mermaidAPI.parse(str); - expect(parser.yy.getAccTitle()).toBe('This is the title'); - expect(parser.yy.getAccDescription()).toBe('Accessibility\nDescription'); - const messages = parser.yy.getMessages(); + expect(diagram.db.getAccTitle()).toBe('This is the title'); + expect(diagram.db.getAccDescription()).toBe('Accessibility\nDescription'); + const messages = diagram.db.getMessages(); }); it('it should space in actor names', function () { @@ -152,11 +159,11 @@ Alice->Bob:Hello Bob, how are - you? Bob-->Alice: I am good thanks!`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); actors.Bob.description = 'Bob'; - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(2); expect(messages[0].from).toBe('Alice'); @@ -169,11 +176,11 @@ Alice-in-Wonderland->Bob:Hello Bob, how are - you? Bob-->Alice-in-Wonderland:I am good thanks!`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors['Alice-in-Wonderland'].description).toBe('Alice-in-Wonderland'); actors.Bob.description = 'Bob'; - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(2); expect(messages[0].from).toBe('Alice-in-Wonderland'); @@ -189,13 +196,13 @@ B-->A: I am good thanks!`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(Object.keys(actors)).toEqual(['A', 'B']); expect(actors.A.description).toBe('Alice'); expect(actors.B.description).toBe('Bob'); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(2); expect(messages[0].from).toBe('A'); expect(messages[1].from).toBe('B'); @@ -215,7 +222,7 @@ sequenceDiagram mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(Object.keys(actors)).toEqual(['Alice', 'Bob', 'John', 'Mandy', 'Joan']); expect(actors.Alice.description).toBe('Alice2'); expect(actors.Alice.type).toBe('actor'); @@ -223,7 +230,7 @@ sequenceDiagram expect(actors.John.type).toBe('participant'); expect(actors.Joan.type).toBe('participant'); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(5); expect(messages[0].from).toBe('Alice'); expect(messages[4].to).toBe('Joan'); @@ -238,12 +245,12 @@ B-->A: I am good thanks!`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(Object.keys(actors)).toEqual(['A', 'B']); expect(actors.A.description).toBe('Alice'); expect(actors.B.description).toBe('Bob'); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(2); expect(messages[0].from).toBe('A'); expect(messages[1].from).toBe('B'); @@ -254,14 +261,14 @@ sequenceDiagram Alice-xBob:Hello Bob, how are you?`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); expect(actors.Bob.description).toBe('Bob'); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(1); - expect(messages[0].type).toBe(parser.yy.LINETYPE.SOLID_CROSS); + expect(messages[0].type).toBe(diagram.db.LINETYPE.SOLID_CROSS); }); it('it should handle in async dotted messages', function () { const str = ` @@ -269,14 +276,14 @@ sequenceDiagram Alice--xBob:Hello Bob, how are you?`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); expect(actors.Bob.description).toBe('Bob'); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(1); - expect(messages[0].type).toBe(parser.yy.LINETYPE.DOTTED_CROSS); + expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED_CROSS); }); it('it should handle in sync messages', function () { const str = ` @@ -284,14 +291,14 @@ sequenceDiagram Alice-)Bob:Hello Bob, how are you?`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); expect(actors.Bob.description).toBe('Bob'); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(1); - expect(messages[0].type).toBe(parser.yy.LINETYPE.SOLID_POINT); + expect(messages[0].type).toBe(diagram.db.LINETYPE.SOLID_POINT); }); it('it should handle in sync dotted messages', function () { const str = ` @@ -299,14 +306,14 @@ sequenceDiagram Alice--)Bob:Hello Bob, how are you?`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); expect(actors.Bob.description).toBe('Bob'); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(1); - expect(messages[0].type).toBe(parser.yy.LINETYPE.DOTTED_POINT); + expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED_POINT); }); it('it should handle in arrow messages', function () { const str = ` @@ -314,27 +321,27 @@ sequenceDiagram Alice->>Bob:Hello Bob, how are you?`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); expect(actors.Bob.description).toBe('Bob'); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(1); - expect(messages[0].type).toBe(parser.yy.LINETYPE.SOLID); + expect(messages[0].type).toBe(diagram.db.LINETYPE.SOLID); }); it('it should handle in arrow messages', function () { const str = 'sequenceDiagram\n' + 'Alice-->>Bob:Hello Bob, how are you?'; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); expect(actors.Bob.description).toBe('Bob'); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(1); - expect(messages[0].type).toBe(parser.yy.LINETYPE.DOTTED); + expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED); }); it('it should handle actor activation', function () { const str = ` @@ -345,18 +352,18 @@ Bob-->>Alice:Hello Alice, I'm fine and you? deactivate Bob`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); expect(actors.Bob.description).toBe('Bob'); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(4); - expect(messages[0].type).toBe(parser.yy.LINETYPE.DOTTED); - expect(messages[1].type).toBe(parser.yy.LINETYPE.ACTIVE_START); + expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED); + expect(messages[1].type).toBe(diagram.db.LINETYPE.ACTIVE_START); expect(messages[1].from.actor).toBe('Bob'); - expect(messages[2].type).toBe(parser.yy.LINETYPE.DOTTED); - expect(messages[3].type).toBe(parser.yy.LINETYPE.ACTIVE_END); + expect(messages[2].type).toBe(diagram.db.LINETYPE.DOTTED); + expect(messages[3].type).toBe(diagram.db.LINETYPE.ACTIVE_END); expect(messages[3].from.actor).toBe('Bob'); }); it('it should handle actor one line notation activation', function () { @@ -366,18 +373,18 @@ deactivate Bob`; Bob-->>- Alice:Hello Alice, I'm fine and you?`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); expect(actors.Bob.description).toBe('Bob'); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(4); - expect(messages[0].type).toBe(parser.yy.LINETYPE.DOTTED); - expect(messages[1].type).toBe(parser.yy.LINETYPE.ACTIVE_START); + expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED); + expect(messages[1].type).toBe(diagram.db.LINETYPE.ACTIVE_START); expect(messages[1].from.actor).toBe('Bob'); - expect(messages[2].type).toBe(parser.yy.LINETYPE.DOTTED); - expect(messages[3].type).toBe(parser.yy.LINETYPE.ACTIVE_END); + expect(messages[2].type).toBe(diagram.db.LINETYPE.DOTTED); + expect(messages[3].type).toBe(diagram.db.LINETYPE.ACTIVE_END); expect(messages[3].from.actor).toBe('Bob'); }); it('it should handle stacked activations', function () { @@ -389,22 +396,22 @@ deactivate Bob`; Carol->>- Bob:Oh Bob, I'm so happy to be here!`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); expect(actors.Bob.description).toBe('Bob'); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(8); - expect(messages[0].type).toBe(parser.yy.LINETYPE.DOTTED); - expect(messages[1].type).toBe(parser.yy.LINETYPE.ACTIVE_START); + expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED); + expect(messages[1].type).toBe(diagram.db.LINETYPE.ACTIVE_START); expect(messages[1].from.actor).toBe('Bob'); - expect(messages[2].type).toBe(parser.yy.LINETYPE.DOTTED); - expect(messages[3].type).toBe(parser.yy.LINETYPE.ACTIVE_START); + expect(messages[2].type).toBe(diagram.db.LINETYPE.DOTTED); + expect(messages[3].type).toBe(diagram.db.LINETYPE.ACTIVE_START); expect(messages[3].from.actor).toBe('Carol'); - expect(messages[5].type).toBe(parser.yy.LINETYPE.ACTIVE_END); + expect(messages[5].type).toBe(diagram.db.LINETYPE.ACTIVE_END); expect(messages[5].from.actor).toBe('Bob'); - expect(messages[7].type).toBe(parser.yy.LINETYPE.ACTIVE_END); + expect(messages[7].type).toBe(diagram.db.LINETYPE.ACTIVE_END); expect(messages[7].from.actor).toBe('Carol'); }); it('it should handle fail parsing when activating an inactive participant', function () { @@ -442,11 +449,11 @@ deactivate Bob`; Bob-->Alice: I am good thanks!`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); actors.Bob.description = 'Bob'; - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(3); expect(messages[0].from).toBe('Alice'); @@ -463,11 +470,11 @@ deactivate Bob`; `; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); actors.Bob.description = 'Bob'; - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(3); expect(messages[0].from).toBe('Alice'); @@ -478,11 +485,11 @@ deactivate Bob`; sequenceDiagram;Alice->Bob: Hello Bob, how are you?;Note right of Bob: Bob thinks;Bob-->Alice: I am good thanks!;`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); actors.Bob.description = 'Bob'; - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(3); expect(messages[0].from).toBe('Alice'); @@ -498,11 +505,11 @@ Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); actors.Bob.description = 'Bob'; - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(3); expect(messages[0].from).toBe('Alice'); @@ -518,11 +525,11 @@ Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); actors.Bob.description = 'Bob'; - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(3); expect(messages[0].from).toBe('Alice'); @@ -543,11 +550,11 @@ Note right of John: Rational thoughts
prevail... Bob-->John: Jolly good!`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); actors.Bob.description = 'Bob'; - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(8); expect(messages[0].from).toBe('Alice'); @@ -572,13 +579,13 @@ note right of 1: multiline
text mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors['1'].description).toBe('multiline
text'); expect(actors['2'].description).toBe('multiline
text'); expect(actors['3'].description).toBe('multiline
text'); expect(actors['4'].description).toBe('multiline
text'); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[0].message).toBe('multiline
text'); expect(messages[1].message).toBe('multiline
text'); expect(messages[2].message).toBe('multiline
text'); @@ -607,7 +614,7 @@ note right of 1:nowrap: multiline
text mermaidAPI.parse(str); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[0].message).toBe('single-line text'); expect(messages[1].message).toBe('single-line text'); expect(messages[2].message).toBe('single-line text'); @@ -642,7 +649,7 @@ note right of 3:wrap: multiline
text mermaidAPI.parse(str); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[0].message).toBe('single-line text'); expect(messages[1].message).toBe('single-line text'); expect(messages[2].message).toBe('multiline
text'); @@ -663,7 +670,7 @@ note right of 2: single-line text mermaidAPI.parse(str); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[0].message).toBe('single-line text'); expect(messages[1].message).toBe('single-line text'); expect(messages[0].wrap).toBe(false); @@ -678,7 +685,7 @@ Note over Bob: Bob thinks mermaidAPI.parse(str); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[1].from).toBe('Bob'); expect(messages[1].to).toBe('Bob'); }); @@ -692,7 +699,7 @@ Note over Bob,Alice: resolution mermaidAPI.parse(str); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[1].from).toBe('Alice'); expect(messages[1].to).toBe('Bob'); expect(messages[2].from).toBe('Bob'); @@ -711,11 +718,11 @@ Bob-->Alice: I am good thanks! end`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); actors.Bob.description = 'Bob'; - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(5); expect(messages[0].from).toBe('Alice'); @@ -733,16 +740,16 @@ end`; `; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); actors.Bob.description = 'Bob'; - const messages = parser.yy.getMessages(); - expect(messages[1].type).toEqual(parser.yy.LINETYPE.RECT_START); + const messages = diagram.db.getMessages(); + expect(messages[1].type).toEqual(diagram.db.LINETYPE.RECT_START); expect(messages[1].message).toBe('rgb(200, 255, 200)'); - expect(messages[2].type).toEqual(parser.yy.LINETYPE.NOTE); - expect(messages[3].type).toEqual(parser.yy.LINETYPE.DOTTED_OPEN); - expect(messages[4].type).toEqual(parser.yy.LINETYPE.RECT_END); + expect(messages[2].type).toEqual(diagram.db.LINETYPE.NOTE); + expect(messages[3].type).toEqual(diagram.db.LINETYPE.DOTTED_OPEN); + expect(messages[4].type).toEqual(diagram.db.LINETYPE.RECT_END); }); it('it should allow for nested rects', function () { @@ -758,19 +765,19 @@ end`; end `; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); actors.Bob.description = 'Bob'; - const messages = parser.yy.getMessages(); - expect(messages[1].type).toEqual(parser.yy.LINETYPE.RECT_START); + const messages = diagram.db.getMessages(); + expect(messages[1].type).toEqual(diagram.db.LINETYPE.RECT_START); expect(messages[1].message).toBe('rgb(200, 255, 200)'); - expect(messages[2].type).toEqual(parser.yy.LINETYPE.RECT_START); + expect(messages[2].type).toEqual(diagram.db.LINETYPE.RECT_START); expect(messages[2].message).toBe('rgb(0, 0, 0)'); - expect(messages[3].type).toEqual(parser.yy.LINETYPE.NOTE); - expect(messages[4].type).toEqual(parser.yy.LINETYPE.RECT_END); - expect(messages[5].type).toEqual(parser.yy.LINETYPE.DOTTED_OPEN); - expect(messages[6].type).toEqual(parser.yy.LINETYPE.RECT_END); + expect(messages[3].type).toEqual(diagram.db.LINETYPE.NOTE); + expect(messages[4].type).toEqual(diagram.db.LINETYPE.RECT_END); + expect(messages[5].type).toEqual(diagram.db.LINETYPE.DOTTED_OPEN); + expect(messages[6].type).toEqual(diagram.db.LINETYPE.RECT_END); }); it('it should handle opt statements', function () { const str = ` @@ -785,11 +792,11 @@ Bob-->Alice: I am good thanks! end`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); actors.Bob.description = 'Bob'; - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(5); expect(messages[0].from).toBe('Alice'); @@ -810,12 +817,12 @@ Bob-->Alice: Feel sick... end`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); actors.Bob.description = 'Bob'; - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(7); expect(messages[0].from).toBe('Alice'); @@ -837,16 +844,16 @@ else default Bob-->Alice: :-) end`; mermaidAPI.parse(str); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(9); expect(messages[1].from).toBe('Bob'); - expect(messages[2].type).toBe(parser.yy.LINETYPE.ALT_START); + expect(messages[2].type).toBe(diagram.db.LINETYPE.ALT_START); expect(messages[3].from).toBe('Bob'); - expect(messages[4].type).toBe(parser.yy.LINETYPE.ALT_ELSE); + expect(messages[4].type).toBe(diagram.db.LINETYPE.ALT_ELSE); expect(messages[5].from).toBe('Bob'); - expect(messages[6].type).toBe(parser.yy.LINETYPE.ALT_ELSE); + expect(messages[6].type).toBe(diagram.db.LINETYPE.ALT_ELSE); expect(messages[7].from).toBe('Bob'); - expect(messages[8].type).toBe(parser.yy.LINETYPE.ALT_END); + expect(messages[8].type).toBe(diagram.db.LINETYPE.ALT_END); }); it('it should handle critical statements without options', function () { const str = ` @@ -856,17 +863,17 @@ sequenceDiagram end`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Service.description).toBe('Service'); expect(actors.DB.description).toBe('DB'); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(3); - expect(messages[0].type).toBe(parser.yy.LINETYPE.CRITICAL_START); + expect(messages[0].type).toBe(diagram.db.LINETYPE.CRITICAL_START); expect(messages[1].from).toBe('Service'); - expect(messages[2].type).toBe(parser.yy.LINETYPE.CRITICAL_END); + expect(messages[2].type).toBe(diagram.db.LINETYPE.CRITICAL_END); }); it('it should handle critical statements with options', function () { const str = ` @@ -880,21 +887,21 @@ sequenceDiagram end`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Service.description).toBe('Service'); expect(actors.DB.description).toBe('DB'); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(7); - expect(messages[0].type).toBe(parser.yy.LINETYPE.CRITICAL_START); + expect(messages[0].type).toBe(diagram.db.LINETYPE.CRITICAL_START); expect(messages[1].from).toBe('Service'); - expect(messages[2].type).toBe(parser.yy.LINETYPE.CRITICAL_OPTION); + expect(messages[2].type).toBe(diagram.db.LINETYPE.CRITICAL_OPTION); expect(messages[3].from).toBe('Service'); - expect(messages[4].type).toBe(parser.yy.LINETYPE.CRITICAL_OPTION); + expect(messages[4].type).toBe(diagram.db.LINETYPE.CRITICAL_OPTION); expect(messages[5].from).toBe('Service'); - expect(messages[6].type).toBe(parser.yy.LINETYPE.CRITICAL_END); + expect(messages[6].type).toBe(diagram.db.LINETYPE.CRITICAL_END); }); it('it should handle break statements', function () { const str = ` @@ -907,19 +914,19 @@ sequenceDiagram API-->BillingService: Start billing process`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Consumer.description).toBe('Consumer'); expect(actors.API.description).toBe('API'); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(6); expect(messages[0].from).toBe('Consumer'); expect(messages[1].from).toBe('API'); - expect(messages[2].type).toBe(parser.yy.LINETYPE.BREAK_START); + expect(messages[2].type).toBe(diagram.db.LINETYPE.BREAK_START); expect(messages[3].from).toBe('API'); - expect(messages[4].type).toBe(parser.yy.LINETYPE.BREAK_END); + expect(messages[4].type).toBe(diagram.db.LINETYPE.BREAK_END); expect(messages[5].from).toBe('API'); }); it('it should handle par statements a sequenceDiagram', function () { @@ -937,12 +944,12 @@ Bob-->>Alice: It's good! end`; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); expect(actors.Bob.description).toBe('Bob'); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(10); expect(messages[0].message).toBe('Parallel one'); @@ -954,7 +961,7 @@ end`; mermaidAPI.parse(str); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[0].message).toBe('-:<>,'); }); it('it should handle special characters in notes', function () { @@ -965,7 +972,7 @@ Note right of Bob: -:<>,;# comment`; mermaidAPI.parse(str); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[1].message).toBe('-:<>,'); }); it('it should handle special characters in loop', function () { @@ -978,7 +985,7 @@ end`; mermaidAPI.parse(str); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[1].message).toBe('-:<>,'); }); it('it should handle special characters in opt', function () { @@ -991,7 +998,7 @@ end`; mermaidAPI.parse(str); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[1].message).toBe('-:<>,'); }); it('it should handle special characters in alt', function () { @@ -1006,7 +1013,7 @@ end`; mermaidAPI.parse(str); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[1].message).toBe('-:<>,'); expect(messages[3].message).toBe(',<>:-'); }); @@ -1022,7 +1029,7 @@ end`; mermaidAPI.parse(str); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[1].message).toBe('-:<>,'); expect(messages[3].message).toBe(',<>:-'); }); @@ -1036,7 +1043,7 @@ end`; mermaidAPI.parse(str); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[1].message).toBe(''); expect(messages[2].message).toBe('I am good thanks!'); }); @@ -1050,7 +1057,7 @@ end`; mermaidAPI.parse(str); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[1].message).toBe(''); expect(messages[2].message).toBe('I am good thanks!'); }); @@ -1065,7 +1072,7 @@ end`; mermaidAPI.parse(str); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[1].message).toBe(''); expect(messages[2].message).toBe('I am good thanks!'); expect(messages[3].message).toBe(''); @@ -1082,7 +1089,7 @@ end`; mermaidAPI.parse(str); - const messages = parser.yy.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[1].message).toBe(''); expect(messages[2].message).toBe('I am good thanks!'); expect(messages[3].message).toBe(''); @@ -1104,7 +1111,7 @@ link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com `; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.a.links['Repo']).toBe('https://repo.contoso.com/'); expect(actors.b.links['Repo']).toBe(undefined); expect(actors.a.links['Dashboard']).toBe('https://dashboard.contoso.com/'); @@ -1128,7 +1135,7 @@ properties b: {"class": "external-service-actor", "icon": "@computer"} `; mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(actors.a.properties['class']).toBe('internal-service-actor'); expect(actors.b.properties['class']).toBe('external-service-actor'); expect(actors.a.properties['icon']).toBe('@clock'); @@ -1158,48 +1165,48 @@ describe('when checking the bounds in a sequenceDiagram', function () { let conf; beforeEach(function () { mermaidAPI.reset(); - parser.yy = sequenceDb; - parser.yy.clear(); - renderer.bounds.init(); - conf = parser.yy.getConfig(); + // diagram.db = sequenceDb; + // diagram.db.clear(); + diagram.renderer.bounds.init(); + conf = diagram.db.getConfig(); }); it('it should handle a simple bound call', function () { - renderer.bounds.insert(100, 100, 200, 200); + diagram.renderer.bounds.insert(100, 100, 200, 200); - const { bounds } = renderer.bounds.getBounds(); + const { bounds } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(100); expect(bounds.starty).toBe(100); expect(bounds.stopx).toBe(200); expect(bounds.stopy).toBe(200); }); it('it should handle an expanding bound', function () { - renderer.bounds.insert(100, 100, 200, 200); - renderer.bounds.insert(25, 50, 300, 400); + diagram.renderer.bounds.insert(100, 100, 200, 200); + diagram.renderer.bounds.insert(25, 50, 300, 400); - const { bounds } = renderer.bounds.getBounds(); + const { bounds } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(25); expect(bounds.starty).toBe(50); expect(bounds.stopx).toBe(300); expect(bounds.stopy).toBe(400); }); it('it should handle inserts within the bound without changing the outer bounds', function () { - renderer.bounds.insert(100, 100, 200, 200); - renderer.bounds.insert(25, 50, 300, 400); - renderer.bounds.insert(125, 150, 150, 200); + diagram.renderer.bounds.insert(100, 100, 200, 200); + diagram.renderer.bounds.insert(25, 50, 300, 400); + diagram.renderer.bounds.insert(125, 150, 150, 200); - const { bounds } = renderer.bounds.getBounds(); + const { bounds } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(25); expect(bounds.starty).toBe(50); expect(bounds.stopx).toBe(300); expect(bounds.stopy).toBe(400); }); it('it should handle a loop without expanding the area', function () { - renderer.bounds.insert(25, 50, 300, 400); - renderer.bounds.verticalPos = 150; - renderer.bounds.newLoop(); - renderer.bounds.insert(125, 150, 150, 200); + diagram.renderer.bounds.insert(25, 50, 300, 400); + diagram.renderer.bounds.verticalPos = 150; + diagram.renderer.bounds.newLoop(); + diagram.renderer.bounds.insert(125, 150, 150, 200); - const loop = renderer.bounds.endLoop(); + const loop = diagram.renderer.bounds.endLoop(); expect(loop.startx).toBe(125 - conf.boxMargin); expect(loop.starty).toBe(150 - conf.boxMargin); @@ -1207,7 +1214,7 @@ describe('when checking the bounds in a sequenceDiagram', function () { expect(loop.stopy).toBe(200 + conf.boxMargin); // Check bounds of first loop - const { bounds } = renderer.bounds.getBounds(); + const { bounds } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(25); expect(bounds.starty).toBe(50); @@ -1215,14 +1222,14 @@ describe('when checking the bounds in a sequenceDiagram', function () { expect(bounds.stopy).toBe(400); }); it('it should handle multiple loops withtout expanding the bounds', function () { - renderer.bounds.insert(100, 100, 1000, 1000); - renderer.bounds.verticalPos = 200; - renderer.bounds.newLoop(); - renderer.bounds.newLoop(); - renderer.bounds.insert(200, 200, 300, 300); + diagram.renderer.bounds.insert(100, 100, 1000, 1000); + diagram.renderer.bounds.verticalPos = 200; + diagram.renderer.bounds.newLoop(); + diagram.renderer.bounds.newLoop(); + diagram.renderer.bounds.insert(200, 200, 300, 300); // Check bounds of first loop - let loop = renderer.bounds.endLoop(); + let loop = diagram.renderer.bounds.endLoop(); expect(loop.startx).toBe(200 - conf.boxMargin); expect(loop.starty).toBe(200 - conf.boxMargin); @@ -1230,7 +1237,7 @@ describe('when checking the bounds in a sequenceDiagram', function () { expect(loop.stopy).toBe(300 + conf.boxMargin); // Check bounds of second loop - loop = renderer.bounds.endLoop(); + loop = diagram.renderer.bounds.endLoop(); expect(loop.startx).toBe(200 - 2 * conf.boxMargin); expect(loop.starty).toBe(200 - 2 * conf.boxMargin); @@ -1238,7 +1245,7 @@ describe('when checking the bounds in a sequenceDiagram', function () { expect(loop.stopy).toBe(300 + 2 * conf.boxMargin); // Check bounds of first loop - const { bounds } = renderer.bounds.getBounds(); + const { bounds } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(100); expect(bounds.starty).toBe(100); @@ -1246,12 +1253,12 @@ describe('when checking the bounds in a sequenceDiagram', function () { expect(bounds.stopy).toBe(1000); }); it('it should handle a loop that expands the area', function () { - renderer.bounds.insert(100, 100, 200, 200); - renderer.bounds.verticalPos = 200; - renderer.bounds.newLoop(); - renderer.bounds.insert(50, 50, 300, 300); + diagram.renderer.bounds.insert(100, 100, 200, 200); + diagram.renderer.bounds.verticalPos = 200; + diagram.renderer.bounds.newLoop(); + diagram.renderer.bounds.insert(50, 50, 300, 300); - const loop = renderer.bounds.endLoop(); + const loop = diagram.renderer.bounds.endLoop(); expect(loop.startx).toBe(50 - conf.boxMargin); expect(loop.starty).toBe(50 - conf.boxMargin); @@ -1259,7 +1266,7 @@ describe('when checking the bounds in a sequenceDiagram', function () { expect(loop.stopy).toBe(300 + conf.boxMargin); // Check bounds after the loop - const { bounds } = renderer.bounds.getBounds(); + const { bounds } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(loop.startx); expect(bounds.starty).toBe(loop.starty); @@ -1289,6 +1296,8 @@ describe('when rendering a sequenceDiagram APA', function () { let conf; beforeEach(function () { mermaidAPI.reset(); + + // }); conf = { diagramMarginX: 50, diagramMarginY: 10, @@ -1304,9 +1313,12 @@ describe('when rendering a sequenceDiagram APA', function () { mirrorActors: false, }; configApi.setSiteConfig({ logLevel: 5, sequence: conf }); - parser.yy = sequenceDb; - parser.yy.clear(); - // conf = parser.yy.getConfig(); + diagram = new Diagram(` +sequenceDiagram +Alice->Bob:Hello Bob, how are you? +Note right of Bob: Bob thinks +Bob-->Alice: I am good thanks!`); + diagram.db.clear(); }); ['tspan', 'fo', 'old', undefined].forEach(function (textPlacement) { it(` @@ -1315,12 +1327,12 @@ it should handle one actor, when textPlacement is ${textPlacement}`, function () sequenceDiagram participant Alice`; - mermaidAPI.reinitialize({ sequence: { textPlacement: textPlacement } }); + // mermaidAPI.reinitialize({ sequence: { textPlacement: textPlacement } }); mermaidAPI.parse(str); - // renderer.setConf(mermaidAPI.getConfig().sequence); - renderer.draw(str, 'tst'); + // diagram.renderer.setConf(mermaidAPI.getConfig().sequence); + diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds } = renderer.bounds.getBounds(); + const { bounds } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width); @@ -1337,7 +1349,7 @@ participant Alice mermaidAPI.parse(str); - const actors = parser.yy.getActors(); + const actors = diagram.db.getActors(); expect(Object.keys(actors)).toEqual(['Alice']); }); it('it should handle one actor and a centered note', function () { @@ -1349,9 +1361,9 @@ Note over Alice: Alice thinks expect(mermaidAPI.getConfig().sequence.mirrorActors).toBeFalsy(); mermaidAPI.parse(str); - renderer.draw(str, 'tst'); + diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width); @@ -1364,10 +1376,10 @@ sequenceDiagram participant Alice Note left of Alice: Alice thinks`; - mermaidAPI.parse(str); - renderer.draw(str, 'tst'); + mermaidAPI.parse(str, diagram); + diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width); @@ -1381,9 +1393,9 @@ participant Alice Note right of Alice: Alice thinks`; mermaidAPI.parse(str); - renderer.draw(str, 'tst'); + diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width / 2 + conf.actorMargin / 2 + conf.width); @@ -1396,9 +1408,9 @@ sequenceDiagram Alice->Bob: Hello Bob, how are you?`; mermaidAPI.parse(str); - renderer.draw(str, 'tst'); + diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin); @@ -1411,9 +1423,9 @@ sequenceDiagram Alice->Bob: Hello Bob, how are you?`; mermaidAPI.parse(str); - renderer.draw(str, 'tst'); + diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); const mermaid = mermaidAPI.getConfig(); expect(mermaid.logLevel).toBe(0); expect(bounds.startx).toBe(0); @@ -1431,10 +1443,10 @@ wrap Alice->Bob: Hello Bob, how are you?`; mermaidAPI.parse(str); - renderer.draw(str, 'tst'); + diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const msgs = parser.yy.getMessages(); - const { bounds, models } = renderer.bounds.getBounds(); + const msgs = diagram.db.getMessages(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); const mermaid = mermaidAPI.getConfig(); expect(mermaid.logLevel).toBe(0); expect(bounds.startx).toBe(0); @@ -1452,9 +1464,9 @@ Note over Bob,Alice: Looks back `; // mermaidAPI.initialize({logLevel:0}) mermaidAPI.parse(str); - renderer.draw(str, 'tst'); + diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin); @@ -1467,9 +1479,9 @@ Alice->Bob: Hello Bob, how are you? Bob->Alice: Fine!`; mermaidAPI.parse(str); - renderer.draw(str, 'tst'); + diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin); @@ -1483,9 +1495,9 @@ Note right of Bob: Bob thinks Bob->Alice: Fine!`; mermaidAPI.parse(str); - renderer.draw(str, 'tst'); + diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); @@ -1502,9 +1514,9 @@ Note left of Alice: Bob thinks Bob->Alice: Fine!`; mermaidAPI.parse(str); - renderer.draw(str, 'tst'); + diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2); expect(bounds.starty).toBe(0); @@ -1519,10 +1531,10 @@ Note left of Alice: Bob thinks Bob->>Alice: Fine!`; mermaidAPI.parse(str); - renderer.draw(str, 'tst'); + diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = renderer.bounds.getBounds(); - const msgs = parser.yy.getMessages(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); + const msgs = diagram.db.getMessages(); expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2); expect(bounds.starty).toBe(0); expect(msgs[0].wrap).toBe(true); @@ -1540,10 +1552,10 @@ Note left of Alice: Bob thinks Bob->>Alice: Fine!`; mermaidAPI.parse(str); - renderer.draw(str, 'tst'); + diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = renderer.bounds.getBounds(); - const msgs = parser.yy.getMessages(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); + const msgs = diagram.db.getMessages(); const mermaid = mermaidAPI.getConfig(); expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2); expect(bounds.starty).toBe(0); @@ -1563,10 +1575,10 @@ Note left of Alice: Bob thinks Bob->>Alice: Fine!`; mermaidAPI.parse(str); - renderer.draw(str, 'tst'); + diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = renderer.bounds.getBounds(); - const msgs = parser.yy.getMessages(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); + const msgs = diagram.db.getMessages(); const mermaid = mermaidAPI.getConfig(); expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2); expect(bounds.starty).toBe(0); @@ -1583,11 +1595,12 @@ sequenceDiagram Alice->>Bob: Hello Bob, how are you? If you are not available right now, I can leave you a message. Please get back to me as soon as you can! Note left of Alice: Bob thinks Bob->>Alice: Fine!`; - mermaidAPI.parse(str); - renderer.draw(str, 'tst'); + // mermaidAPI.initialize({ logLevel: 0 }); + mermaidAPI.parse(str, diagram); + diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = renderer.bounds.getBounds(); - const msgs = parser.yy.getMessages(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); + const msgs = diagram.db.getMessages(); const mermaid = mermaidAPI.getConfig(); expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2); expect(bounds.starty).toBe(0); @@ -1608,9 +1621,9 @@ loop Cheers Bob->Alice: Fine! end`; mermaidAPI.parse(str); - renderer.draw(str, 'tst'); + diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); @@ -1626,8 +1639,8 @@ end`; end `; mermaidAPI.parse(str); - renderer.draw(str, 'tst'); - const { bounds, models } = renderer.bounds.getBounds(); + diagram.renderer.draw(str, 'tst', '1.2.3', diagram); + const { bounds, models } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); @@ -1661,23 +1674,23 @@ describe('when rendering a sequenceDiagram with actor mirror activated', functio let conf; beforeEach(function () { mermaidAPI.reset(); - parser.yy = sequenceDb; - parser.yy.clear(); - conf = parser.yy.getConfig(); - renderer.bounds.init(); + // diagram.db = sequenceDb; + diagram.db.clear(); + conf = diagram.db.getConfig(); + diagram.renderer.bounds.init(); }); ['tspan', 'fo', 'old', undefined].forEach(function (textPlacement) { it('it should handle one actor, when textPlacement is' + textPlacement, function () { mermaidAPI.initialize(addConf(conf, 'textPlacement', textPlacement)); - renderer.bounds.init(); + diagram.renderer.bounds.init(); const str = ` sequenceDiagram participant Alice`; - renderer.bounds.init(); + diagram.renderer.bounds.init(); mermaidAPI.parse(str); - renderer.draw(str, 'tst'); + diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width); @@ -1705,10 +1718,10 @@ describe('when rendering a sequenceDiagram with directives', function () { let conf; beforeEach(function () { mermaidAPI.reset(); - parser.yy = sequenceDb; - parser.yy.clear(); - conf = parser.yy.getConfig(); - renderer.bounds.init(); + // diagram.db = sequenceDb; + diagram.db.clear(); + conf = diagram.db.getConfig(); + diagram.renderer.bounds.init(); }); it('it should handle one actor, when theme is dark and logLevel is 1 DX1', function () { @@ -1719,12 +1732,12 @@ sequenceDiagram participant Alice `; - renderer.bounds.init(); + diagram.renderer.bounds.init(); mermaidAPI.parse(str); - renderer.draw(str, 'tst'); + diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); const mermaid = mermaidAPI.getConfig(); expect(mermaid.theme).toBe('dark'); expect(mermaid.logLevel).toBe(1); @@ -1743,9 +1756,9 @@ participant Alice `; mermaidAPI.parse(str); - renderer.draw(str, 'tst'); + diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); const mermaid = mermaidAPI.getConfig(); expect(mermaid.logLevel).toBe(3); expect(bounds.startx).toBe(0); @@ -1763,9 +1776,9 @@ Alice->Bob:Hello Bob, how are you? Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`; - mermaidAPI.parse(str1); - renderer.draw(str1, 'tst'); // needs to be rendered for the correct value of visibility autonumbers - expect(parser.yy.showSequenceNumbers()).toBe(true); + mermaidAPI.parse(str1, diagram); + diagram.renderer.draw(str1, 'tst', '1.2.3', diagram); // needs to be rendered for the correct value of visibility autonumbers + expect(diagram.db.showSequenceNumbers()).toBe(true); const str2 = ` sequenceDiagram @@ -1773,8 +1786,8 @@ Alice->Bob:Hello Bob, how are you? Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`; - mermaidAPI.parse(str2); - renderer.draw(str2, 'tst'); - expect(parser.yy.showSequenceNumbers()).toBe(false); + mermaidAPI.parse(str2, diagram); + diagram.renderer.draw(str2, 'tst', '1.2.3', diagram); + expect(diagram.db.showSequenceNumbers()).toBe(false); }); }); diff --git a/src/diagrams/sequence/sequenceRenderer.js b/src/diagrams/sequence/sequenceRenderer.js index 809e3164f7..46d48b0587 100644 --- a/src/diagrams/sequence/sequenceRenderer.js +++ b/src/diagrams/sequence/sequenceRenderer.js @@ -5,7 +5,8 @@ import { log } from '../../logger'; import common from '../common/common'; // import sequenceDb from './sequenceDb'; import * as configApi from '../../config'; -import utils, { assignWithDepth, configureSvgSize } from '../../utils'; +import assignWithDepth from '../../assignWithDepth'; +import utils, { configureSvgSize } from '../../utils'; import addSVGAccessibilityFields from '../../accessibility'; let conf = {}; diff --git a/src/diagrams/user-journey/journeyRenderer.js b/src/diagrams/user-journey/journeyRenderer.js index c8ad6278c0..79424cfef6 100644 --- a/src/diagrams/user-journey/journeyRenderer.js +++ b/src/diagrams/user-journey/journeyRenderer.js @@ -69,7 +69,6 @@ export const draw = function (text, id, version, diagObj) { svgDraw.initGraphics(diagram); const tasks = diagObj.db.getTasks(); - console.log('text and tasks', text, tasks); const title = diagObj.db.getDiagramTitle(); const actorNames = diagObj.db.getActors(); diff --git a/src/mermaid.js b/src/mermaid.js index 3ea510a7f4..a708554a8d 100644 --- a/src/mermaid.js +++ b/src/mermaid.js @@ -209,7 +209,7 @@ const setParseErrorHandler = function (newParseErrorHandler) { const mermaid = { startOnLoad: true, htmlLabels: true, - + diagrams: {}, mermaidAPI, parse: mermaidAPI != undefined ? mermaidAPI.parse : null, render: mermaidAPI != undefined ? mermaidAPI.render : null, diff --git a/src/mermaidAPI.js b/src/mermaidAPI.js index 7bd06e04ca..9c45a2bf2e 100644 --- a/src/mermaidAPI.js +++ b/src/mermaidAPI.js @@ -19,56 +19,27 @@ import { select } from 'd3'; import { compile, serialize, stringify } from 'stylis'; import pkg from '../package.json'; import * as configApi from './config'; -import c4Db from './diagrams/c4/c4Db'; -import c4Renderer from './diagrams/c4/c4Renderer'; -import c4Parser from './diagrams/c4/parser/c4Diagram'; +import apa from './diagram-api/diagram-orchestration'; import classDb from './diagrams/class/classDb'; -import classRenderer from './diagrams/class/classRenderer'; -import classRendererV2 from './diagrams/class/classRenderer-v2'; -import classParser from './diagrams/class/parser/classDiagram'; -import erDb from './diagrams/er/erDb'; -import erRenderer from './diagrams/er/erRenderer'; -import erParser from './diagrams/er/parser/erDiagram'; import flowDb from './diagrams/flowchart/flowDb'; import flowRenderer from './diagrams/flowchart/flowRenderer'; import flowRendererV2 from './diagrams/flowchart/flowRenderer-v2'; -import flowParser from './diagrams/flowchart/parser/flow'; import ganttDb from './diagrams/gantt/ganttDb'; import ganttRenderer from './diagrams/gantt/ganttRenderer'; -import ganttParser from './diagrams/gantt/parser/gantt'; -import gitGraphAst from './diagrams/git/gitGraphAst'; -import gitGraphRenderer from './diagrams/git/gitGraphRenderer'; -import gitGraphParser from './diagrams/git/parser/gitGraph'; -import infoDb from './diagrams/info/infoDb'; -import infoRenderer from './diagrams/info/infoRenderer'; -import infoParser from './diagrams/info/parser/info'; -import pieParser from './diagrams/pie/parser/pie'; -import pieDb from './diagrams/pie/pieDb'; -import pieRenderer from './diagrams/pie/pieRenderer'; -import addSVGAccessibilityFields from './diagrams/pie/pieRenderer'; -import requirementParser from './diagrams/requirement/parser/requirementDiagram'; -import requirementDb from './diagrams/requirement/requirementDb'; -import requirementRenderer from './diagrams/requirement/requirementRenderer'; -import sequenceParser from './diagrams/sequence/parser/sequenceDiagram'; -import sequenceDb from './diagrams/sequence/sequenceDb'; import sequenceRenderer from './diagrams/sequence/sequenceRenderer'; -import stateParser from './diagrams/state/parser/stateDiagram'; -import stateDb from './diagrams/state/stateDb'; import stateRenderer from './diagrams/state/stateRenderer'; import stateRendererV2 from './diagrams/state/stateRenderer-v2'; -import journeyDb from './diagrams/user-journey/journeyDb'; import journeyRenderer from './diagrams/user-journey/journeyRenderer'; -import journeyParser from './diagrams/user-journey/parser/journey'; import Diagram from './Diagram'; import errorRenderer from './errorRenderer'; import { attachFunctions } from './interactionDb'; import { log, setLogLevel } from './logger'; import getStyles from './styles'; import theme from './themes'; -import utils, { directiveSanitizer, assignWithDepth, sanitizeCss } from './utils'; +import utils, { directiveSanitizer } from './utils'; +import assignWithDepth from './assignWithDepth'; import DOMPurify from 'dompurify'; import mermaid from './mermaid'; - /** * @param text * @param dia @@ -77,20 +48,9 @@ import mermaid from './mermaid'; function parse(text, dia) { var parseEncounteredException = false; try { - text = text + '\n'; const diag = dia ? dia : new Diagram(text); diag.db.clear(); - const cnf = configApi.getConfig(); - let parser = diag.parser; - - log.debug('Type ' + diag.type); - parser.parser.yy.graphType = diag.type; - parser.parser.yy.parseError = (str, hash) => { - const error = { str, hash }; - throw error; - }; - - parser.parse(text); + return diag.parse(text); } catch (error) { parseEncounteredException = true; // Is this the correct way to access mermiad's parseError() @@ -290,6 +250,7 @@ const render = function (id, _txt, cb, container) { txt = encodeEntities(txt); + // Imortant that we do not create the diagram until after the directives have been included const diag = new Diagram(txt); // Get the tmp element containing the the svg const element = root.select('#d' + id).node(); diff --git a/src/mermaidAPI.spec.js b/src/mermaidAPI.spec.js index 74b1be0b5b..e4c2d168da 100644 --- a/src/mermaidAPI.spec.js +++ b/src/mermaidAPI.spec.js @@ -1,6 +1,6 @@ import mermaid from './mermaid'; import mermaidAPI from './mermaidAPI'; -import { assignWithDepth } from './utils'; +import assignWithDepth from './assignWithDepth'; describe('when using mermaidAPI and ', function () { describe('doing initialize ', function () { diff --git a/src/utils.js b/src/utils.js index 0d2b4392ce..db45ab9f62 100644 --- a/src/utils.js +++ b/src/utils.js @@ -16,6 +16,8 @@ import { import common from './diagrams/common/common'; import { configKeys } from './defaultConfig'; import { log } from './logger'; +import detectType from './diagram-api/detectType'; +import assignWithDepth from './assignWithDepth'; // Effectively an enum of the supported curve types, accessible by name const d3CurveTypes = { @@ -160,90 +162,6 @@ export const detectDirective = function (text, type = null) { } }; -/** - * @function detectType Detects the type of the graph text. Takes into consideration the possible - * existence of an %%init directive - * - * ```mermaid - * %%{initialize: {"startOnLoad": true, logLevel: "fatal" }}%% - * graph LR - * a-->b - * b-->c - * c-->d - * d-->e - * e-->f - * f-->g - * g-->h - * ``` - * @param {string} text The text defining the graph - * @param {{ - * class: { defaultRenderer: string } | undefined; - * state: { defaultRenderer: string } | undefined; - * flowchart: { defaultRenderer: string } | undefined; - * }} [cnf] - * @returns {string} A graph definition key - */ -export const detectType = function (text, cnf) { - text = text.replace(directive, '').replace(anyComment, '\n'); - if (text.match(/^\s*C4Context|C4Container|C4Component|C4Dynamic|C4Deployment/)) { - return 'c4'; - } - - if (text.match(/^\s*sequenceDiagram/)) { - return 'sequence'; - } - - if (text.match(/^\s*gantt/)) { - return 'gantt'; - } - if (text.match(/^\s*classDiagram-v2/)) { - return 'classDiagram'; - } - if (text.match(/^\s*classDiagram/)) { - if (cnf && cnf.class && cnf.class.defaultRenderer === 'dagre-wrapper') return 'classDiagram'; - return 'class'; - } - - if (text.match(/^\s*stateDiagram-v2/)) { - return 'stateDiagram'; - } - - if (text.match(/^\s*stateDiagram/)) { - if (cnf && cnf.class && cnf.state.defaultRenderer === 'dagre-wrapper') return 'stateDiagram'; - return 'state'; - } - - if (text.match(/^\s*gitGraph/)) { - return 'gitGraph'; - } - if (text.match(/^\s*flowchart/)) { - return 'flowchart-v2'; - } - - if (text.match(/^\s*info/)) { - return 'info'; - } - if (text.match(/^\s*pie/)) { - return 'pie'; - } - - if (text.match(/^\s*erDiagram/)) { - return 'er'; - } - - if (text.match(/^\s*journey/)) { - return 'journey'; - } - - if (text.match(/^\s*requirement/) || text.match(/^\s*requirementDiagram/)) { - return 'requirement'; - } - if (cnf && cnf.flowchart && cnf.flowchart.defaultRenderer === 'dagre-wrapper') - return 'flowchart-v2'; - - return 'flowchart'; -}; - /** * Caches results of functions based on input * @@ -578,79 +496,6 @@ export const random = (options) => { return makeid(options.length); }; -/** - * @function assignWithDepth Extends the functionality of {@link ObjectConstructor.assign} with the - * ability to merge arbitrary-depth objects For each key in src with path `k` (recursively) - * performs an Object.assign(dst[`k`], src[`k`]) with a slight change from the typical handling of - * undefined for dst[`k`]: instead of raising an error, dst[`k`] is auto-initialized to {} and - * effectively merged with src[`k`]

Additionally, dissimilar types will not clobber unless the - * config.clobber parameter === true. Example: - * - * ```js - * let config_0 = { foo: { bar: 'bar' }, bar: 'foo' }; - * let config_1 = { foo: 'foo', bar: 'bar' }; - * let result = assignWithDepth(config_0, config_1); - * console.log(result); - * //-> result: { foo: { bar: 'bar' }, bar: 'bar' } - * ``` - * - * Traditional Object.assign would have clobbered foo in config_0 with foo in config_1. If src is a - * destructured array of objects and dst is not an array, assignWithDepth will apply each element - * of src to dst in order. - * @param dst - * @param src - * @param config - * @param dst - * @param src - * @param config - * @param dst - * @param src - * @param config - * @param {any} dst - The destination of the merge - * @param {any} src - The source object(s) to merge into destination - * @param {{ depth: number; clobber: boolean }} [config={ depth: 2, clobber: false }] - Depth: depth - * to traverse within src and dst for merging - clobber: should dissimilar types clobber (default: - * { depth: 2, clobber: false }). Default is `{ depth: 2, clobber: false }` - * @returns {any} - */ -export const assignWithDepth = function (dst, src, config) { - const { depth, clobber } = Object.assign({ depth: 2, clobber: false }, config); - if (Array.isArray(src) && !Array.isArray(dst)) { - src.forEach((s) => assignWithDepth(dst, s, config)); - return dst; - } else if (Array.isArray(src) && Array.isArray(dst)) { - src.forEach((s) => { - if (dst.indexOf(s) === -1) { - dst.push(s); - } - }); - return dst; - } - if (typeof dst === 'undefined' || depth <= 0) { - if (dst !== undefined && dst !== null && typeof dst === 'object' && typeof src === 'object') { - return Object.assign(dst, src); - } else { - return src; - } - } - if (typeof src !== 'undefined' && typeof dst === 'object' && typeof src === 'object') { - Object.keys(src).forEach((key) => { - if ( - typeof src[key] === 'object' && - (dst[key] === undefined || typeof dst[key] === 'object') - ) { - if (dst[key] === undefined) { - dst[key] = Array.isArray(src[key]) ? [] : {}; - } - dst[key] = assignWithDepth(dst[key], src[key], { depth: depth - 1, clobber }); - } else if (clobber || (typeof dst[key] !== 'object' && typeof src[key] !== 'object')) { - dst[key] = src[key]; - } - }); - } - return dst; -}; - export const getTextObj = function () { return { x: 0, @@ -1096,7 +941,6 @@ export default { setupGraphViewbox, detectInit, detectDirective, - detectType, isSubstringInArray, interpolateToCurve, calcLabelPosition, diff --git a/src/utils.spec.js b/src/utils.spec.js index b079beeeb1..31517c43ae 100644 --- a/src/utils.spec.js +++ b/src/utils.spec.js @@ -1,52 +1,55 @@ import utils from './utils'; +import assignWithDepth from './assignWithDepth'; +import detectType from './diagram-api/detectType'; +import './diagram-api/diagram-orchestration'; describe('when assignWithDepth: should merge objects within objects', function () { it('should handle simple, depth:1 types (identity)', function () { let config_0 = { foo: 'bar', bar: 0 }; let config_1 = { foo: 'bar', bar: 0 }; - let result = utils.assignWithDepth(config_0, config_1); + let result = assignWithDepth(config_0, config_1); expect(result).toEqual(config_1); }); it('should handle simple, depth:1 types (dst: undefined)', function () { let config_0 = undefined; let config_1 = { foo: 'bar', bar: 0 }; - let result = utils.assignWithDepth(config_0, config_1); + let result = assignWithDepth(config_0, config_1); expect(result).toEqual(config_1); }); it('should handle simple, depth:1 types (src: undefined)', function () { let config_0 = { foo: 'bar', bar: 0 }; let config_1 = undefined; - let result = utils.assignWithDepth(config_0, config_1); + let result = assignWithDepth(config_0, config_1); expect(result).toEqual(config_0); }); it('should handle simple, depth:1 types (merge)', function () { let config_0 = { foo: 'bar', bar: 0 }; let config_1 = { foo: 'foo' }; - let result = utils.assignWithDepth(config_0, config_1); + let result = assignWithDepth(config_0, config_1); expect(result).toEqual({ foo: 'foo', bar: 0 }); }); it('should handle depth:2 types (dst: orphan)', function () { let config_0 = { foo: 'bar', bar: { foo: 'bar' } }; let config_1 = { foo: 'bar' }; - let result = utils.assignWithDepth(config_0, config_1); + let result = assignWithDepth(config_0, config_1); expect(result).toEqual(config_0); }); it('should handle depth:2 types (dst: object, src: simple type)', function () { let config_0 = { foo: 'bar', bar: { foo: 'bar' } }; let config_1 = { foo: 'foo', bar: 'should NOT clobber' }; - let result = utils.assignWithDepth(config_0, config_1); + let result = assignWithDepth(config_0, config_1); expect(result).toEqual({ foo: 'foo', bar: { foo: 'bar' } }); }); it('should handle depth:2 types (src: orphan)', function () { let config_0 = { foo: 'bar' }; let config_1 = { foo: 'bar', bar: { foo: 'bar' } }; - let result = utils.assignWithDepth(config_0, config_1); + let result = assignWithDepth(config_0, config_1); expect(result).toEqual(config_1); }); it('should handle depth:2 types (merge)', function () { let config_0 = { foo: 'bar', bar: { foo: 'bar' }, boofar: 1 }; let config_1 = { foo: 'foo', bar: { bar: 0 }, foobar: 'foobar' }; - let result = utils.assignWithDepth(config_0, config_1); + let result = assignWithDepth(config_0, config_1); expect(result).toEqual({ foo: 'foo', bar: { foo: 'bar', bar: 0 }, @@ -65,7 +68,7 @@ describe('when assignWithDepth: should merge objects within objects', function ( bar: { foo: 'foo', bar: { foo: { message: 'clobbered other foo' } } }, foobar: 'foobar', }; - let result = utils.assignWithDepth(config_0, config_1); + let result = assignWithDepth(config_0, config_1); expect(result).toEqual({ foo: 'foo', bar: { foo: 'foo', bar: { foo: { message: 'clobbered other foo' } } }, @@ -87,7 +90,7 @@ describe('when assignWithDepth: should merge objects within objects', function ( bar: { foo: 'foo', bar: { foo: { message: 'this' } } }, foobar: 'foobar', }; - let result = utils.assignWithDepth(config_0, config_1, { depth: 1 }); + let result = assignWithDepth(config_0, config_1, { depth: 1 }); expect(result).toEqual({ foo: 'foo', bar: { foo: 'foo', bar: { foo: { message: 'this' } } }, @@ -106,7 +109,7 @@ describe('when assignWithDepth: should merge objects within objects', function ( bar: { foo: 'foo', bar: { foo: { message: 'this' } } }, foobar: 'foobar', }; - let result = utils.assignWithDepth(config_0, config_1, { depth: 3 }); + let result = assignWithDepth(config_0, config_1, { depth: 3 }); expect(result).toEqual({ foo: 'foo', bar: { foo: 'foo', bar: { foo: { message: 'this', willbe: 'present' } } }, @@ -137,7 +140,7 @@ describe('when memoizing', function () { describe('when detecting chart type ', function () { it('should handle a graph definition', function () { const str = 'graph TB\nbfs1:queue'; - const type = utils.detectType(str); + const type = detectType(str); expect(type).toBe('flowchart'); }); it('should handle an initialize definition', function () { @@ -145,7 +148,7 @@ describe('when detecting chart type ', function () { %%{initialize: { 'logLevel': 0, 'theme': 'dark' }}%% sequenceDiagram Alice->Bob: hi`; - const type = utils.detectType(str); + const type = detectType(str); const init = utils.detectInit(str); expect(type).toBe('sequence'); expect(init).toEqual({ logLevel: 0, theme: 'dark' }); @@ -155,7 +158,7 @@ Alice->Bob: hi`; %%{init: { 'logLevel': 0, 'theme': 'dark' }}%% sequenceDiagram Alice->Bob: hi`; - const type = utils.detectType(str); + const type = detectType(str); const init = utils.detectInit(str); expect(type).toBe('sequence'); expect(init).toEqual({ logLevel: 0, theme: 'dark' }); @@ -165,7 +168,7 @@ Alice->Bob: hi`; %%{init: { 'logLevel': 0, 'theme': 'dark', 'config': {'wrap': true} } }%% sequenceDiagram Alice->Bob: hi`; - const type = utils.detectType(str); + const type = detectType(str); const init = utils.detectInit(str); expect(type).toBe('sequence'); expect(init).toEqual({ logLevel: 0, theme: 'dark', sequence: { wrap: true } }); @@ -180,7 +183,7 @@ Alice->Bob: hi`; }%% sequenceDiagram Alice->Bob: hi`; - const type = utils.detectType(str); + const type = detectType(str); const init = utils.detectInit(str); expect(type).toBe('sequence'); expect(init).toEqual({ logLevel: 0, theme: 'dark' }); @@ -195,25 +198,25 @@ Alice->Bob: hi`; }%% sequenceDiagram Alice->Bob: hi`; - const type = utils.detectType(str); + const type = detectType(str); const init = utils.detectInit(str); expect(type).toBe('sequence'); expect(init).toEqual({ logLevel: 0, theme: 'dark' }); }); it('should handle a graph definition with leading spaces', function () { const str = ' graph TB\nbfs1:queue'; - const type = utils.detectType(str); + const type = detectType(str); expect(type).toBe('flowchart'); }); it('should handle a graph definition with leading spaces and newline', function () { const str = ' \n graph TB\nbfs1:queue'; - const type = utils.detectType(str); + const type = detectType(str); expect(type).toBe('flowchart'); }); it('should handle a graph definition for gitGraph', function () { const str = ' \n gitGraph TB:\nbfs1:queue'; - const type = utils.detectType(str); + const type = detectType(str); expect(type).toBe('gitGraph'); }); }); diff --git a/test.js b/test.js new file mode 100644 index 0000000000..824cfec888 --- /dev/null +++ b/test.js @@ -0,0 +1,5 @@ +function apa() { + // comment's + const a = 1; + return 'apa' + a; +}