diff --git a/cypress/fixtures/example.json b/cypress/fixtures/example.json new file mode 100644 index 00000000000..02e4254378e --- /dev/null +++ b/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/cypress/helpers/util.js b/cypress/helpers/util.js index dd3fdd2c924..0a52a335b22 100644 --- a/cypress/helpers/util.js +++ b/cypress/helpers/util.js @@ -42,7 +42,8 @@ export const imgSnapshotTest = (graphStr, _options, api = false, validation) => if (!options.fontSize) { options.fontSize = '16px'; } - const useAppli = Cypress.env('useAppli'); + // const useAppli = Cypress.env('useAppli'); + const useAppli = false; const branch = Cypress.env('codeBranch'); cy.log('Hello ' + useAppli ? 'Appli' : 'image-snapshot'); const name = (options.name || cy.state('runnable').fullTitle()).replace(/\s+/g, '-'); diff --git a/cypress/e2e/other/configuration.spec.js b/cypress/integration/other/configuration.spec.js similarity index 100% rename from cypress/e2e/other/configuration.spec.js rename to cypress/integration/other/configuration.spec.js diff --git a/cypress/e2e/other/ghsa.spec.js b/cypress/integration/other/ghsa.spec.js similarity index 100% rename from cypress/e2e/other/ghsa.spec.js rename to cypress/integration/other/ghsa.spec.js diff --git a/cypress/e2e/other/interaction.spec.js b/cypress/integration/other/interaction.spec.js similarity index 100% rename from cypress/e2e/other/interaction.spec.js rename to cypress/integration/other/interaction.spec.js diff --git a/cypress/e2e/other/rerender.spec.js b/cypress/integration/other/rerender.spec.js similarity index 100% rename from cypress/e2e/other/rerender.spec.js rename to cypress/integration/other/rerender.spec.js diff --git a/cypress/e2e/other/webpackUsage.spec.js b/cypress/integration/other/webpackUsage.spec.js similarity index 100% rename from cypress/e2e/other/webpackUsage.spec.js rename to cypress/integration/other/webpackUsage.spec.js diff --git a/cypress/e2e/other/xss.spec.js b/cypress/integration/other/xss.spec.js similarity index 100% rename from cypress/e2e/other/xss.spec.js rename to cypress/integration/other/xss.spec.js diff --git a/cypress/e2e/rendering/appli.spec.js b/cypress/integration/rendering/appli.spec.js similarity index 100% rename from cypress/e2e/rendering/appli.spec.js rename to cypress/integration/rendering/appli.spec.js diff --git a/cypress/e2e/rendering/classDiagram-v2.spec.js b/cypress/integration/rendering/classDiagram-v2.spec.js similarity index 100% rename from cypress/e2e/rendering/classDiagram-v2.spec.js rename to cypress/integration/rendering/classDiagram-v2.spec.js diff --git a/cypress/e2e/rendering/classDiagram.spec.js b/cypress/integration/rendering/classDiagram.spec.js similarity index 100% rename from cypress/e2e/rendering/classDiagram.spec.js rename to cypress/integration/rendering/classDiagram.spec.js diff --git a/cypress/e2e/rendering/conf-and-directives.spec.js b/cypress/integration/rendering/conf-and-directives.spec.js similarity index 100% rename from cypress/e2e/rendering/conf-and-directives.spec.js rename to cypress/integration/rendering/conf-and-directives.spec.js diff --git a/cypress/e2e/rendering/current.spec.js b/cypress/integration/rendering/current.spec.js similarity index 100% rename from cypress/e2e/rendering/current.spec.js rename to cypress/integration/rendering/current.spec.js diff --git a/cypress/e2e/rendering/debug.spec.js b/cypress/integration/rendering/debug.spec.js similarity index 100% rename from cypress/e2e/rendering/debug.spec.js rename to cypress/integration/rendering/debug.spec.js diff --git a/cypress/e2e/rendering/erDiagram.spec.js b/cypress/integration/rendering/erDiagram.spec.js similarity index 100% rename from cypress/e2e/rendering/erDiagram.spec.js rename to cypress/integration/rendering/erDiagram.spec.js diff --git a/cypress/e2e/rendering/flowchart-v2.spec.js b/cypress/integration/rendering/flowchart-v2.spec.js similarity index 100% rename from cypress/e2e/rendering/flowchart-v2.spec.js rename to cypress/integration/rendering/flowchart-v2.spec.js diff --git a/cypress/e2e/rendering/flowchart.spec.js b/cypress/integration/rendering/flowchart.spec.js similarity index 100% rename from cypress/e2e/rendering/flowchart.spec.js rename to cypress/integration/rendering/flowchart.spec.js diff --git a/cypress/e2e/rendering/gantt.spec.js b/cypress/integration/rendering/gantt.spec.js similarity index 100% rename from cypress/e2e/rendering/gantt.spec.js rename to cypress/integration/rendering/gantt.spec.js diff --git a/cypress/e2e/rendering/gitGraph.spec.js b/cypress/integration/rendering/gitGraph.spec.js similarity index 86% rename from cypress/e2e/rendering/gitGraph.spec.js rename to cypress/integration/rendering/gitGraph.spec.js index 4dda2c16edc..283a52c67c4 100644 --- a/cypress/e2e/rendering/gitGraph.spec.js +++ b/cypress/integration/rendering/gitGraph.spec.js @@ -207,4 +207,50 @@ describe('Git Graph diagram', () => { {} ); }); + + it('12: should render commits for more than 8 branches', () => { + imgSnapshotTest( + ` + gitGraph + checkout main + commit + checkout main + branch branch1 + commit + checkout main + merge branch1 + branch branch2 + commit + checkout main + merge branch2 + branch branch3 + commit + checkout main + merge branch3 + branch branch4 + commit + checkout main + merge branch4 + branch branch5 + commit + checkout main + merge branch5 + branch branch6 + commit + checkout main + merge branch6 + branch branch7 + commit + checkout main + merge branch7 + branch branch8 + commit + checkout main + merge branch8 + branch branch9 + commit + `, + {} + ); + }); }); diff --git a/cypress/e2e/rendering/info.spec.js b/cypress/integration/rendering/info.spec.js similarity index 100% rename from cypress/e2e/rendering/info.spec.js rename to cypress/integration/rendering/info.spec.js diff --git a/cypress/e2e/rendering/journey.spec.js b/cypress/integration/rendering/journey.spec.js similarity index 100% rename from cypress/e2e/rendering/journey.spec.js rename to cypress/integration/rendering/journey.spec.js diff --git a/cypress/e2e/rendering/pie.spec.js b/cypress/integration/rendering/pie.spec.js similarity index 100% rename from cypress/e2e/rendering/pie.spec.js rename to cypress/integration/rendering/pie.spec.js diff --git a/cypress/e2e/rendering/requirement.spec.js b/cypress/integration/rendering/requirement.spec.js similarity index 100% rename from cypress/e2e/rendering/requirement.spec.js rename to cypress/integration/rendering/requirement.spec.js diff --git a/cypress/e2e/rendering/sequencediagram.spec.js b/cypress/integration/rendering/sequencediagram.spec.js similarity index 94% rename from cypress/e2e/rendering/sequencediagram.spec.js rename to cypress/integration/rendering/sequencediagram.spec.js index c110f05ada9..f1def339139 100644 --- a/cypress/e2e/rendering/sequencediagram.spec.js +++ b/cypress/integration/rendering/sequencediagram.spec.js @@ -80,7 +80,7 @@ context('Sequence diagram', () => { loop Loopy Bob->>Alice: Pasten end `, - {} + { wrap: true } ); }); context('font settings', () => { @@ -126,6 +126,17 @@ context('Sequence diagram', () => { { sequence: { noteAlign: 'left' } } ); }); + it('should render multi-line notes aligned to the left when configured', () => { + imgSnapshotTest( + ` + sequenceDiagram + Alice->>Bob: I'm short + note left of Alice: I am left aligned
but also
multiline + Bob->>Alice: Short as well + `, + { sequence: { noteAlign: 'left' } } + ); + }); it('should render notes aligned to the right when configured', () => { imgSnapshotTest( ` @@ -137,6 +148,37 @@ context('Sequence diagram', () => { { sequence: { noteAlign: 'right' } } ); }); + it('should render multi-line notes aligned to the right when configured', () => { + imgSnapshotTest( + ` + sequenceDiagram + Alice->>Bob: I'm short + note left of Alice: I am right aligned
but also
multiline + Bob->>Alice: Short as well + `, + { sequence: { noteAlign: 'right' } } + ); + }); + it('should render multi-line messages aligned to the left when configured', () => { + imgSnapshotTest( + ` + sequenceDiagram + Alice->>Bob: I'm short
but also
multiline + Bob->>Alice: Short as well
and also
multiline + `, + { sequence: { messageAlign: 'left' } } + ); + }); + it('should render multi-line messages aligned to the right when configured', () => { + imgSnapshotTest( + ` + sequenceDiagram + Alice->>Bob: I'm short
but also
multiline + Bob->>Alice: Short as well
and also
multiline + `, + { sequence: { messageAlign: 'right' } } + ); + }); }); context('auth width scaling', () => { it('should render long actor descriptions', () => { diff --git a/cypress/e2e/rendering/stateDiagram-v2.spec.js b/cypress/integration/rendering/stateDiagram-v2.spec.js similarity index 97% rename from cypress/e2e/rendering/stateDiagram-v2.spec.js rename to cypress/integration/rendering/stateDiagram-v2.spec.js index b5ab8644001..946b5d31ef4 100644 --- a/cypress/e2e/rendering/stateDiagram-v2.spec.js +++ b/cypress/integration/rendering/stateDiagram-v2.spec.js @@ -509,4 +509,16 @@ stateDiagram-v2 expect(svg).to.not.have.attr('style'); }); }); + + it('v2 should render a state diagram and set the correct length of the labels', () => { + imgSnapshotTest( + ` + stateDiagram-v2 + [*] --> 1 + 1 --> 2: test({ foo#colon; 'far' }) + 2 --> [*] + `, + { logLevel: 0, fontFamily: 'courier' } + ); + }); }); diff --git a/cypress/e2e/rendering/stateDiagram.spec.js b/cypress/integration/rendering/stateDiagram.spec.js similarity index 100% rename from cypress/e2e/rendering/stateDiagram.spec.js rename to cypress/integration/rendering/stateDiagram.spec.js diff --git a/cypress/e2e/rendering/theme.spec.js b/cypress/integration/rendering/theme.spec.js similarity index 100% rename from cypress/e2e/rendering/theme.spec.js rename to cypress/integration/rendering/theme.spec.js diff --git a/cypress/platform/knsv.html b/cypress/platform/knsv.html index 8bc9f88e22e..0d870e1a369 100644 --- a/cypress/platform/knsv.html +++ b/cypress/platform/knsv.html @@ -218,13 +218,41 @@ }
- stateDiagram - accTitle: Apa - accDescr: One that can climb better then any man - [*] --> S1 - state "Some long name" as S1 +%%{init: {'config': {'wrap': true }}}%% + sequenceDiagram + participant A as Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be + A->>Bob: Hola + Bob-->A: Pasten !
+ gitGraph + commit id: "ZERO" + branch develop + commit id:"A" + checkout main + commit id:"ONE" + checkout develop + commit id:"B" + branch featureA + commit id:"FIX" + commit id: "FIX-2" + checkout main + commit id:"TWO" + cherry-pick id:"A" + commit id:"THREE" + cherry-pick id:"FIX" + checkout develop + commit id:"C" + merge featureA +
+
+flowchart TD + A[Christmas] -->|Get money| B(Go shopping) + B --> C{Let me think} + C -->|One| D[Laptop] + C -->|Two| E[iPhone] + C -->|Three| F[fa:fa-car Car] +
classDiagram Animal "1" <|-- Duck Animal <|-- Fish @@ -283,6 +311,10 @@ class: { // defaultRenderer: 'dagre-d3', htmlLabels: true, + }, + sequence: { + // mirrorActors: false,' + wrap: false, }, // gantt: { axisFormat: '%m/%d/%Y' }, // sequence: { @@ -305,6 +337,7 @@ curve: 'cardinal', // securityLevel: 'sandbox', // themeVariables: {relationLabelColor: 'red'} + wrap: true, }); function callback() { alert('It worked'); diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js new file mode 100644 index 00000000000..2c98a54ade0 --- /dev/null +++ b/cypress/plugins/index.js @@ -0,0 +1,32 @@ +// *********************************************************** +// This example plugins/index.js can be used to load plugins +// +// You can change the location of this file or turn off loading +// the plugins file with the 'pluginsFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/plugins-guide +// *********************************************************** + +// This function is called when a project is opened or re-opened (e.g. due to +// the project's config changing) + +// module.exports = (on, config) => { +// // `on` is used to hook into various events Cypress emits +// // `config` is the resolved Cypress config +// } + +const { addMatchImageSnapshotPlugin } = require('cypress-image-snapshot/plugin'); +require('@applitools/eyes-cypress')(module); + +module.exports = (on, config) => { + addMatchImageSnapshotPlugin(on, config); + // copy any needed variables from process.env to config.env + config.env.useAppli = process.env.USE_APPLI ? true : false; + config.env.codeBranch = process.env.APPLI_BRANCH; + + // do not forget to return the changed config object! + return config; +}; + +require('@applitools/eyes-cypress')(module); diff --git a/docs/Setup.md b/docs/Setup.md index 9614b655b26..85070a1e723 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,15 +1429,6 @@ function _Default value: At default, will mirror Global Config_ Returns **[object][5]** The siteConfig -## parse - -### Parameters - -- `text` -- `dia` - -Returns **any** - ## getSiteConfig ## getSiteConfig @@ -1471,21 +1471,6 @@ Returns **any** The currentConfig merged with the sanitized conf Returns **any** The currentConfig -## sanitize - -## sanitize - -| Function | Description | Type | Values | -| -------- | -------------------------------------- | ----------- | ------ | -| sanitize | Sets the siteConfig to desired values. | Put Request | None | - -Ensures options parameter does not attempt to override siteConfig secure keys **Notes**: modifies -options in-place - -### Parameters - -- `options` **any** The potential setConfig parameter - ## render Function that renders an svg with a graph from a chart definition. Usage example below. @@ -1514,6 +1499,21 @@ $(function () { Returns **any** +## sanitize + +## sanitize + +| Function | Description | Type | Values | +| -------- | -------------------------------------- | ----------- | ------ | +| sanitize | Sets the siteConfig to desired values. | Put Request | None | + +Ensures options parameter does not attempt to override siteConfig secure keys **Notes**: modifies +options in-place + +### Parameters + +- `options` **any** The potential setConfig parameter + ## addDirective Pushes in a directive to the configuration diff --git a/package.json b/package.json index d295b5f5556..b1abfe0fca7 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "postbuild": "documentation build src/mermaidAPI.js src/config.js src/defaultConfig.js --shallow -f md --markdown-toc false > docs/Setup.md", "build:watch": "yarn build:development --watch", "release": "yarn build", - "lint": "eslint ./ --ext .js,.json,.html,.md", + "lint": "eslint ./ --ext .js,.json,.html", "lint:fix": "yarn lint --fix", "e2e:depr": "yarn lint && jest e2e --config e2e/jest.config.js", "cypress": "cypress run", @@ -81,7 +81,7 @@ "concurrently": "^7.0.0", "coveralls": "^3.0.2", "css-to-string-loader": "^0.1.3", - "cypress": "10.3.0", + "cypress": "9.7.0", "cypress-image-snapshot": "^4.0.1", "documentation": "13.2.0", "eslint": "^8.4.1", diff --git a/src/Diagram.js b/src/Diagram.js index b1fa1dc4124..a87ed42fb5c 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 00000000000..a74c4794573 --- /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 f438318c7cc..59c6c18cbac 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/dagre-wrapper/createLabel.js b/src/dagre-wrapper/createLabel.js index ed7b9f6fb11..3e3ffdfc956 100644 --- a/src/dagre-wrapper/createLabel.js +++ b/src/dagre-wrapper/createLabel.js @@ -2,6 +2,7 @@ import { select } from 'd3'; import { log } from '../logger'; // eslint-disable-line import { getConfig } from '../config'; import { sanitizeText, evaluate } from '../diagrams/common/common'; +import { decodeEntities } from '../mermaidAPI'; const sanitizeTxt = (txt) => sanitizeText(txt, getConfig()); @@ -52,7 +53,7 @@ const createLabel = (_vertexText, style, isTitle, isNode) => { log.info('vertexText' + vertexText); const node = { isNode, - label: vertexText.replace( + label: decodeEntities(vertexText).replace( /fa[lrsb]?:fa-[\w-]+/g, (s) => `` ), diff --git a/src/diagram-api/detectType.js b/src/diagram-api/detectType.js new file mode 100644 index 00000000000..a5f074e3e15 --- /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 00000000000..d73bc1bbba0 --- /dev/null +++ b/src/diagram-api/diagram-orchestration.js @@ -0,0 +1,32 @@ +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 +// ); +const addDiagrams = () => { + registerDiagram( + 'gitGraph', + gitGraphParser, + gitGraphDb, + gitGraphRenderer, + undefined, + gitGraphDetector + ); +}; +export default addDiagrams; diff --git a/src/diagram-api/diagramAPI.js b/src/diagram-api/diagramAPI.js index a695de5bfaa..62c8843682f 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'); + }, + }, + 'flowchart-v2': { + 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 acd39fa4773..6af59bb928f 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 356b3688a93..4e1ce10193e 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 00000000000..3707a330475 --- /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/git/gitGraphRenderer.js b/src/diagrams/git/gitGraphRenderer.js index 1d94f7c5e7d..0a7c457cf72 100644 --- a/src/diagrams/git/gitGraphRenderer.js +++ b/src/diagrams/git/gitGraphRenderer.js @@ -15,6 +15,8 @@ const commitType = { CHERRY_PICK: 4, }; +const THEME_COLOR_LIMIT = 8; + let branchPos = {}; let commitPos = {}; let lanes = []; @@ -117,13 +119,9 @@ const drawCommits = (svg, commits, modifyGraph) => { circle.attr('width', 20); circle.attr( 'class', - 'commit ' + - commit.id + - ' commit-highlight' + - branchPos[commit.branch].index + - ' ' + - typeClass + - '-outer' + `commit ${commit.id} commit-highlight${ + branchPos[commit.branch].index % THEME_COLOR_LIMIT + } ${typeClass}-outer` ); gBullets .append('rect') @@ -133,13 +131,9 @@ const drawCommits = (svg, commits, modifyGraph) => { .attr('width', 12) .attr( 'class', - 'commit ' + - commit.id + - ' commit' + - branchPos[commit.branch].index + - ' ' + - typeClass + - '-inner' + `commit ${commit.id} commit${ + branchPos[commit.branch].index % THEME_COLOR_LIMIT + } ${typeClass}-inner` ); } else if (commit.type === commitType.CHERRY_PICK) { gBullets @@ -147,21 +141,21 @@ const drawCommits = (svg, commits, modifyGraph) => { .attr('cx', x) .attr('cy', y) .attr('r', 10) - .attr('class', 'commit ' + commit.id + ' ' + typeClass); + .attr('class', `commit ${commit.id} ${typeClass}`); gBullets .append('circle') .attr('cx', x - 3) .attr('cy', y + 2) .attr('r', 2.75) .attr('fill', '#fff') - .attr('class', 'commit ' + commit.id + ' ' + typeClass); + .attr('class', `commit ${commit.id} ${typeClass}`); gBullets .append('circle') .attr('cx', x + 3) .attr('cy', y + 2) .attr('r', 2.75) .attr('fill', '#fff') - .attr('class', 'commit ' + commit.id + ' ' + typeClass); + .attr('class', `commit ${commit.id} ${typeClass}`); gBullets .append('line') .attr('x1', x + 3) @@ -169,7 +163,7 @@ const drawCommits = (svg, commits, modifyGraph) => { .attr('x2', x) .attr('y2', y - 5) .attr('stroke', '#fff') - .attr('class', 'commit ' + commit.id + ' ' + typeClass); + .attr('class', `commit ${commit.id} ${typeClass}`); gBullets .append('line') .attr('x1', x - 3) @@ -177,13 +171,16 @@ const drawCommits = (svg, commits, modifyGraph) => { .attr('x2', x) .attr('y2', y - 5) .attr('stroke', '#fff') - .attr('class', 'commit ' + commit.id + ' ' + typeClass); + .attr('class', `commit ${commit.id} ${typeClass}`); } else { const circle = gBullets.append('circle'); circle.attr('cx', x); circle.attr('cy', y); circle.attr('r', commit.type === commitType.MERGE ? 9 : 10); - circle.attr('class', 'commit ' + commit.id + ' commit' + branchPos[commit.branch].index); + circle.attr( + 'class', + `commit ${commit.id} commit${branchPos[commit.branch].index % THEME_COLOR_LIMIT}` + ); if (commit.type === commitType.MERGE) { const circle2 = gBullets.append('circle'); circle2.attr('cx', x); @@ -191,7 +188,9 @@ const drawCommits = (svg, commits, modifyGraph) => { circle2.attr('r', 6); circle2.attr( 'class', - 'commit ' + typeClass + ' ' + commit.id + ' commit' + branchPos[commit.branch].index + `commit ${typeClass} ${commit.id} commit${ + branchPos[commit.branch].index % THEME_COLOR_LIMIT + }` ); } if (commit.type === commitType.REVERSE) { @@ -200,7 +199,9 @@ const drawCommits = (svg, commits, modifyGraph) => { .attr('d', `M ${x - 5},${y - 5}L${x + 5},${y + 5}M${x - 5},${y + 5}L${x + 5},${y - 5}`) .attr( 'class', - 'commit ' + typeClass + ' ' + commit.id + ' commit' + branchPos[commit.branch].index + `commit ${typeClass} ${commit.id} commit${ + branchPos[commit.branch].index % THEME_COLOR_LIMIT + }` ); } } @@ -430,7 +431,7 @@ const drawArrow = (svg, commit1, commit2, allCommits) => { const arrow = svg .append('path') .attr('d', lineDef) - .attr('class', 'arrow arrow' + colorClassNum); + .attr('class', 'arrow arrow' + (colorClassNum % THEME_COLOR_LIMIT)); }; const drawArrows = (svg, commits) => { @@ -460,7 +461,7 @@ const drawBranches = (svg, branches) => { const gitGraphConfig = getConfig().gitGraph; const g = svg.append('g'); branches.forEach((branch, index) => { - let adjustIndexForTheme = index >= 8 ? index - 8 : index; + const adjustIndexForTheme = index % THEME_COLOR_LIMIT; const pos = branchPos[branch.name].pos; const line = g.append('line'); diff --git a/src/diagrams/mindmap/info.spc.js b/src/diagrams/mindmap/info.spc.js new file mode 100644 index 00000000000..69a969fb134 --- /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 00000000000..5a324fbb453 --- /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 00000000000..cbe3c52f8f0 --- /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 00000000000..341e3968cf6 --- /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 00000000000..473b63fcfcd --- /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 00000000000..0b0729813df --- /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 7d68c972380..7d030912774 100644 --- a/src/diagrams/sequence/sequenceDb.js +++ b/src/diagrams/sequence/sequenceDb.js @@ -19,7 +19,7 @@ const notes = []; let diagramTitle = ''; let description = ''; let sequenceNumbersEnabled = false; -let wrapEnabled = false; +let wrapEnabled; export const parseDirective = function (statement, context, type) { mermaidAPI.parseDirective(this, statement, context, type); @@ -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 5f77c902915..5f09e0e2d2a 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 809e3164f77..ee9c5c87eff 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 = {}; @@ -228,7 +229,7 @@ const drawNote = function (elem, noteModel) { textObj.fontWeight = conf.noteFontWeight; textObj.anchor = conf.noteAlign; textObj.textMargin = conf.noteMargin; - textObj.valign = conf.noteAlign; + textObj.valign = 'center'; let textElem = drawText(g, textObj); @@ -341,7 +342,7 @@ const drawMessage = function (diagram, msgModel, lineStarty, diagObj) { textObj.fontSize = conf.messageFontSize; textObj.fontWeight = conf.messageFontWeight; textObj.anchor = conf.messageAlign; - textObj.valign = conf.messageAlign; + textObj.valign = 'center'; textObj.textMargin = conf.wrapPadding; textObj.tspan = false; diff --git a/src/diagrams/sequence/svgDraw.js b/src/diagrams/sequence/svgDraw.js index a00d10169f8..864037c2b05 100644 --- a/src/diagrams/sequence/svgDraw.js +++ b/src/diagrams/sequence/svgDraw.js @@ -193,7 +193,7 @@ export const drawText = function (elem, textData) { case 'start': textData.x = Math.round(textData.x + textData.textMargin); textData.anchor = 'start'; - textData.dominantBaseline = 'text-after-edge'; + textData.dominantBaseline = 'middle'; textData.alignmentBaseline = 'middle'; break; case 'middle': @@ -207,7 +207,7 @@ export const drawText = function (elem, textData) { case 'end': textData.x = Math.round(textData.x + textData.width - textData.textMargin); textData.anchor = 'end'; - textData.dominantBaseline = 'text-before-edge'; + textData.dominantBaseline = 'middle'; textData.alignmentBaseline = 'middle'; break; } @@ -847,9 +847,12 @@ const _drawTextCandidateFunc = (function () { function byTspan(content, g, x, y, width, height, textAttrs, conf) { const { actorFontSize, actorFontFamily, actorFontWeight } = conf; + let _actorFontSize = + actorFontSize && actorFontSize.replace ? actorFontSize.replace('px', '') : actorFontSize; + const lines = content.split(common.lineBreakRegex); for (let i = 0; i < lines.length; i++) { - const dy = i * actorFontSize - (actorFontSize * (lines.length - 1)) / 2; + const dy = i * _actorFontSize - (_actorFontSize * (lines.length - 1)) / 2; const text = g .append('text') .attr('x', x + width / 2) diff --git a/src/diagrams/user-journey/journeyRenderer.js b/src/diagrams/user-journey/journeyRenderer.js index c8ad6278c06..79424cfef68 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 3ea510a7f4f..a708554a8d1 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 7bd06e04ca3..5b16c609a4f 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 addDiagrams 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(); @@ -554,6 +515,7 @@ function initialize(options) { updateRendererConfigs(config); setLogLevel(config.logLevel); + addDiagrams(); } const mermaidAPI = Object.freeze({ diff --git a/src/mermaidAPI.spec.js b/src/mermaidAPI.spec.js index 74b1be0b5b7..e4c2d168daf 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 0d2b4392ce1..db45ab9f623 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 b079beeeb19..31517c43aeb 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 00000000000..824cfec8884 --- /dev/null +++ b/test.js @@ -0,0 +1,5 @@ +function apa() { + // comment's + const a = 1; + return 'apa' + a; +} diff --git a/yarn.lock b/yarn.lock index be9bbd08e0a..18817d66ad9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -70,12 +70,12 @@ "@applitools/utils" "1.3.10" "@applitools/eyes-cypress@^3.25.7": - version "3.26.4" - resolved "https://registry.yarnpkg.com/@applitools/eyes-cypress/-/eyes-cypress-3.26.4.tgz#e1a511cc6ff9f851e29d918cebf9008922e6650d" - integrity sha512-YTlLlNBEwyLKzkKH9kAWz17GkDpI5kkuFIP+Gm4BGjRYawpLpF9GvxlCng0Q+Lli1jMIEIP6tZnjrapHbKqm4A== + version "3.26.6" + resolved "https://registry.yarnpkg.com/@applitools/eyes-cypress/-/eyes-cypress-3.26.6.tgz#a629ef45e1ae37b2234a79fac197f858eae96ccf" + integrity sha512-bj6goVPMdptgRreFcdoOKWJzkebp3R0TYj7G8OGDm6H2cHPQGLwPT+1Z+1Moj9XGy1X6Pgur6TeTtGE4q/QsUw== dependencies: "@applitools/eyes-api" "1.7.4" - "@applitools/eyes-universal" "2.9.6" + "@applitools/eyes-universal" "2.9.7" "@applitools/functional-commons" "1.6.0" "@applitools/logger" "1.1.15" "@applitools/visual-grid-client" "15.13.6" @@ -102,10 +102,10 @@ chalk "3.0.0" tunnel "0.0.6" -"@applitools/eyes-universal@2.9.6": - version "2.9.6" - resolved "https://registry.yarnpkg.com/@applitools/eyes-universal/-/eyes-universal-2.9.6.tgz#65dad010283d5117704137e6c10e4592c6bdd7e1" - integrity sha512-Un6/p8CCI7bdootTDnjpls/mo53Q/3YV8VQQalbkR7Xex63Y4/r4Y/xowoAZb+Q/Iq/BblMwhKFh11dEePFMpA== +"@applitools/eyes-universal@2.9.7": + version "2.9.7" + resolved "https://registry.yarnpkg.com/@applitools/eyes-universal/-/eyes-universal-2.9.7.tgz#0e4e5309e04abbeeb2f29a9e5d63a2feb90de55f" + integrity sha512-pqmgAt2MSSYsT1Iye0motD6x4O9IMF0CCpqKbllU2Om6KSSedT8+c8V0nr+SSrWxKYnvZ6Et1MPs2xYibOywsg== dependencies: "@applitools/execution-grid-client" "1.1.22" "@applitools/eyes-sdk-core" "13.8.12" @@ -1750,49 +1750,49 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@jest/console@^28.1.1": - version "28.1.1" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-28.1.1.tgz#305f8ca50b6e70413839f54c0e002b60a0f2fd7d" - integrity sha512-0RiUocPVFEm3WRMOStIHbRWllG6iW6E3/gUPnf4lkrVFyXIIDeCe+vlKeYyFOMhB2EPE6FLFCNADSOOQMaqvyA== +"@jest/console@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-28.1.3.tgz#2030606ec03a18c31803b8a36382762e447655df" + integrity sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw== dependencies: - "@jest/types" "^28.1.1" + "@jest/types" "^28.1.3" "@types/node" "*" chalk "^4.0.0" - jest-message-util "^28.1.1" - jest-util "^28.1.1" + jest-message-util "^28.1.3" + jest-util "^28.1.3" slash "^3.0.0" -"@jest/core@^28.1.2": - version "28.1.2" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-28.1.2.tgz#eac519b9acbd154313854b8823a47b5c645f785a" - integrity sha512-Xo4E+Sb/nZODMGOPt2G3cMmCBqL4/W2Ijwr7/mrXlq4jdJwcFQ/9KrrJZT2adQRk2otVBXXOz1GRQ4Z5iOgvRQ== +"@jest/core@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-28.1.3.tgz#0ebf2bd39840f1233cd5f2d1e6fc8b71bd5a1ac7" + integrity sha512-CIKBrlaKOzA7YG19BEqCw3SLIsEwjZkeJzf5bdooVnW4bH5cktqe3JX+G2YV1aK5vP8N9na1IGWFzYaTp6k6NA== dependencies: - "@jest/console" "^28.1.1" - "@jest/reporters" "^28.1.2" - "@jest/test-result" "^28.1.1" - "@jest/transform" "^28.1.2" - "@jest/types" "^28.1.1" + "@jest/console" "^28.1.3" + "@jest/reporters" "^28.1.3" + "@jest/test-result" "^28.1.3" + "@jest/transform" "^28.1.3" + "@jest/types" "^28.1.3" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" ci-info "^3.2.0" exit "^0.1.2" graceful-fs "^4.2.9" - jest-changed-files "^28.0.2" - jest-config "^28.1.2" - jest-haste-map "^28.1.1" - jest-message-util "^28.1.1" + jest-changed-files "^28.1.3" + jest-config "^28.1.3" + jest-haste-map "^28.1.3" + jest-message-util "^28.1.3" jest-regex-util "^28.0.2" - jest-resolve "^28.1.1" - jest-resolve-dependencies "^28.1.2" - jest-runner "^28.1.2" - jest-runtime "^28.1.2" - jest-snapshot "^28.1.2" - jest-util "^28.1.1" - jest-validate "^28.1.1" - jest-watcher "^28.1.1" + jest-resolve "^28.1.3" + jest-resolve-dependencies "^28.1.3" + jest-runner "^28.1.3" + jest-runtime "^28.1.3" + jest-snapshot "^28.1.3" + jest-util "^28.1.3" + jest-validate "^28.1.3" + jest-watcher "^28.1.3" micromatch "^4.0.4" - pretty-format "^28.1.1" + pretty-format "^28.1.3" rimraf "^3.0.0" slash "^3.0.0" strip-ansi "^6.0.0" @@ -1807,20 +1807,30 @@ "@types/node" "*" jest-mock "^28.1.1" -"@jest/expect-utils@^28.1.1": - version "28.1.1" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-28.1.1.tgz#d84c346025b9f6f3886d02c48a6177e2b0360587" - integrity sha512-n/ghlvdhCdMI/hTcnn4qV57kQuV9OTsZzH1TTCVARANKhl6hXJqLKUkwX69ftMGpsbpt96SsDD8n8LD2d9+FRw== +"@jest/environment@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-28.1.3.tgz#abed43a6b040a4c24fdcb69eab1f97589b2d663e" + integrity sha512-1bf40cMFTEkKyEf585R9Iz1WayDjHoHqvts0XFYEqyKM3cFWDpeMoqKKTAF9LSYQModPUlh8FKptoM2YcMWAXA== + dependencies: + "@jest/fake-timers" "^28.1.3" + "@jest/types" "^28.1.3" + "@types/node" "*" + jest-mock "^28.1.3" + +"@jest/expect-utils@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-28.1.3.tgz#58561ce5db7cd253a7edddbc051fb39dda50f525" + integrity sha512-wvbi9LUrHJLn3NlDW6wF2hvIMtd4JUl2QNVrjq+IBSHirgfrR3o9RnVtxzdEGO2n9JyIWwHnLfby5KzqBGg2YA== dependencies: jest-get-type "^28.0.2" -"@jest/expect@^28.1.2": - version "28.1.2" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-28.1.2.tgz#0b25acedff46e1e1e5606285306c8a399c12534f" - integrity sha512-HBzyZBeFBiOelNbBKN0pilWbbrGvwDUwAqMC46NVJmWm8AVkuE58NbG1s7DR4cxFt4U5cVLxofAoHxgvC5MyOw== +"@jest/expect@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-28.1.3.tgz#9ac57e1d4491baca550f6bdbd232487177ad6a72" + integrity sha512-lzc8CpUbSoE4dqT0U+g1qODQjBRHPpCPXissXD4mS9+sWQdmmpeJ9zSH1rS1HEkrsMN0fb7nKrJ9giAR1d3wBw== dependencies: - expect "^28.1.1" - jest-snapshot "^28.1.2" + expect "^28.1.3" + jest-snapshot "^28.1.3" "@jest/fake-timers@^28.1.2": version "28.1.2" @@ -1834,25 +1844,37 @@ jest-mock "^28.1.1" jest-util "^28.1.1" -"@jest/globals@^28.1.2": - version "28.1.2" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-28.1.2.tgz#92fab296e337c7309c25e4202fb724f62249d83f" - integrity sha512-cz0lkJVDOtDaYhvT3Fv2U1B6FtBnV+OpEyJCzTHM1fdoTsU4QNLAt/H4RkiwEUU+dL4g/MFsoTuHeT2pvbo4Hg== +"@jest/fake-timers@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-28.1.3.tgz#230255b3ad0a3d4978f1d06f70685baea91c640e" + integrity sha512-D/wOkL2POHv52h+ok5Oj/1gOG9HSywdoPtFsRCUmlCILXNn5eIWmcnd3DIiWlJnpGvQtmajqBP95Ei0EimxfLw== dependencies: - "@jest/environment" "^28.1.2" - "@jest/expect" "^28.1.2" - "@jest/types" "^28.1.1" + "@jest/types" "^28.1.3" + "@sinonjs/fake-timers" "^9.1.2" + "@types/node" "*" + jest-message-util "^28.1.3" + jest-mock "^28.1.3" + jest-util "^28.1.3" -"@jest/reporters@^28.1.2": - version "28.1.2" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-28.1.2.tgz#0327be4ce4d0d9ae49e7908656f89669d0c2a260" - integrity sha512-/whGLhiwAqeCTmQEouSigUZJPVl7sW8V26EiboImL+UyXznnr1a03/YZ2BX8OlFw0n+Zlwu+EZAITZtaeRTxyA== +"@jest/globals@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-28.1.3.tgz#a601d78ddc5fdef542728309894895b4a42dc333" + integrity sha512-XFU4P4phyryCXu1pbcqMO0GSQcYe1IsalYCDzRNyhetyeyxMcIxa11qPNDpVNLeretItNqEmYYQn1UYz/5x1NA== + dependencies: + "@jest/environment" "^28.1.3" + "@jest/expect" "^28.1.3" + "@jest/types" "^28.1.3" + +"@jest/reporters@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-28.1.3.tgz#9adf6d265edafc5fc4a434cfb31e2df5a67a369a" + integrity sha512-JuAy7wkxQZVNU/V6g9xKzCGC5LVXx9FDcABKsSXp5MiKPEE2144a/vXTEDoyzjUpZKfVwp08Wqg5A4WfTMAzjg== dependencies: "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^28.1.1" - "@jest/test-result" "^28.1.1" - "@jest/transform" "^28.1.2" - "@jest/types" "^28.1.1" + "@jest/console" "^28.1.3" + "@jest/test-result" "^28.1.3" + "@jest/transform" "^28.1.3" + "@jest/types" "^28.1.3" "@jridgewell/trace-mapping" "^0.3.13" "@types/node" "*" chalk "^4.0.0" @@ -1865,9 +1887,9 @@ istanbul-lib-report "^3.0.0" istanbul-lib-source-maps "^4.0.0" istanbul-reports "^3.1.3" - jest-message-util "^28.1.1" - jest-util "^28.1.1" - jest-worker "^28.1.1" + jest-message-util "^28.1.3" + jest-util "^28.1.3" + jest-worker "^28.1.3" slash "^3.0.0" string-length "^4.0.1" strip-ansi "^6.0.0" @@ -1897,24 +1919,24 @@ callsites "^3.0.0" graceful-fs "^4.2.9" -"@jest/test-result@^28.1.1": - version "28.1.1" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-28.1.1.tgz#c6f18d1bbb01aa88925dd687872a75f8414b317a" - integrity sha512-hPmkugBktqL6rRzwWAtp1JtYT4VHwv8OQ+9lE5Gymj6dHzubI/oJHMUpPOt8NrdVWSrz9S7bHjJUmv2ggFoUNQ== +"@jest/test-result@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-28.1.3.tgz#5eae945fd9f4b8fcfce74d239e6f725b6bf076c5" + integrity sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg== dependencies: - "@jest/console" "^28.1.1" - "@jest/types" "^28.1.1" + "@jest/console" "^28.1.3" + "@jest/types" "^28.1.3" "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-sequencer@^28.1.1": - version "28.1.1" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-28.1.1.tgz#f594ee2331df75000afe0d1ae3237630ecec732e" - integrity sha512-nuL+dNSVMcWB7OOtgb0EGH5AjO4UBCt68SLP08rwmC+iRhyuJWS9MtZ/MpipxFwKAlHFftbMsydXqWre8B0+XA== +"@jest/test-sequencer@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-28.1.3.tgz#9d0c283d906ac599c74bde464bc0d7e6a82886c3" + integrity sha512-NIMPEqqa59MWnDi1kvXXpYbqsfQmSJsIbnd85mdVGkiDfQ9WQQTXOLsvISUfonmnBT+w85WEgneCigEEdHDFxw== dependencies: - "@jest/test-result" "^28.1.1" + "@jest/test-result" "^28.1.3" graceful-fs "^4.2.9" - jest-haste-map "^28.1.1" + jest-haste-map "^28.1.3" slash "^3.0.0" "@jest/transform@^28.1.2", "@jest/transform@^28.1.3": @@ -1938,12 +1960,33 @@ slash "^3.0.0" write-file-atomic "^4.0.1" -"@jest/types@^28.1.1": - version "28.1.1" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-28.1.1.tgz#d059bbc80e6da6eda9f081f293299348bd78ee0b" - integrity sha512-vRXVqSg1VhDnB8bWcmvLzmg0Bt9CRKVgHPXqYwvWMX3TvAjeO+nRuK6+VdTKCtWOvYlmkF/HqNAL/z+N3B53Kw== +"@jest/transform@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-28.1.3.tgz#59d8098e50ab07950e0f2fc0fc7ec462371281b0" + integrity sha512-u5dT5di+oFI6hfcLOHGTAfmUxFRrjK+vnaP0kkVow9Md/M7V/MxqQMOz/VV25UZO8pzeA9PjfTpOu6BDuwSPQA== dependencies: - "@jest/schemas" "^28.0.2" + "@babel/core" "^7.11.6" + "@jest/types" "^28.1.3" + "@jridgewell/trace-mapping" "^0.3.13" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^1.4.0" + fast-json-stable-stringify "^2.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^28.1.3" + jest-regex-util "^28.0.2" + jest-util "^28.1.3" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + write-file-atomic "^4.0.1" + +"@jest/types@^28.1.1", "@jest/types@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-28.1.3.tgz#b05de80996ff12512bc5ceb1d208285a7d11748b" + integrity sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ== + dependencies: + "@jest/schemas" "^28.1.3" "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^3.0.0" "@types/node" "*" @@ -3087,6 +3130,19 @@ babel-jest@^28.0.3, babel-jest@^28.1.2: graceful-fs "^4.2.9" slash "^3.0.0" +babel-jest@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-28.1.3.tgz#c1187258197c099072156a0a121c11ee1e3917d5" + integrity sha512-epUaPOEWMk3cWX0M/sPvCHHCe9fMFAa/9hXEgKP8nFfNl/jlGkE9ucq9NqkZGXLDduCJYS0UvSlPUwC0S+rH6Q== + dependencies: + "@jest/transform" "^28.1.3" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^28.1.3" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + babel-loader@^8.2.2: version "8.2.5" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.5.tgz#d45f585e654d5a5d90f5350a779d7647c5ed512e" @@ -3125,6 +3181,16 @@ babel-plugin-jest-hoist@^28.1.3: "@types/babel__core" "^7.1.14" "@types/babel__traverse" "^7.0.6" +babel-plugin-jest-hoist@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-28.1.3.tgz#1952c4d0ea50f2d6d794353762278d1d8cca3fbe" + integrity sha512-Ys3tUKAmfnkRUpPdpa98eYrAR0nV+sSFUZZEGuQ2EbFd1y4SOLtD5QDNHAq+bb9a+bbXvYQC4b+ID/THIMcU6Q== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.1.14" + "@types/babel__traverse" "^7.0.6" + babel-plugin-polyfill-corejs2@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz#440f1b70ccfaabc6b676d196239b138f8a2cfba5" @@ -3175,6 +3241,14 @@ babel-preset-jest@^28.1.3: babel-plugin-jest-hoist "^28.1.3" babel-preset-current-node-syntax "^1.0.0" +babel-preset-jest@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-28.1.3.tgz#5dfc20b99abed5db994406c2b9ab94c73aaa419d" + integrity sha512-L+fupJvlWAHbQfn74coNX3zf60LXMJsezNvvx8eIh7iOR1luJ1poxYgQk1F8PYtNq/6QODDHCqsSnTFSWC491A== + dependencies: + babel-plugin-jest-hoist "^28.1.3" + babel-preset-current-node-syntax "^1.0.0" + babelify@^10.0.0: version "10.0.0" resolved "https://registry.yarnpkg.com/babelify/-/babelify-10.0.0.tgz#fe73b1a22583f06680d8d072e25a1e0d1d1d7fb5" @@ -3476,9 +3550,9 @@ camelcase@^6.2.0: integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== caniuse-lite@^1.0.30001332, caniuse-lite@^1.0.30001359: - version "1.0.30001364" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001364.tgz" - integrity sha512-9O0xzV3wVyX0SlegIQ6knz+okhBB5pE0PC40MNdwcipjwpxoUEHL24uJ+gG42cgklPjfO5ZjZPme9FTSN3QT2Q== + version "1.0.30001373" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001373.tgz" + integrity sha512-pJYArGHrPp3TUqQzFYRmP/lwJlj8RCbVe3Gd3eJQkAV8SAC6b19XS9BjMvRdvaS8RMkaTN8ZhoHP6S1y8zzwEQ== caseless@~0.12.0: version "0.12.0" @@ -4244,10 +4318,10 @@ cypress-image-snapshot@^4.0.1: pkg-dir "^3.0.0" term-img "^4.0.0" -cypress@10.3.0: - version "10.3.0" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-10.3.0.tgz#fae8d32f0822fcfb938e79c7c31ef344794336ae" - integrity sha512-txkQWKzvBVnWdCuKs5Xc08gjpO89W2Dom2wpZgT9zWZT5jXxqPIxqP/NC1YArtkpmp3fN5HW8aDjYBizHLUFvg== +cypress@9.7.0: + version "9.7.0" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-9.7.0.tgz#bf55b2afd481f7a113ef5604aa8b693564b5e744" + integrity sha512-+1EE1nuuuwIt/N1KXRR2iWHU+OiIt7H28jJDyyI4tiUftId/DrXYEwoDa5+kH2pki1zxnA0r6HrUGHV5eLbF5Q== dependencies: "@cypress/request" "^2.88.10" "@cypress/xvfb" "^1.2.4" @@ -5496,16 +5570,16 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expect@^28.1.1: - version "28.1.1" - resolved "https://registry.yarnpkg.com/expect/-/expect-28.1.1.tgz#ca6fff65f6517cf7220c2e805a49c19aea30b420" - integrity sha512-/AANEwGL0tWBwzLNOvO0yUdy2D52jVdNXppOqswC49sxMN2cPWsGCQdzuIf9tj6hHoBQzNvx75JUYuQAckPo3w== +expect@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/expect/-/expect-28.1.3.tgz#90a7c1a124f1824133dd4533cce2d2bdcb6603ec" + integrity sha512-eEh0xn8HlsuOBxFgIss+2mX85VAS4Qy3OSkjV7rlBWljtA4oWH37glVGyOZSZvErDT/yBywZdPGwCXuTvSG85g== dependencies: - "@jest/expect-utils" "^28.1.1" + "@jest/expect-utils" "^28.1.3" jest-get-type "^28.0.2" - jest-matcher-utils "^28.1.1" - jest-message-util "^28.1.1" - jest-util "^28.1.1" + jest-matcher-utils "^28.1.3" + jest-message-util "^28.1.3" + jest-util "^28.1.3" express@^4.17.3: version "4.17.3" @@ -7070,94 +7144,94 @@ iterm2-version@^4.1.0: app-path "^3.2.0" plist "^3.0.1" -jest-changed-files@^28.0.2: - version "28.0.2" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-28.0.2.tgz#7d7810660a5bd043af9e9cfbe4d58adb05e91531" - integrity sha512-QX9u+5I2s54ZnGoMEjiM2WeBvJR2J7w/8ZUmH2um/WLAuGAYFQcsVXY9+1YL6k0H/AGUdH8pXUAv6erDqEsvIA== +jest-changed-files@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-28.1.3.tgz#d9aeee6792be3686c47cb988a8eaf82ff4238831" + integrity sha512-esaOfUWJXk2nfZt9SPyC8gA1kNfdKLkQWyzsMlqq8msYSlNKfmZxfRgZn4Cd4MGVUF+7v6dBs0d5TOAKa7iIiA== dependencies: execa "^5.0.0" - throat "^6.0.1" + p-limit "^3.1.0" -jest-circus@^28.1.2: - version "28.1.2" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-28.1.2.tgz#0d5a5623eccb244efe87d1edc365696e4fcf80ce" - integrity sha512-E2vdPIJG5/69EMpslFhaA46WkcrN74LI5V/cSJ59L7uS8UNoXbzTxmwhpi9XrIL3zqvMt5T0pl5k2l2u2GwBNQ== +jest-circus@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-28.1.3.tgz#d14bd11cf8ee1a03d69902dc47b6bd4634ee00e4" + integrity sha512-cZ+eS5zc79MBwt+IhQhiEp0OeBddpc1n8MBo1nMB8A7oPMKEO+Sre+wHaLJexQUj9Ya/8NOBY0RESUgYjB6fow== dependencies: - "@jest/environment" "^28.1.2" - "@jest/expect" "^28.1.2" - "@jest/test-result" "^28.1.1" - "@jest/types" "^28.1.1" + "@jest/environment" "^28.1.3" + "@jest/expect" "^28.1.3" + "@jest/test-result" "^28.1.3" + "@jest/types" "^28.1.3" "@types/node" "*" chalk "^4.0.0" co "^4.6.0" dedent "^0.7.0" is-generator-fn "^2.0.0" - jest-each "^28.1.1" - jest-matcher-utils "^28.1.1" - jest-message-util "^28.1.1" - jest-runtime "^28.1.2" - jest-snapshot "^28.1.2" - jest-util "^28.1.1" - pretty-format "^28.1.1" + jest-each "^28.1.3" + jest-matcher-utils "^28.1.3" + jest-message-util "^28.1.3" + jest-runtime "^28.1.3" + jest-snapshot "^28.1.3" + jest-util "^28.1.3" + p-limit "^3.1.0" + pretty-format "^28.1.3" slash "^3.0.0" stack-utils "^2.0.3" - throat "^6.0.1" -jest-cli@^28.1.2: - version "28.1.2" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-28.1.2.tgz#b89012e5bad14135e71b1628b85475d3773a1bbc" - integrity sha512-l6eoi5Do/IJUXAFL9qRmDiFpBeEJAnjJb1dcd9i/VWfVWbp3mJhuH50dNtX67Ali4Ecvt4eBkWb4hXhPHkAZTw== +jest-cli@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-28.1.3.tgz#558b33c577d06de55087b8448d373b9f654e46b2" + integrity sha512-roY3kvrv57Azn1yPgdTebPAXvdR2xfezaKKYzVxZ6It/5NCxzJym6tUI5P1zkdWhfUYkxEI9uZWcQdaFLo8mJQ== dependencies: - "@jest/core" "^28.1.2" - "@jest/test-result" "^28.1.1" - "@jest/types" "^28.1.1" + "@jest/core" "^28.1.3" + "@jest/test-result" "^28.1.3" + "@jest/types" "^28.1.3" chalk "^4.0.0" exit "^0.1.2" graceful-fs "^4.2.9" import-local "^3.0.2" - jest-config "^28.1.2" - jest-util "^28.1.1" - jest-validate "^28.1.1" + jest-config "^28.1.3" + jest-util "^28.1.3" + jest-validate "^28.1.3" prompts "^2.0.1" yargs "^17.3.1" -jest-config@^28.1.2: - version "28.1.2" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-28.1.2.tgz#ba00ad30caf62286c86e7c1099e915218a0ac8c6" - integrity sha512-g6EfeRqddVbjPVBVY4JWpUY4IvQoFRIZcv4V36QkqzE0IGhEC/VkugFeBMAeUE7PRgC8KJF0yvJNDeQRbamEVA== +jest-config@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-28.1.3.tgz#e315e1f73df3cac31447eed8b8740a477392ec60" + integrity sha512-MG3INjByJ0J4AsNBm7T3hsuxKQqFIiRo/AUqb1q9LRKI5UU6Aar9JHbr9Ivn1TVwfUD9KirRoM/T6u8XlcQPHQ== dependencies: "@babel/core" "^7.11.6" - "@jest/test-sequencer" "^28.1.1" - "@jest/types" "^28.1.1" - babel-jest "^28.1.2" + "@jest/test-sequencer" "^28.1.3" + "@jest/types" "^28.1.3" + babel-jest "^28.1.3" chalk "^4.0.0" ci-info "^3.2.0" deepmerge "^4.2.2" glob "^7.1.3" graceful-fs "^4.2.9" - jest-circus "^28.1.2" - jest-environment-node "^28.1.2" + jest-circus "^28.1.3" + jest-environment-node "^28.1.3" jest-get-type "^28.0.2" jest-regex-util "^28.0.2" - jest-resolve "^28.1.1" - jest-runner "^28.1.2" - jest-util "^28.1.1" - jest-validate "^28.1.1" + jest-resolve "^28.1.3" + jest-runner "^28.1.3" + jest-util "^28.1.3" + jest-validate "^28.1.3" micromatch "^4.0.4" parse-json "^5.2.0" - pretty-format "^28.1.1" + pretty-format "^28.1.3" slash "^3.0.0" strip-json-comments "^3.1.1" -jest-diff@^28.1.1: - version "28.1.1" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-28.1.1.tgz#1a3eedfd81ae79810931c63a1d0f201b9120106c" - integrity sha512-/MUUxeR2fHbqHoMMiffe/Afm+U8U4olFRJ0hiVG2lZatPJcnGxx292ustVu7bULhjV65IYMxRdploAKLbcrsyg== +jest-diff@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-28.1.3.tgz#948a192d86f4e7a64c5264ad4da4877133d8792f" + integrity sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw== dependencies: chalk "^4.0.0" diff-sequences "^28.1.1" jest-get-type "^28.0.2" - pretty-format "^28.1.1" + pretty-format "^28.1.3" jest-docblock@^28.1.1: version "28.1.1" @@ -7166,16 +7240,16 @@ jest-docblock@^28.1.1: dependencies: detect-newline "^3.0.0" -jest-each@^28.1.1: - version "28.1.1" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-28.1.1.tgz#ba5238dacf4f31d9fe23ddc2c44c01e7c23885c4" - integrity sha512-A042rqh17ZvEhRceDMi784ppoXR7MWGDEKTXEZXb4svt0eShMZvijGxzKsx+yIjeE8QYmHPrnHiTSQVhN4nqaw== +jest-each@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-28.1.3.tgz#bdd1516edbe2b1f3569cfdad9acd543040028f81" + integrity sha512-arT1z4sg2yABU5uogObVPvSlSMQlDA48owx07BDPAiasW0yYpYHYOo4HHLz9q0BVzDVU4hILFjzJw0So9aCL/g== dependencies: - "@jest/types" "^28.1.1" + "@jest/types" "^28.1.3" chalk "^4.0.0" jest-get-type "^28.0.2" - jest-util "^28.1.1" - pretty-format "^28.1.1" + jest-util "^28.1.3" + pretty-format "^28.1.3" jest-environment-jsdom@^28.0.2: version "28.1.2" @@ -7191,17 +7265,17 @@ jest-environment-jsdom@^28.0.2: jest-util "^28.1.1" jsdom "^19.0.0" -jest-environment-node@^28.1.2: - version "28.1.2" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-28.1.2.tgz#3e2eb47f6d173b0648d5f7c717cb1c26651d5c8a" - integrity sha512-oYsZz9Qw27XKmOgTtnl0jW7VplJkN2oeof+SwAwKFQacq3CLlG9u4kTGuuLWfvu3J7bVutWlrbEQMOCL/jughw== +jest-environment-node@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-28.1.3.tgz#7e74fe40eb645b9d56c0c4b70ca4357faa349be5" + integrity sha512-ugP6XOhEpjAEhGYvp5Xj989ns5cB1K6ZdjBYuS30umT4CQEETaxSiPcZ/E1kFktX4GkrcM4qu07IIlDYX1gp+A== dependencies: - "@jest/environment" "^28.1.2" - "@jest/fake-timers" "^28.1.2" - "@jest/types" "^28.1.1" + "@jest/environment" "^28.1.3" + "@jest/fake-timers" "^28.1.3" + "@jest/types" "^28.1.3" "@types/node" "*" - jest-mock "^28.1.1" - jest-util "^28.1.1" + jest-mock "^28.1.3" + jest-util "^28.1.3" jest-get-type@^28.0.2: version "28.0.2" @@ -7261,23 +7335,23 @@ jest-image-snapshot@4.2.0: rimraf "^2.6.2" ssim.js "^3.1.1" -jest-leak-detector@^28.1.1: - version "28.1.1" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-28.1.1.tgz#537f37afd610a4b3f4cab15e06baf60484548efb" - integrity sha512-4jvs8V8kLbAaotE+wFR7vfUGf603cwYtFf1/PYEsyX2BAjSzj8hQSVTP6OWzseTl0xL6dyHuKs2JAks7Pfubmw== +jest-leak-detector@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-28.1.3.tgz#a6685d9b074be99e3adee816ce84fd30795e654d" + integrity sha512-WFVJhnQsiKtDEo5lG2mM0v40QWnBM+zMdHHyJs8AWZ7J0QZJS59MsyKeJHWhpBZBH32S48FOVvGyOFT1h0DlqA== dependencies: jest-get-type "^28.0.2" - pretty-format "^28.1.1" + pretty-format "^28.1.3" -jest-matcher-utils@^28.1.1: - version "28.1.1" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-28.1.1.tgz#a7c4653c2b782ec96796eb3088060720f1e29304" - integrity sha512-NPJPRWrbmR2nAJ+1nmnfcKKzSwgfaciCCrYZzVnNoxVoyusYWIjkBMNvu0RHJe7dNj4hH3uZOPZsQA+xAYWqsw== +jest-matcher-utils@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz#5a77f1c129dd5ba3b4d7fc20728806c78893146e" + integrity sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw== dependencies: chalk "^4.0.0" - jest-diff "^28.1.1" + jest-diff "^28.1.3" jest-get-type "^28.0.2" - pretty-format "^28.1.1" + pretty-format "^28.1.3" jest-message-util@^28.1.1: version "28.1.1" @@ -7294,6 +7368,21 @@ jest-message-util@^28.1.1: slash "^3.0.0" stack-utils "^2.0.3" +jest-message-util@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-28.1.3.tgz#232def7f2e333f1eecc90649b5b94b0055e7c43d" + integrity sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^28.1.3" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^28.1.3" + slash "^3.0.0" + stack-utils "^2.0.3" + jest-mock@^28.1.1: version "28.1.1" resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-28.1.1.tgz#37903d269427fa1ef5b2447be874e1c62a39a371" @@ -7302,6 +7391,14 @@ jest-mock@^28.1.1: "@jest/types" "^28.1.1" "@types/node" "*" +jest-mock@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-28.1.3.tgz#d4e9b1fc838bea595c77ab73672ebf513ab249da" + integrity sha512-o3J2jr6dMMWYVH4Lh/NKmDXdosrsJgi4AviS8oXLujcjpCMBb1FMsblDnOXKZKfSiHLxYub1eS0IHuRXsio9eA== + dependencies: + "@jest/types" "^28.1.3" + "@types/node" "*" + jest-pnp-resolver@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" @@ -7312,111 +7409,111 @@ jest-regex-util@^28.0.2: resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-28.0.2.tgz#afdc377a3b25fb6e80825adcf76c854e5bf47ead" integrity sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw== -jest-resolve-dependencies@^28.1.2: - version "28.1.2" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.2.tgz#ca528858e0c6642d5a1dda8fc7cda10230c275bc" - integrity sha512-OXw4vbOZuyRTBi3tapWBqdyodU+T33ww5cPZORuTWkg+Y8lmsxQlVu3MWtJh6NMlKRTHQetF96yGPv01Ye7Mbg== +jest-resolve-dependencies@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.3.tgz#8c65d7583460df7275c6ea2791901fa975c1fe66" + integrity sha512-qa0QO2Q0XzQoNPouMbCc7Bvtsem8eQgVPNkwn9LnS+R2n8DaVDPL/U1gngC0LTl1RYXJU0uJa2BMC2DbTfFrHA== dependencies: jest-regex-util "^28.0.2" - jest-snapshot "^28.1.2" + jest-snapshot "^28.1.3" -jest-resolve@^28.1.1: - version "28.1.1" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-28.1.1.tgz#bc2eaf384abdcc1aaf3ba7c50d1adf01e59095e5" - integrity sha512-/d1UbyUkf9nvsgdBildLe6LAD4DalgkgZcKd0nZ8XUGPyA/7fsnaQIlKVnDiuUXv/IeZhPEDrRJubVSulxrShA== +jest-resolve@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-28.1.3.tgz#cfb36100341ddbb061ec781426b3c31eb51aa0a8" + integrity sha512-Z1W3tTjE6QaNI90qo/BJpfnvpxtaFTFw5CDgwpyE/Kz8U/06N1Hjf4ia9quUhCh39qIGWF1ZuxFiBiJQwSEYKQ== dependencies: chalk "^4.0.0" graceful-fs "^4.2.9" - jest-haste-map "^28.1.1" + jest-haste-map "^28.1.3" jest-pnp-resolver "^1.2.2" - jest-util "^28.1.1" - jest-validate "^28.1.1" + jest-util "^28.1.3" + jest-validate "^28.1.3" resolve "^1.20.0" resolve.exports "^1.1.0" slash "^3.0.0" -jest-runner@^28.1.2: - version "28.1.2" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-28.1.2.tgz#f293409592a62234285a71237e38499a3554e350" - integrity sha512-6/k3DlAsAEr5VcptCMdhtRhOoYClZQmxnVMZvZ/quvPGRpN7OBQYPIC32tWSgOnbgqLXNs5RAniC+nkdFZpD4A== +jest-runner@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-28.1.3.tgz#5eee25febd730b4713a2cdfd76bdd5557840f9a1" + integrity sha512-GkMw4D/0USd62OVO0oEgjn23TM+YJa2U2Wu5zz9xsQB1MxWKDOlrnykPxnMsN0tnJllfLPinHTka61u0QhaxBA== dependencies: - "@jest/console" "^28.1.1" - "@jest/environment" "^28.1.2" - "@jest/test-result" "^28.1.1" - "@jest/transform" "^28.1.2" - "@jest/types" "^28.1.1" + "@jest/console" "^28.1.3" + "@jest/environment" "^28.1.3" + "@jest/test-result" "^28.1.3" + "@jest/transform" "^28.1.3" + "@jest/types" "^28.1.3" "@types/node" "*" chalk "^4.0.0" emittery "^0.10.2" graceful-fs "^4.2.9" jest-docblock "^28.1.1" - jest-environment-node "^28.1.2" - jest-haste-map "^28.1.1" - jest-leak-detector "^28.1.1" - jest-message-util "^28.1.1" - jest-resolve "^28.1.1" - jest-runtime "^28.1.2" - jest-util "^28.1.1" - jest-watcher "^28.1.1" - jest-worker "^28.1.1" + jest-environment-node "^28.1.3" + jest-haste-map "^28.1.3" + jest-leak-detector "^28.1.3" + jest-message-util "^28.1.3" + jest-resolve "^28.1.3" + jest-runtime "^28.1.3" + jest-util "^28.1.3" + jest-watcher "^28.1.3" + jest-worker "^28.1.3" + p-limit "^3.1.0" source-map-support "0.5.13" - throat "^6.0.1" -jest-runtime@^28.1.2: - version "28.1.2" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-28.1.2.tgz#d68f34f814a848555a345ceda23289f14d59a688" - integrity sha512-i4w93OsWzLOeMXSi9epmakb2+3z0AchZtUQVF1hesBmcQQy4vtaql5YdVe9KexdJaVRyPDw8DoBR0j3lYsZVYw== +jest-runtime@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-28.1.3.tgz#a57643458235aa53e8ec7821949e728960d0605f" + integrity sha512-NU+881ScBQQLc1JHG5eJGU7Ui3kLKrmwCPPtYsJtBykixrM2OhVQlpMmFWJjMyDfdkGgBMNjXCGB/ebzsgNGQw== dependencies: - "@jest/environment" "^28.1.2" - "@jest/fake-timers" "^28.1.2" - "@jest/globals" "^28.1.2" + "@jest/environment" "^28.1.3" + "@jest/fake-timers" "^28.1.3" + "@jest/globals" "^28.1.3" "@jest/source-map" "^28.1.2" - "@jest/test-result" "^28.1.1" - "@jest/transform" "^28.1.2" - "@jest/types" "^28.1.1" + "@jest/test-result" "^28.1.3" + "@jest/transform" "^28.1.3" + "@jest/types" "^28.1.3" chalk "^4.0.0" cjs-module-lexer "^1.0.0" collect-v8-coverage "^1.0.0" execa "^5.0.0" glob "^7.1.3" graceful-fs "^4.2.9" - jest-haste-map "^28.1.1" - jest-message-util "^28.1.1" - jest-mock "^28.1.1" + jest-haste-map "^28.1.3" + jest-message-util "^28.1.3" + jest-mock "^28.1.3" jest-regex-util "^28.0.2" - jest-resolve "^28.1.1" - jest-snapshot "^28.1.2" - jest-util "^28.1.1" + jest-resolve "^28.1.3" + jest-snapshot "^28.1.3" + jest-util "^28.1.3" slash "^3.0.0" strip-bom "^4.0.0" -jest-snapshot@^28.1.2: - version "28.1.2" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-28.1.2.tgz#93d31b87b11b384f5946fe0767541496135f8d52" - integrity sha512-wzrieFttZYfLvrCVRJxX+jwML2YTArOUqFpCoSVy1QUapx+LlV9uLbV/mMEhYj4t7aMeE9aSQFHSvV/oNoDAMA== +jest-snapshot@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-28.1.3.tgz#17467b3ab8ddb81e2f605db05583d69388fc0668" + integrity sha512-4lzMgtiNlc3DU/8lZfmqxN3AYD6GGLbl+72rdBpXvcV+whX7mDrREzkPdp2RnmfIiWBg1YbuFSkXduF2JcafJg== dependencies: "@babel/core" "^7.11.6" "@babel/generator" "^7.7.2" "@babel/plugin-syntax-typescript" "^7.7.2" "@babel/traverse" "^7.7.2" "@babel/types" "^7.3.3" - "@jest/expect-utils" "^28.1.1" - "@jest/transform" "^28.1.2" - "@jest/types" "^28.1.1" + "@jest/expect-utils" "^28.1.3" + "@jest/transform" "^28.1.3" + "@jest/types" "^28.1.3" "@types/babel__traverse" "^7.0.6" "@types/prettier" "^2.1.5" babel-preset-current-node-syntax "^1.0.0" chalk "^4.0.0" - expect "^28.1.1" + expect "^28.1.3" graceful-fs "^4.2.9" - jest-diff "^28.1.1" + jest-diff "^28.1.3" jest-get-type "^28.0.2" - jest-haste-map "^28.1.1" - jest-matcher-utils "^28.1.1" - jest-message-util "^28.1.1" - jest-util "^28.1.1" + jest-haste-map "^28.1.3" + jest-matcher-utils "^28.1.3" + jest-message-util "^28.1.3" + jest-util "^28.1.3" natural-compare "^1.4.0" - pretty-format "^28.1.1" + pretty-format "^28.1.3" semver "^7.3.5" jest-util@^28.1.1: @@ -7447,26 +7544,39 @@ jest-validate@^28.1.1: version "28.1.1" resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-28.1.1.tgz#59b7b339b3c85b5144bd0c06ad3600f503a4acc8" integrity sha512-Kpf6gcClqFCIZ4ti5++XemYJWUPCFUW+N2gknn+KgnDf549iLul3cBuKVe1YcWRlaF8tZV8eJCap0eECOEE3Ug== + dependencies: - "@jest/types" "^28.1.1" + "@jest/types" "^28.1.3" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-28.1.3.tgz#e322267fd5e7c64cea4629612c357bbda96229df" + integrity sha512-SZbOGBWEsaTxBGCOpsRWlXlvNkvTkY0XxRfh7zYmvd8uL5Qzyg0CHAXiXKROflh801quA6+/DsT4ODDthOC/OA== + dependencies: + "@jest/types" "^28.1.3" camelcase "^6.2.0" chalk "^4.0.0" jest-get-type "^28.0.2" leven "^3.1.0" - pretty-format "^28.1.1" + pretty-format "^28.1.3" -jest-watcher@^28.1.1: - version "28.1.1" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-28.1.1.tgz#533597fb3bfefd52b5cd115cd916cffd237fb60c" - integrity sha512-RQIpeZ8EIJMxbQrXpJQYIIlubBnB9imEHsxxE41f54ZwcqWLysL/A0ZcdMirf+XsMn3xfphVQVV4EW0/p7i7Ug== +jest-watcher@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-28.1.3.tgz#c6023a59ba2255e3b4c57179fc94164b3e73abd4" + integrity sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g== dependencies: - "@jest/test-result" "^28.1.1" - "@jest/types" "^28.1.1" + "@jest/test-result" "^28.1.3" + "@jest/types" "^28.1.3" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" emittery "^0.10.2" - jest-util "^28.1.1" + jest-util "^28.1.3" string-length "^4.0.1" jest-worker@^27.4.5: @@ -7497,14 +7607,14 @@ jest-worker@^28.1.3: supports-color "^8.0.0" jest@^28.0.3: - version "28.1.2" - resolved "https://registry.yarnpkg.com/jest/-/jest-28.1.2.tgz#451ff24081ce31ca00b07b60c61add13aa96f8eb" - integrity sha512-Tuf05DwLeCh2cfWCQbcz9UxldoDyiR1E9Igaei5khjonKncYdc6LDfynKCEWozK0oLE3GD+xKAo2u8x/0s6GOg== + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest/-/jest-28.1.3.tgz#e9c6a7eecdebe3548ca2b18894a50f45b36dfc6b" + integrity sha512-N4GT5on8UkZgH0O5LUavMRV1EDEhNTL0KEfRmDIeZHSV7p2XgLoY9t9VDUgL6o+yfdgYHVxuz81G8oB9VG5uyA== dependencies: - "@jest/core" "^28.1.2" - "@jest/types" "^28.1.1" + "@jest/core" "^28.1.3" + "@jest/types" "^28.1.3" import-local "^3.0.2" - jest-cli "^28.1.2" + jest-cli "^28.1.3" jison-lex@0.3.x: version "0.3.4" @@ -8967,7 +9077,7 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^3.0.2: +p-limit@^3.0.2, p-limit@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== @@ -9380,6 +9490,16 @@ pretty-format@^28.1.1: ansi-styles "^5.0.0" react-is "^18.0.0" +pretty-format@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-28.1.3.tgz#c9fba8cedf99ce50963a11b27d982a9ae90970d5" + integrity sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q== + dependencies: + "@jest/schemas" "^28.1.3" + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^18.0.0" + process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -10923,11 +11043,6 @@ throat@5.0.0: resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA== -throat@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.1.tgz#d514fedad95740c12c2d7fc70ea863eb51ade375" - integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w== - throttleit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c"