diff --git a/.esbuild/esbuild.cjs b/.esbuild/esbuild.cjs index 5cdee62c7..e38951bdb 100644 --- a/.esbuild/esbuild.cjs +++ b/.esbuild/esbuild.cjs @@ -1,4 +1,4 @@ -const { esmBuild, umdBuild } = require('./util.cjs'); +const { esmBuild, esmCoreBuild, iifeBuild } = require('./util.cjs'); const { build } = require('esbuild'); const handler = (e) => { @@ -7,8 +7,14 @@ const handler = (e) => { }; const watch = process.argv.includes('--watch'); -build(umdBuild({ minify: false, watch })).catch(handler); +// mermaid.js +build(iifeBuild({ minify: false, watch })).catch(handler); +// mermaid.esm.mjs build(esmBuild({ minify: false, watch })).catch(handler); +// mermaid.min.js build(esmBuild()).catch(handler); -build(umdBuild()).catch(handler); +// mermaid.esm.min.mjs +build(iifeBuild()).catch(handler); +// mermaid.core.mjs (node_modules unbundled) +build(esmCoreBuild()).catch(handler); diff --git a/.esbuild/serve.cjs b/.esbuild/serve.cjs index 13eba401d..c54ff1e9f 100644 --- a/.esbuild/serve.cjs +++ b/.esbuild/serve.cjs @@ -1,7 +1,7 @@ const esbuild = require('esbuild'); const http = require('http'); const path = require('path'); -const { umdBuild } = require('./util.cjs'); +const { iifeBuild } = require('./util.cjs'); // Start esbuild's server on a random local port esbuild @@ -9,7 +9,7 @@ esbuild { servedir: path.join(__dirname, '..'), }, - umdBuild({ minify: false }) + iifeBuild({ minify: false }) ) .then((result) => { // The result tells us where esbuild's local server is diff --git a/.esbuild/util.cjs b/.esbuild/util.cjs index 7fc77d0c5..0cddb7e45 100644 --- a/.esbuild/util.cjs +++ b/.esbuild/util.cjs @@ -1,5 +1,6 @@ const { Generator } = require('jison'); const fs = require('fs'); +const { dependencies } = require('../package.json'); /** @typedef {import('esbuild').BuildOptions} Options */ @@ -18,33 +19,68 @@ const buildOptions = (override = {}) => { tsconfig: 'tsconfig.json', resolveExtensions: ['.ts', '.js', '.json', '.jison'], external: ['require', 'fs', 'path'], - entryPoints: ['src/mermaid.ts'], - outfile: 'dist/mermaid.min.js', + outdir: 'dist', plugins: [jisonPlugin], sourcemap: 'external', ...override, }; }; +const getOutFiles = (extension) => { + return { + [`mermaid${extension}`]: 'src/mermaid.ts', + [`diagramAPI${extension}`]: 'src/diagram-api/diagramAPI.ts', + }; +}; /** - * @param {Options} override - * @returns {Options} + * Build options for mermaid.esm.* build. + * + * For ESM browser use. + * + * @param {Options} override - Override options. + * @returns {Options} ESBuild build options. */ exports.esmBuild = (override = { minify: true }) => { return buildOptions({ format: 'esm', - outfile: `dist/mermaid.esm${override.minify ? '.min' : ''}.mjs`, + entryPoints: getOutFiles(`.esm${override.minify ? '.min' : ''}`), + outExtension: { '.js': '.mjs' }, ...override, }); }; /** - * @param {Options} override - * @returns {Options} + * Build options for mermaid.core.* build. + * + * This build does not bundle `./node_modules/`, as it is designed to be used with + * Webpack/ESBuild/Vite to use mermaid inside an app/website. + * + * @param {Options} override - Override options. + * @returns {Options} ESBuild build options. */ -exports.umdBuild = (override = { minify: true }) => { +exports.esmCoreBuild = (override) => { return buildOptions({ - outfile: `dist/mermaid${override.minify ? '.min' : ''}.js`, + format: 'esm', + entryPoints: getOutFiles(`.core`), + outExtension: { '.js': '.mjs' }, + external: ['require', 'fs', 'path', ...Object.keys(dependencies)], + platform: 'neutral', + ...override, + }); +}; + +/** + * Build options for mermaid.js build. + * + * For IIFE browser use (where ESM is not yet supported). + * + * @param {Options} override - Override options. + * @returns {Options} ESBuild build options. + */ +exports.iifeBuild = (override = { minify: true }) => { + return buildOptions({ + entryPoints: getOutFiles(override.minify ? '.min' : ''), + format: 'iife', ...override, }); }; @@ -55,7 +91,9 @@ const jisonPlugin = { build.onLoad({ filter: /\.jison$/ }, async (args) => { // Load the file from the file system const source = await fs.promises.readFile(args.path, 'utf8'); - const contents = new Generator(source, { 'token-stack': true }).generate(); + const contents = new Generator(source, { 'token-stack': true }).generate({ + moduleMain: '() => {}', // disable moduleMain (default one requires Node.JS modules) + }); return { contents, warnings: [] }; }); }, diff --git a/.eslintignore b/.eslintignore index 9d8891de0..60c278861 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,5 @@ dist/** .github/** docs/Setup.md +cypress.config.js +cypress/plugins/index.js diff --git a/.eslintrc.json b/.eslintrc.json index 4c702fcbc..02753280c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -15,6 +15,7 @@ }, "extends": [ "eslint:recommended", + "plugin:@typescript-eslint/recommended", "plugin:jsdoc/recommended", "plugin:json/recommended", "plugin:markdown/recommended", @@ -22,6 +23,7 @@ ], "plugins": ["@typescript-eslint", "html", "jest", "jsdoc", "json"], "rules": { + "no-console": "error", "no-prototype-builtins": "off", "no-unused-vars": "off", "jsdoc/check-indentation": "off", @@ -35,6 +37,16 @@ "jsdoc/require-returns": "off", "jsdoc/require-returns-description": "off", "cypress/no-async-tests": "off", + "@typescript-eslint/ban-ts-comment": [ + "error", + { + "ts-expect-error": "allow-with-description", + "ts-ignore": "allow-with-description", + "ts-nocheck": "allow-with-description", + "ts-check": "allow-with-description", + "minimumDescriptionLength": 10 + } + ], "json/*": ["error", "allowComments"], "no-empty": ["error", { "allowEmptyCatch": true }] }, @@ -45,6 +57,19 @@ "no-undef": "off", "jsdoc/require-jsdoc": "off" } + }, + { + "files": ["./cypress/**", "./demos/**"], + "rules": { + "no-console": "off" + } + }, + { + "files": ["./**/*.spec.{ts,js}", "./cypress/**", "./demos/**", "./**/docs/**"], + "rules": { + "jsdoc/require-jsdoc": "off", + "@typescript-eslint/no-unused-vars": "off" + } } ] } diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index c7015dbe7..396ff4e6e 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -14,7 +14,7 @@ jobs: name: check tests if: github.repository_owner == 'mermaid-js' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 - uses: testomatio/check-tests@stable diff --git a/.github/workflows/e2e b/.github/workflows/e2e index 5b716e429..338869490 100644 --- a/.github/workflows/e2e +++ b/.github/workflows/e2e @@ -36,3 +36,9 @@ jobs: run: yarn e2e env: CYPRESS_CACHE_FOLDER: .cache/Cypress + + - name: Upload Coverage to Coveralls + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + flag-name: e2e diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 44e2f4cb1..e567aba89 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -40,3 +40,18 @@ jobs: - name: Verify Docs run: yarn docs:verify + + - name: Check no `console.log()` in .jison files + # ESLint can't parse .jison files directly + # In the future, it might be worth making a `eslint-plugin-jison`, so + # that this will be built into the `yarn lint` command. + run: | + shopt -s globstar + mkdir -p tmp/ + for jison_file in src/**/*.jison; do + outfile="tmp/$(basename -- "$jison_file" .jison)-jison.js" + echo "Converting $jison_file to $outfile" + # default module-type (CJS) always adds a console.log() + yarn jison "$jison_file" --outfile "$outfile" --module-type "amd" + done + yarn eslint --no-eslintrc --rule no-console:error --parser "@babel/eslint-parser" "./tmp/*-jison.js" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 97aa0a377..08c35befa 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,3 +32,12 @@ jobs: - name: Run Unit Tests run: | yarn ci --coverage + + - name: Upload Coverage to Coveralls + # it feels a bit weird to use @master, but that's what the docs use + # (coveralls also doesn't publish a @v1 we can use) + # https://github.com/marketplace/actions/coveralls-github-action + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + flag-name: unit diff --git a/.lintstagedrc.json b/.lintstagedrc.json index db16ea99a..b88abda4b 100644 --- a/.lintstagedrc.json +++ b/.lintstagedrc.json @@ -1,4 +1,5 @@ { "src/docs/**": ["yarn docs:build --git"], - "*.{ts,js,json,html,md}": ["eslint --fix", "prettier --write"] + "src/docs.mts": ["yarn docs:build --git"], + "*.{ts,js,json,html,md,mts}": ["eslint --fix", "prettier --write"] } diff --git a/.webpack/webpack.config.babel.js b/.webpack/webpack.config.babel.js index 9dfd834b7..15760b19b 100644 --- a/.webpack/webpack.config.babel.js +++ b/.webpack/webpack.config.babel.js @@ -3,43 +3,44 @@ import nodeExternals from 'webpack-node-externals'; import baseConfig from './webpack.config.base'; export default (_env, args) => { - switch (args.mode) { - case 'development': - return [ - baseConfig, - merge(baseConfig, { - externals: [nodeExternals()], - output: { - filename: '[name].core.js', - }, - }), - ]; - case 'production': - return [ - // umd - merge(baseConfig, { - output: { - filename: '[name].min.js', - }, - }), - // esm - mergeWithCustomize({ - customizeObject: customizeObject({ - 'output.library': 'replace', - }), - })(baseConfig, { - experiments: { - outputModule: true, - }, - output: { - library: { - type: 'module', - }, - filename: '[name].esm.min.mjs', - }, - }), - ]; - default: - throw new Error('No matching configuration was found!'); - } + return [ + // non-minified + merge(baseConfig, { + optimization: { + minimize: false, + }, + }), + // core [To be used by webpack/esbuild/vite etc to bundle mermaid] + merge(baseConfig, { + externals: [nodeExternals()], + output: { + filename: '[name].core.js', + }, + optimization: { + minimize: false, + }, + }), + // umd + merge(baseConfig, { + output: { + filename: '[name].min.js', + }, + }), + // esm + mergeWithCustomize({ + customizeObject: customizeObject({ + 'output.library': 'replace', + }), + })(baseConfig, { + experiments: { + outputModule: true, + }, + output: { + library: { + type: 'module', + }, + filename: '[name].esm.min.mjs', + }, + }), + ]; }; diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fb7f3bf5a..8171aeca9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,8 +20,8 @@ yarn test We make all changes via pull requests. As we have many pull requests from developers new to mermaid, the current approach is to have _knsv, Knut Sveidqvist_ as a main reviewer of changes and merging pull requests. More precisely like this: - Large changes reviewed by knsv or other developer asked to review by knsv -- Smaller low-risk changes like dependencies, documentation etc can be merged by active collaborators -- documentation (updates to the docs folder is also allowed via direct commits) +- Smaller low-risk changes like dependencies, documentation, etc. can be merged by active collaborators +- Documentation (updates to the `src/docs` folder is also allowed via direct commits) To commit code, create a branch, let it start with the type like feature or bug followed by the issue number for reference and some describing text. @@ -37,12 +37,28 @@ Another: Less strict here, it is OK to commit directly in the `develop` branch if you are a collaborator. -The documentation is located in the `docs` directory and published using GitHub Pages. -The documentation site is powered by [Docsify](https://docsify.js.org), a simple documentation site generator. +The documentation is written in **Markdown**. For more information about Markdown [see the GitHub Markdown help page](https://help.github.com/en/github/writing-on-github/basic-writing-and-formatting-syntax). -The documentation is written in Markdown, for more information about Markdown [see the GitHub Markdown help page](https://help.github.com/en/github/writing-on-github/basic-writing-and-formatting-syntax). +### Documentation source files are in /src/docs -If you want to preview the documentation site on your machine, you need to install `docsify-cli`: +The source files for the project documentation are located in the `/src/docs` directory. This is where you should make changes. +The files under `/src/docs` are processed to generate the published documentation, and the resulting files are put into the `/docs` directory. + +```mermaid +flowchart LR + classDef default fill:#fff,color:black,stroke:black + + source["files in /src/docs\n(changes should be done here)"] -- automatic processing\nto generate the final documentation--> published["files in /docs\ndisplayed on the official documentation site"] + +``` + +**_DO NOT CHANGE FILES IN `/docs`_** + +### The official documentation site + +**[The mermaid documentation site](https://mermaid-js.github.io/mermaid/) is powered by [Docsify](https://docsify.js.org), a simple documentation site generator.** + +If you want to preview the whole documentation site on your machine, you need to install `docsify-cli`: ```sh $ npm i docsify-cli -g @@ -121,9 +137,13 @@ it('should render forks and joins', () => { Finally, if it is not in the documentation, no one will know about it and then **no one will use it**. Wouldn't that be sad? With all the effort that was put into the feature? -The docs are located in the docs folder and are ofc written in markdown. Just pick the right section and start typing. If you want to add to the structure as in adding a new section and new file you do that via the \_navbar.md. +The source files for documentation are in `/src/docs` and are written in markdown. Just pick the right section and start typing. See the [Committing Documentation](#committing-documentation) section for more about how the documentation is generated. -The changes in master is reflected in https://mermaid-js.github.io/mermaid/ once released the updates are committed to https://mermaid-js.github.io/#/ +#### Adding to or changing the documentation organization + +If you want to add a new section or change the organization (structure), then you need to make sure to **change the side navigation** in `src/docs/_sidebar.md`. + +When changes are committed and then released, they become part of the `master` branch and become part of the published documentation on https://mermaid-js.github.io/mermaid/ ## Last words diff --git a/cypress.config.js b/cypress.config.js index 044c5d523..d7c9831d4 100644 --- a/cypress.config.js +++ b/cypress.config.js @@ -1,3 +1,5 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ + const { defineConfig } = require('cypress'); const { addMatchImageSnapshotPlugin } = require('cypress-image-snapshot/plugin'); require('@applitools/eyes-cypress')(module); diff --git a/cypress/platform/bundle-test.js b/cypress/platform/bundle-test.js index 22f4fe93c..373f8741a 100644 --- a/cypress/platform/bundle-test.js +++ b/cypress/platform/bundle-test.js @@ -1,4 +1,4 @@ -import mermaid from '../../dist/mermaid'; +import mermaid from '../../dist/mermaid.core'; let code = `flowchart LR Power_Supply --> Transmitter_A diff --git a/cypress/platform/knsv.html b/cypress/platform/knsv.html index c98ce70c8..a06667c1f 100644 --- a/cypress/platform/knsv.html +++ b/cypress/platform/knsv.html @@ -39,6 +39,14 @@
+flowchart LR
+  a ---
+    
+
+flowchart LR
+  a2 ---
+    
+
 flowchart LR
   classDef aPID stroke:#4e4403,fill:#fdde29,color:#4e4403,rx:5px,ry:5px;
   classDef crm stroke:#333333,fill:#DCDCDC,color:#333333,rx:5px,ry:5px;
@@ -73,7 +81,31 @@ flowchart TD
     
 flowchart TD
-id
+
+  release-branch[Create Release Branch]:::relClass
+  develop-branch[Update Develop Branch]:::relClass
+  github-release-draft[GitHub Release Draft]:::relClass
+  trigger-pipeline[Trigger Jenkins pipeline]:::fixClass
+  github-release[GitHub Release]:::postClass
+
+  build-ready --> release-branch
+  build-ready --> develop-branch
+  release-branch --> jenkins-release-build
+  jenkins-release-build --> github-release-draft
+  jenkins-release-build --> install-release
+  install-release --> verify-release
+  jenkins-release-build --> announce
+  github-release-draft --> github-release
+  verify-release --> verify-check
+  verify-check -- Yes --> github-release
+  verify-check -- No --> release-fix
+  release-fix --> release-branch-pr
+  verify-check -- No --> delete-artifacts
+  release-branch-pr --> trigger-pipeline
+  delete-artifacts --> trigger-pipeline
+  trigger-pipeline --> jenkins-release-build
+
+
     
 flowchart LR
@@ -99,7 +131,7 @@ flowchart TD
       class A someclass;
       class C someclass;
     
-
+    
    sequenceDiagram
       title: My Sequence Diagram Title
       accTitle: My Acc Sequence Diagram
@@ -109,14 +141,14 @@ flowchart TD
       John-->>Alice: Great!
       Alice-)John: See you later!
     
-
+    
 graph TD
     A -->|000| B
     B -->|111| C
 
     linkStyle 1 stroke:#ff3,stroke-width:4px,color:red;
     
-
+    
   journey
       accTitle: My User Journey Diagram
       accDescr: My User Journey Diagram Description
@@ -130,10 +162,10 @@ graph TD
         Go downstairs: 5: Me
         Sit down: 5: Me
     
-
+    
         info
     
-
+    
 requirementDiagram
       accTitle: My req Diagram
       accDescr: My req Diagram Description
@@ -174,7 +206,7 @@ requirementDiagram
     test_req - contains -> test_req3
     test_req <- copies - test_entity2
     
-
+    
 gantt
     dateFormat  YYYY-MM-DD
     title       Adding GANTT diagram functionality to mermaid
@@ -206,7 +238,7 @@ gantt
     Add gantt diagram to demo page      :20h
     Add another diagram to demo page    :48h
     
-
+    
 stateDiagram
   state Active {
     Idle
@@ -234,7 +266,7 @@ stateDiagram
           end
           B ->> A: Return
     
-
+    
 classDiagram
 accTitle: My class diagram
 accDescr: My class diagram Description
@@ -259,7 +291,7 @@ class Class10 {
         A->>Bob: Hola
         Bob-->A: Pasten !
     
-
+    
       gitGraph
        commit id: "ZERO"
        branch develop
@@ -288,7 +320,7 @@ flowchart TD
       C -->|Two| E[iPhone]
       C -->|Three| F[fa:fa-car Car]
     
-
+    
         classDiagram
           Animal "1" <|-- Duck
           Animal <|-- Fish
@@ -311,7 +343,7 @@ flowchart TD
             +run()
           }
     
-
+    
         erDiagram
     CAR ||--o{ NAMED-DRIVER : allows
     CAR {
@@ -357,6 +389,11 @@ flowchart TD
 
         document.getElementsByTagName('body')[0].appendChild(div);
       }
+
+      mermaid.parseError = function (err, hash) {
+        console.error('In parse error:');
+        console.error(err);
+      };
     
   
 
diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html
index 94b99602a..3be7bfb73 100644
--- a/cypress/platform/knsv2.html
+++ b/cypress/platform/knsv2.html
@@ -47,9 +47,17 @@
     
Security check
-sequenceDiagram
-  Nothing:Valid;
-      
+ flowchart TD + A[myClass1] --> B[default] & C[default] + B[default] & C[default] --> D[myClass2] + classDef default stroke-width:2px,fill:none,stroke:silver + classDef node color:red + classDef myClass1 color:#0000ff + classDef myClass2 stroke:#0000ff,fill:#ccccff + class A myClass1 + class D myClass2 +
@@ -59,6 +67,7 @@ sequenceDiagram }; mermaid.initialize({ startOnLoad: false, + logLevel: 0, // themeVariables: {relationLabelColor: 'red'} }); function callback() { diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js index 2c98a54ad..ca5a37d5a 100644 --- a/cypress/plugins/index.js +++ b/cypress/plugins/index.js @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ // *********************************************************** // This example plugins/index.js can be used to load plugins // diff --git a/demos/index.html b/demos/index.html index 58234c6d7..8ef343ef1 100644 --- a/demos/index.html +++ b/demos/index.html @@ -1083,7 +1083,9 @@ Enterprise_Boundary(b0, "BankBoundary0") {
-A summary of all options and their defaults is found [here][4]. +A summary of all options and their defaults is found [here][3]. A description of each option follows below. ## theme @@ -224,7 +221,7 @@ Default value: true Decides which rendering engine that is to be used for the rendering. Legal values are: dagre-d3 dagre-wrapper - wrapper for dagre implemented in mermaid -Default value: 'dagre-d3' +Default value: 'dagre-wrapper' ## sequence @@ -367,7 +364,8 @@ Default value: true **Notes:** -This will display arrows that start and begin at the same node as right angles, rather than a curve +This will display arrows that start and begin at the same node as right angles, rather than a +curve Default value: false @@ -719,7 +717,8 @@ Default value: true **Notes:** -This will display arrows that start and begin at the same node as right angles, rather than a curves +This will display arrows that start and begin at the same node as right angles, rather than a +curves Default value: false @@ -1411,10 +1410,10 @@ This sets the auto-wrap padding for the diagram (sides only) ### Parameters -- `text` **[string][5]** -- `parseError` **[Function][6]?** +- `text` **[string][4]** +- `parseError` **[Function][5]?** -Returns **[boolean][7]** +Returns **[boolean][6]** ## setSiteConfig @@ -1433,7 +1432,7 @@ function _Default value: At default, will mirror Global Config_ - `conf` **MermaidConfig** The base currentConfig to use as siteConfig -Returns **[object][8]** The siteConfig +Returns **[object][7]** The siteConfig ## getSiteConfig @@ -1445,7 +1444,7 @@ Returns **[object][8]** The siteConfig **Notes**: Returns **any** values in siteConfig. -Returns **[object][8]** The siteConfig +Returns **[object][7]** The siteConfig ## setConfig @@ -1484,10 +1483,10 @@ $(function () { ### Parameters -- `id` **[string][5]** The id of the element to be rendered -- `text` **[string][5]** The graph definition -- `cb` **function (svgCode: [string][5], bindFunctions: function (element: [Element][9]): void): void** -- `container` **[Element][9]** Selector to element in which a div with the graph temporarily will be +- `id` **[string][4]** The id of the element to be rendered +- `text` **[string][4]** The graph definition +- `cb` **function (svgCode: [string][4], bindFunctions: function (element: [Element][8]): void): void** +- `container` **[Element][8]** Selector to element in which a div with the graph temporarily will be inserted. If one is provided a hidden div will be inserted in the body of the page instead. The element will be removed when rendering is completed. @@ -1526,7 +1525,7 @@ Pushes in a directive to the configuration ### Parameters -- `directive` **[object][8]** The directive to push in +- `directive` **[object][7]** The directive to push in ## reset @@ -1620,12 +1619,11 @@ Returns **void** ``` -[1]: https://github.com/mermaid-js/mermaid/blob/develop/src/mermaidAPI.js -[2]: Setup.md?id=render -[3]: 8.6.0_docs.md -[4]: #mermaidapi-configuration-defaults -[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String -[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function -[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean -[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object -[9]: https://developer.mozilla.org/docs/Web/API/Element +[1]: Setup.md?id=render +[2]: 8.6.0_docs.md +[3]: #mermaidapi-configuration-defaults +[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String +[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function +[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean +[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object +[8]: https://developer.mozilla.org/docs/Web/API/Element diff --git a/docs/Tutorials.md b/docs/Tutorials.md index 0211d35d0..0eac9ccfe 100644 --- a/docs/Tutorials.md +++ b/docs/Tutorials.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Tutorials diff --git a/docs/_navbar.md b/docs/_navbar.md index 6ec266461..222926fc4 100644 --- a/docs/_navbar.md +++ b/docs/_navbar.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. - Getting started diff --git a/docs/_sidebar.md b/docs/_sidebar.md index 40e46d835..a97bd8d72 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. - 📔 Introduction diff --git a/docs/accessibility.md b/docs/accessibility.md index 820fe364a..70ebef9d1 100644 --- a/docs/accessibility.md +++ b/docs/accessibility.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Accessibility Options diff --git a/docs/breakingChanges.md b/docs/breakingChanges.md index f5bb4ddb3..01088b9dc 100644 --- a/docs/breakingChanges.md +++ b/docs/breakingChanges.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Breaking changes diff --git a/docs/c4c.md b/docs/c4c.md index 1b4251785..48688f1a0 100644 --- a/docs/c4c.md +++ b/docs/c4c.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # C4 Diagrams diff --git a/docs/classDiagram.md b/docs/classDiagram.md index 1576aaa17..6c9ae96fe 100644 --- a/docs/classDiagram.md +++ b/docs/classDiagram.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Class diagrams diff --git a/docs/developer-docs/configuration.md b/docs/developer-docs/configuration.md index a10954416..e764e200a 100644 --- a/docs/developer-docs/configuration.md +++ b/docs/developer-docs/configuration.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Configuration diff --git a/docs/development.md b/docs/development.md index d5cbe891e..70762be86 100644 --- a/docs/development.md +++ b/docs/development.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Development and Contribution 🙌 @@ -8,7 +8,7 @@ So you want to help? That's great! Here are a few things to get you started on the right path. -**The Docs Structure is dictated by [sidebar.md](https://github.com/mermaid-js/mermaid/edit/develop/docs/_sidebar.md)** +**The Docs Structure is dictated by [sidebar.md](https://github.com/mermaid-js/mermaid/edit/develop/src/docs/_sidebar.md)** **Note: Commits and Pull Requests should be directed to the develop branch.** @@ -46,9 +46,9 @@ Start with the type, such as **feature** or **bug**, followed by the issue numbe If it is not in the documentation, it's like it never happened. Wouldn't that be sad? With all the effort that was put into the feature? -The docs are located in the `src/docs` folder and are written in Markdown. Just pick the right section and start typing. If you want to propose changes to the structure of the documentation, such as adding a new section or a new file you do that via the **[sidebar](https://github.com/mermaid-js/mermaid/edit/develop/docs/_sidebar.md)**. +The docs are located in the `src/docs` folder and are written in Markdown. Just pick the right section and start typing. If you want to propose changes to the structure of the documentation, such as adding a new section or a new file you do that via the **[sidebar](https://github.com/mermaid-js/mermaid/edit/develop/src/docs/_sidebar.md)**. -> **All the documents displayed in the github.io page are listed in [sidebar.md](https://github.com/mermaid-js/mermaid/edit/develop/docs/_sidebar.md)**. +> **All the documents displayed in the GitHub.io page are listed in [sidebar.md](https://github.com/mermaid-js/mermaid/edit/develop/src/docs/_sidebar.md)**. The contents of are based on the docs from the `master` branch. Updates committed to the `master` branch are reflected in the [Mermaid Docs](https://mermaid-js.github.io/mermaid/) once released. @@ -60,7 +60,7 @@ The documentation is located in the `src/docs` directory and organized according The `docs` folder will be automatically generated when committing to `src/docs` and should not be edited manually. -We encourage contributions to the documentation at [mermaid-js/mermaid/docs](https://github.com/mermaid-js/mermaid/tree/develop/docs). We publish documentation using GitHub Pages with [Docsify](https://www.youtube.com/watch?v=TV88lp7egMw&t=3s) +We encourage contributions to the documentation at [mermaid-js/mermaid/src/docs](https://github.com/mermaid-js/mermaid/tree/develop/src/docs). We publish documentation using GitHub Pages with [Docsify](https://www.youtube.com/watch?v=TV88lp7egMw&t=3s) ### Add Unit Tests for Parsing @@ -73,7 +73,7 @@ This tests the rendering and visual appearance of the diagrams. This ensures tha To start working with the e2e tests: 1. Run `yarn dev` to start the dev server -2. Start **Cypress** by running `cypress open` in the **mermaid** folder.\ +2. Start **Cypress** by running `cypress open` in the **mermaid** folder. (Make sure you have path to Cypress in order, the binary is located in `node_modules/.bin`). The rendering tests are very straightforward to create. There is a function `imgSnapshotTest`, which takes a diagram in text form and the mermaid options, and it renders that diagram in Cypress. @@ -114,7 +114,7 @@ Markdown is used to format the text, for more information about Markdown [see th To edit Docs on your computer: -1. Find the Markdown file (.md) to edit in the [mermaid-js/mermaid/docs](https://github.com/mermaid-js/mermaid/tree/develop/docs) directory in the `develop` branch. +1. Find the Markdown file (.md) to edit in the [mermaid-js/mermaid/src/docs](https://github.com/mermaid-js/mermaid/tree/develop/src/docs) directory in the `develop` branch. 2. Create a fork of the develop branch. 3. Make changes or add new documentation. 4. Commit changes to your fork and push it to GitHub. @@ -123,7 +123,7 @@ To edit Docs on your computer: To edit Docs on GitHub: 1. Login to [GitHub.com](https://www.github.com). -2. Navigate to [mermaid-js/mermaid/docs](https://github.com/mermaid-js/mermaid/tree/develop/docs). +2. Navigate to [mermaid-js/mermaid/src/docs](https://github.com/mermaid-js/mermaid/tree/develop/src/docs). 3. To edit a file, click the pencil icon at the top-right of the file contents panel. 4. Describe what you changed in the **Propose file change** section, located at the bottom of the page. 5. Submit your changes by clicking the button **Propose file change** at the bottom (by automatic creation of a fork and a new branch). diff --git a/docs/diagrams-and-syntax-and-examples/flowchart.md b/docs/diagrams-and-syntax-and-examples/flowchart.md index 3aef42ef7..0f798d27f 100644 --- a/docs/diagrams-and-syntax-and-examples/flowchart.md +++ b/docs/diagrams-and-syntax-and-examples/flowchart.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. --- diff --git a/docs/directives.md b/docs/directives.md index 943dac53f..8ef732008 100644 --- a/docs/directives.md +++ b/docs/directives.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Directives diff --git a/docs/entityRelationshipDiagram.md b/docs/entityRelationshipDiagram.md index 34e6a3ac6..1f24796b6 100644 --- a/docs/entityRelationshipDiagram.md +++ b/docs/entityRelationshipDiagram.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Entity Relationship Diagrams diff --git a/docs/examples.md b/docs/examples.md index 174a2c986..d717083c6 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Examples diff --git a/docs/faq.md b/docs/faq.md index a1b6e4837..ac5eeeb80 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Frequently Asked Questions diff --git a/docs/flowchart.md b/docs/flowchart.md index 4d469f55e..3ff17ad02 100644 --- a/docs/flowchart.md +++ b/docs/flowchart.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Flowcharts - Basic Syntax diff --git a/docs/gantt.md b/docs/gantt.md index b0a302d9f..9d598d977 100644 --- a/docs/gantt.md +++ b/docs/gantt.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Gantt diagrams diff --git a/docs/gitgraph.md b/docs/gitgraph.md index c423c2515..5f86cf53c 100644 --- a/docs/gitgraph.md +++ b/docs/gitgraph.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Gitgraph Diagrams diff --git a/docs/index.html b/docs/index.html index 39d454533..0a41b516c 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,6 +1,6 @@ - + mermaid - Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, @@ -21,22 +21,13 @@ rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css" /> - <script src="//cdn.jsdelivr.net/npm/mermaid@9.1.6/dist/mermaid.min.js"></script> + <script src="//cdn.jsdelivr.net/npm/mermaid@9.1.7/dist/mermaid.min.js"></script> <!-- <script src="http://localhost:9000/mermaid.js"></script> --> - <script> - // prettier-ignore - (function (i, s, o, g, r, a, m) { - i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () { - (i[r].q = i[r].q || []).push(arguments) - }, i[r].l = 1 * new Date(); a = s.createElement(o), - m = s.getElementsByTagName(o)[0]; a.async = 1; a.src = g; m.parentNode.insertBefore(a, m) - })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga'); - - ga('create', 'UA-153180559-1', 'auto'); - if (location) { - ga('send', 'pageview', location.hash); - } - </script> + <script + defer="" + data-domain="mermaid-js.github.io" + src="https://plausible.io/js/plausible.js" + ></script> <script> var require = { paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.29.1/min/vs' }, diff --git a/docs/integrations.md b/docs/integrations.md index 16e735779..57d3bd316 100644 --- a/docs/integrations.md +++ b/docs/integrations.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Integrations diff --git a/docs/introduction.md b/docs/introduction.md index 38c7c7a0e..992fbafc1 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -1 +1 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. diff --git a/docs/landing/index.html b/docs/landing/index.html index 9b1e3749f..2431ad9bd 100644 --- a/docs/landing/index.html +++ b/docs/landing/index.html @@ -1,6 +1,6 @@ <!DOCTYPE html> <html lang="en"> - <head> + <!--# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs.--><head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> @@ -64,7 +64,7 @@ using Mermaid.js. </p> <a - href="https://www.amazon.com/Official-Guide-Mermaid-js-beautiful-flowcharts-dp-1801078025/dp/1801078025/ref=mt_other?_encoding=UTF8&me=&qid=1628153965" + href="https://www.amazon.com/Official-Guide-Mermaid-js-beautiful-flowcharts-dp-1801078025/dp/1801078025/ref=mt_other?_encoding=UTF8&me=&qid=1628153965" > <button style="background: #ffa41c; border: 1px solid #ff8f00" @@ -322,7 +322,7 @@ </p> </h3> <a - href="https://www.amazon.com/Official-Guide-Mermaid-js-beautiful-flowcharts-dp-1801078025/dp/1801078025/ref=mt_other?_encoding=UTF8&me=&qid=1628153965" + href="https://www.amazon.com/Official-Guide-Mermaid-js-beautiful-flowcharts-dp-1801078025/dp/1801078025/ref=mt_other?_encoding=UTF8&me=&qid=1628153965" > <button style="background: #ffa41c; border: 1px solid #ff8f00" diff --git a/docs/mermaidCLI.md b/docs/mermaidCLI.md index e3249315b..0d32c5472 100644 --- a/docs/mermaidCLI.md +++ b/docs/mermaidCLI.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # mermaid CLI diff --git a/docs/mindmap.md b/docs/mindmap.md index f9d732463..3d435d68a 100644 --- a/docs/mindmap.md +++ b/docs/mindmap.md @@ -1,9 +1,7 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Mindmap -**Edit this Page** [![N|Solid](img/GitHub-Mark-32px.png)](https://github.com/mermaid-js/mermaid/blob/develop/docs/mindmap.md) - > Mindmap: This is an experimental diagram for now. The syntax and properties can change in future releases. The syntax is stabel except for the icon integration which is the experimental part. "A mind map is a diagram used to visually organize information into a hierarchy, showing relationships among pieces of the whole. It is often created around a single concept, drawn as an image in the center of a blank page, to which associated representations of ideas such as images, words and parts of words are added. Major ideas are connected directly to the central concept, and other ideas branch out from those major ideas." Wikipedia @@ -64,7 +62,7 @@ In the following example you can see how there are 3 dufferent levels. One with B C -In summary is is a simple text outline where there are one node at the root level called `Root` which has one child `A`. A in turn has two children `B`and `C`. In the diagram below we can see this rendered as a mindmap. +In summary is a simple text outline where there are one node at the root level called `Root` which has one child `A`. `A` in turn has two children `B`and `C`. In the diagram below we can see this rendered as a mindmap. ```mermaid-example mindmap @@ -168,7 +166,7 @@ More shapes will be added, beginning with the shapes available in flowcharts. ## icons -As with flowcharts you can add icons to your nodes but with an updated syntax. The styling for the font based icons are added during the integration so that they are available for the web page. _This is not something a diagram author can do but has to be done with the site administrator or the integrator_. Once the icon fonts are in place you add them to the mind map nodes using the `::icon()` syntax. You place the classes for the icon within the parethesis like in the following example where icons for material design and fontwaresome 4. is displayed. The intention is that this approach should be used for all diagrams supporting icons. **Expermental feature:** This wider scope is also the reason Mindmaps are experimental as this syntax and approach could change. +As with flowcharts you can add icons to your nodes but with an updated syntax. The styling for the font based icons are added during the integration so that they are available for the web page. _This is not something a diagram author can do but has to be done with the site administrator or the integrator_. Once the icon fonts are in place you add them to the mind map nodes using the `::icon()` syntax. You place the classes for the icon within the parenthesis like in the following example where icons for material design and fontawesome 4 are displayed. The intention is that this approach should be used for all diagrams supporting icons. **Experimental feature:** This wider scope is also the reason Mindmaps are experimental as this syntax and approach could change. ```mermaid-example mindmap @@ -190,7 +188,7 @@ mindmap ## Classes -Again the syntax for adding classes is similar to flowcharts and you can add classes using a tripple colon following a numver of css classes separated by space. In the following example one of the nodes has two custom classes attached urgent turning the background red and the text whiet and large increasing the font size: +Again the syntax for adding classes is similar to flowcharts. You can add classes using a triple colon following a number of css classes separated by space. In the following example one of the nodes has two custom classes attached urgent turning the background red and the text white and large increasing the font size: ```mermaid-example mindmap @@ -222,7 +220,7 @@ The actual indentation does not really matter only compared with the previous ro B C -This outline is unclear as `B` clearly is a child of `A` but when we move on to `C` the clarity is lost. `C` is not a child of `B` with a highter indentation nor does ot haver the same indentation as `B`. The only thing that is clear is that the first node with smaller indentation, indicating a parent, is A. Then Mermaid relies on this known truth and compensates for the unclear indentation and selects `A` as a parent of `C` leading till the same diagram with `B` and `C` as sieblings. +This outline is unclear as `B` clearly is a child of `A` but when we move on to `C` the clarity is lost. `C` is not a child of `B` with a higher indentation nor does it have the same indentation as `B`. The only thing that is clear is that the first node with smaller indentation, indicating a parent, is A. Then Mermaid relies on this known truth and compensates for the unclear indentation and selects `A` as a parent of `C` leading till the same diagram with `B` and `C` as siblings. ```mermaid-example mindmap diff --git a/docs/n00b-advanced.md b/docs/n00b-advanced.md index 4e9d74b98..b8970142a 100644 --- a/docs/n00b-advanced.md +++ b/docs/n00b-advanced.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Advanced n00b mermaid (Coming soon..) diff --git a/docs/n00b-gettingStarted.md b/docs/n00b-gettingStarted.md index f3ade5559..505542539 100644 --- a/docs/n00b-gettingStarted.md +++ b/docs/n00b-gettingStarted.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # A Mermaid User-Guide for Beginners diff --git a/docs/n00b-overview.md b/docs/n00b-overview.md index 913fcc2f6..c109b63f2 100644 --- a/docs/n00b-overview.md +++ b/docs/n00b-overview.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Overview for Beginners diff --git a/docs/n00b-syntaxReference.md b/docs/n00b-syntaxReference.md index 9f18e3d28..d25c6425e 100644 --- a/docs/n00b-syntaxReference.md +++ b/docs/n00b-syntaxReference.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Diagram Syntax diff --git a/docs/newDiagram.md b/docs/newDiagram.md index e2191f1de..285cb7637 100644 --- a/docs/newDiagram.md +++ b/docs/newDiagram.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Adding a New Diagram/Chart 📊 diff --git a/docs/pie.md b/docs/pie.md index 1e13e3872..79dcbfee5 100644 --- a/docs/pie.md +++ b/docs/pie.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Pie chart diagrams diff --git a/docs/requirementDiagram.md b/docs/requirementDiagram.md index c510183d9..d31967871 100644 --- a/docs/requirementDiagram.md +++ b/docs/requirementDiagram.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Requirement Diagram diff --git a/docs/security.md b/docs/security.md index e2990eb5b..ee9033ca2 100644 --- a/docs/security.md +++ b/docs/security.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Security diff --git a/docs/sequenceDiagram.md b/docs/sequenceDiagram.md index ae0bd5e45..97968a676 100644 --- a/docs/sequenceDiagram.md +++ b/docs/sequenceDiagram.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Sequence diagrams diff --git a/docs/stateDiagram.md b/docs/stateDiagram.md index 6af3b0bc4..8ea9fd239 100644 --- a/docs/stateDiagram.md +++ b/docs/stateDiagram.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # State diagrams diff --git a/docs/theming.md b/docs/theming.md index 287499eff..9ba136ec4 100644 --- a/docs/theming.md +++ b/docs/theming.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Theme Configuration diff --git a/docs/upgrading.md b/docs/upgrading.md index fd7f72d82..c4d7bd3bd 100644 --- a/docs/upgrading.md +++ b/docs/upgrading.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Upgrading diff --git a/docs/usage.md b/docs/usage.md index 02bd1bb13..e59670d02 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # Usage diff --git a/docs/user-journey.md b/docs/user-journey.md index 9e213f425..e0d924f85 100644 --- a/docs/user-journey.md +++ b/docs/user-journey.md @@ -1,4 +1,4 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs. +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. # User Journey Diagram diff --git a/package.json b/package.json index 9cc425a04..e447426ae 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,14 @@ { "name": "mermaid", - "version": "9.1.6", + "version": "9.2.0-rc1", "description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.", - "main": "dist/mermaid.min.js", - "module": "dist/mermaid.esm.min.mjs", + "main": "dist/mermaid.core.mjs", + "module": "dist/mermaid.core.mjs", "types": "dist/mermaid.d.ts", "exports": { ".": { "require": "./dist/mermaid.min.js", - "import": "./dist/mermaid.esm.min.mjs", + "import": "./dist/mermaid.core.mjs", "types": "./dist/mermaid.d.ts" }, "./*": "./*" @@ -28,20 +28,21 @@ "build:types": "tsc -p ./tsconfig.json --emitDeclarationOnly", "build:webpack": "webpack --mode production --progress --color", "build:watch": "yarn build:code --watch", - "build": "yarn clean; concurrently \"yarn build:code\" \"yarn build:types\"", + "build:new": "concurrently \"yarn build:code\" \"yarn build:types\"", + "build": "yarn clean; yarn build:webpack", "docs:build": "ts-node-esm src/docs.mts", "docs:verify": "ts-node-esm src/docs.mts --verify", - "postbuild": "documentation build src/mermaidAPI.ts src/config.ts src/defaultConfig.ts --shallow -f md --markdown-toc false > src/docs/Setup.md; prettier --write src/docs/Setup.md; yarn docs:build", + "postbuild": "documentation build src/mermaidAPI.ts src/config.ts src/defaultConfig.ts --shallow -f md --markdown-toc false > src/docs/Setup.md && prettier --write src/docs/Setup.md && yarn docs:build", "release": "yarn build", - "lint": "eslint --cache --ignore-path .gitignore .; prettier --check .", - "lint:fix": "eslint --fix --ignore-path .gitignore .; prettier --write .", + "lint": "eslint --cache --ignore-path .gitignore . && prettier --check .", + "lint:fix": "eslint --fix --ignore-path .gitignore . && prettier --write .", "e2e:depr": "yarn lint && jest e2e --config e2e/jest.config.js", "cypress": "cypress run", "cypress:open": "cypress open", "e2e": "start-server-and-test dev http://localhost:9000/ cypress", "e2e-upd": "yarn lint && jest e2e -u --config e2e/jest.config.js", "dev": "webpack serve --config ./.webpack/webpack.config.e2e.babel.js", - "ci": "vitest", + "ci": "vitest run", "test": "yarn lint && vitest run", "test:watch": "vitest --coverage --watch", "prepublishOnly": "yarn build && yarn test", @@ -69,44 +70,47 @@ "d3": "^7.0.0", "dagre": "^0.8.5", "dagre-d3": "^0.6.4", - "dompurify": "2.3.10", + "dompurify": "2.4.0", "fast-clone": "^1.5.13", "graphlib": "^2.1.8", "khroma": "^2.0.0", + "lodash": "^4.17.21", "moment-mini": "^2.24.0", "non-layered-tidy-tree-layout": "^2.0.2", - "stylis": "^4.0.10" + "stylis": "^4.1.2" }, "devDependencies": { "@applitools/eyes-cypress": "^3.25.7", - "@babel/core": "^7.14.6", + "@babel/core": "^7.19.0", "@babel/eslint-parser": "^7.14.7", - "@babel/preset-env": "^7.14.7", + "@babel/preset-env": "^7.19.0", "@babel/register": "^7.14.5", "@commitlint/cli": "^17.1.2", "@commitlint/config-conventional": "^17.0.0", "@types/d3": "^7.4.0", "@types/dompurify": "^2.3.4", + "@types/jsdom": "^20.0.0", + "@types/lodash": "^4.14.184", "@types/prettier": "^2.7.0", "@types/stylis": "^4.0.2", - "@typescript-eslint/eslint-plugin": "^5.36.1", - "@typescript-eslint/parser": "^5.36.1", - "@vitest/coverage-c8": "^0.23.1", - "@vitest/ui": "^0.23.1", + "@typescript-eslint/eslint-plugin": "^5.37.0", + "@typescript-eslint/parser": "^5.37.0", + "@vitest/coverage-c8": "^0.23.2", + "@vitest/ui": "^0.23.2", "babel-loader": "^8.2.2", - "concurrently": "^7.0.0", - "coveralls": "^3.0.2", + "concurrently": "^7.4.0", + "coveralls": "^3.1.1", "css-to-string-loader": "^0.1.3", "cypress": "9.7.0", "cypress-image-snapshot": "^4.0.1", "documentation": "13.2.0", "esbuild": "^0.15.6", "esbuild-loader": "^2.19.0", - "eslint": "^8.23.0", + "eslint": "^8.23.1", "eslint-config-prettier": "^8.5.0", "eslint-plugin-cypress": "^2.12.1", "eslint-plugin-html": "^7.1.0", - "eslint-plugin-jest": "^27.0.1", + "eslint-plugin-jest": "^27.0.4", "eslint-plugin-jsdoc": "^39.3.6", "eslint-plugin-json": "^3.1.0", "eslint-plugin-markdown": "^3.0.0", @@ -119,20 +123,20 @@ "lint-staged": "^13.0.0", "moment": "^2.23.0", "path-browserify": "^1.0.1", - "prettier": "^2.3.2", - "prettier-plugin-jsdoc": "^0.3.30", + "prettier": "^2.7.1", + "prettier-plugin-jsdoc": "^0.4.2", "remark": "^14.0.2", "rimraf": "^3.0.2", "start-server-and-test": "^1.12.6", "terser-webpack-plugin": "^5.3.6", "ts-loader": "^9.3.1", "ts-node": "^10.9.1", - "typescript": "^4.8.2", + "typescript": "^4.8.3", "unist-util-flatmap": "^1.0.0", "vitest": "^0.23.1", "webpack": "^5.53.0", "webpack-cli": "^4.7.2", - "webpack-dev-server": "^4.10.1", + "webpack-dev-server": "^4.11.0", "webpack-merge": "^5.8.0", "webpack-node-externals": "^3.0.0" }, diff --git a/src/Diagram.ts b/src/Diagram.ts index 4f1765899..a54cfbefd 100644 --- a/src/Diagram.ts +++ b/src/Diagram.ts @@ -8,6 +8,7 @@ export class Diagram { parser; renderer; db; + // eslint-disable-next-line @typescript-eslint/ban-types constructor(public txt: string, parseError?: Function) { const cnf = configApi.getConfig(); this.txt = txt; @@ -33,6 +34,7 @@ export class Diagram { this.parse(this.txt, parseError); } + // eslint-disable-next-line @typescript-eslint/ban-types parse(text: string, parseError?: Function): boolean { try { text = text + '\n'; diff --git a/src/__mocks__/mermaidAPI.ts b/src/__mocks__/mermaidAPI.ts index ded24fc3d..f15db139f 100644 --- a/src/__mocks__/mermaidAPI.ts +++ b/src/__mocks__/mermaidAPI.ts @@ -16,6 +16,7 @@ let hasLoadedDiagrams = false; * @param text * @param parseError */ +// eslint-disable-next-line @typescript-eslint/ban-types function parse(text: string, parseError?: Function): boolean { if (!hasLoadedDiagrams) { addDiagrams(); diff --git a/src/assignWithDepth.js b/src/assignWithDepth.js index 9f44b01ee..eff568d3e 100644 --- a/src/assignWithDepth.js +++ b/src/assignWithDepth.js @@ -1,3 +1,4 @@ +'use strict'; /** * @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) diff --git a/src/config.ts b/src/config.ts index 9eb688bb4..44dcf8bd1 100644 --- a/src/config.ts +++ b/src/config.ts @@ -62,9 +62,9 @@ export const setSiteConfig = (conf: MermaidConfig): MermaidConfig => { siteConfig = assignWithDepth({}, defaultConfig); siteConfig = assignWithDepth(siteConfig, conf); - // @ts-ignore + // @ts-ignore: TODO Fix ts errors if (conf.theme && theme[conf.theme]) { - // @ts-ignore + // @ts-ignore: TODO Fix ts errors siteConfig.themeVariables = theme[conf.theme].getThemeVariables(conf.themeVariables); } @@ -216,6 +216,8 @@ export const addDirective = (directive: any) => { * | conf | base set of values, which currentConfig could be **reset** to. | Dictionary | Required | Any Values, with respect to the secure Array | * * **Notes**: (default: current siteConfig ) (optional, default `getSiteConfig()`) + * + * @param config */ export const reset = (config = siteConfig): void => { // Replace current config with siteConfig diff --git a/src/config.type.ts b/src/config.type.ts index 6814a265c..d9d94226f 100644 --- a/src/config.type.ts +++ b/src/config.type.ts @@ -219,7 +219,8 @@ export interface MindmapDiagramConfig extends BaseDiagramConfig { padding: number; maxNodeWidth: number; } -export interface PieDiagramConfig extends BaseDiagramConfig {} + +export type PieDiagramConfig = BaseDiagramConfig; export interface ErDiagramConfig extends BaseDiagramConfig { diagramPadding?: number; diff --git a/src/dagre-wrapper/createLabel.js b/src/dagre-wrapper/createLabel.js index 631fb7645..ba0ce4a5d 100644 --- a/src/dagre-wrapper/createLabel.js +++ b/src/dagre-wrapper/createLabel.js @@ -1,11 +1,9 @@ import { select } from 'd3'; import { log } from '../logger'; import { getConfig } from '../config'; -import { sanitizeText, evaluate } from '../diagrams/common/common'; +import { evaluate } from '../diagrams/common/common'; import { decodeEntities } from '../mermaidAPI'; -const sanitizeTxt = (txt) => sanitizeText(txt, getConfig()); - /** * @param dom * @param styleFn diff --git a/src/dagre-wrapper/markers.js b/src/dagre-wrapper/markers.js index b28be4119..fa229d231 100644 --- a/src/dagre-wrapper/markers.js +++ b/src/dagre-wrapper/markers.js @@ -119,7 +119,7 @@ const dependency = (elem, type) => { .append('path') .attr('d', 'M 18,7 L9,13 L14,7 L9,1 Z'); }; -const lollipop = (elem, type, id) => { +const lollipop = (elem, type) => { elem .append('defs') .append('marker') diff --git a/src/dagre-wrapper/nodes.js b/src/dagre-wrapper/nodes.js index 344210e93..f25eb2e86 100644 --- a/src/dagre-wrapper/nodes.js +++ b/src/dagre-wrapper/nodes.js @@ -6,9 +6,7 @@ import intersect from './intersect/index.js'; import createLabel from './createLabel'; import note from './shapes/note'; import { parseMember } from '../diagrams/class/svgDraw'; -import { evaluate, sanitizeText as sanitize } from '../diagrams/common/common'; - -const sanitizeText = (txt) => sanitize(txt, getConfig()); +import { evaluate } from '../diagrams/common/common'; const question = (parent, node) => { const { shapeSvg, bbox } = labelHelper(parent, node, undefined, true); @@ -348,7 +346,7 @@ const rect = (parent, node) => { }; const labelRect = (parent, node) => { - const { shapeSvg, bbox, halfPadding } = labelHelper(parent, node, 'label', true); + const { shapeSvg } = labelHelper(parent, node, 'label', true); log.trace('Classes = ', node.classes); // add the rect diff --git a/src/defaultConfig.ts b/src/defaultConfig.ts index 60d867437..681fda60c 100644 --- a/src/defaultConfig.ts +++ b/src/defaultConfig.ts @@ -228,9 +228,9 @@ const config: Partial<MermaidConfig> = { * Decides which rendering engine that is to be used for the rendering. Legal values are: * dagre-d3 dagre-wrapper - wrapper for dagre implemented in mermaid * - * Default value: 'dagre-d3' + * Default value: 'dagre-wrapper' */ - defaultRenderer: 'dagre-d3', + defaultRenderer: 'dagre-wrapper', }, /** The object containing configurations specific for sequence diagrams */ @@ -387,7 +387,8 @@ const config: Partial<MermaidConfig> = { * * **Notes:** * - * This will display arrows that start and begin at the same node as right angles, rather than a curve + * This will display arrows that start and begin at the same node as right angles, rather than a + * curve * * Default value: false */ @@ -802,7 +803,8 @@ const config: Partial<MermaidConfig> = { * * **Notes:** * - * This will display arrows that start and begin at the same node as right angles, rather than a curves + * This will display arrows that start and begin at the same node as right angles, rather than a + * curves * * Default value: false */ diff --git a/src/diagram-api/detectType.ts b/src/diagram-api/detectType.ts index 87b681767..817de5149 100644 --- a/src/diagram-api/detectType.ts +++ b/src/diagram-api/detectType.ts @@ -1,26 +1,12 @@ import { MermaidConfig } from '../config.type'; -export type DiagramDetector = (text: string) => boolean; +export type DiagramDetector = (text: string, config?: MermaidConfig) => boolean; const directive = /[%]{2}[{]\s*(?:(?:(\w+)\s*:|(\w+))\s*(?:(?:(\w+))|((?:(?![}][%]{2}).|\r?\n)*))?\s*)(?:[}][%]{2})?/gi; const anyComment = /\s*%%.*\n/gm; const detectors: Record<string, DiagramDetector> = {}; -const diagramMatchers: Record<string, RegExp> = { - c4: /^\s*C4Context|C4Container|C4Component|C4Dynamic|C4Deployment/, - sequence: /^\s*sequenceDiagram/, - gantt: /^\s*gantt/, - classDiagram: /^\s*classDiagram-v2/, - stateDiagram: /^\s*stateDiagram-v2/, - 'flowchart-v2': /^\s*flowchart/, // Might need to add |graph to fix #3391 - info: /^\s*info/, - pie: /^\s*pie/, - er: /^\s*erDiagram/, - journey: /^\s*journey/, - // gitGraph: /^\s*gitGraph/, - requirement: /^\s*requirement(Diagram)?/, -}; /** * @function detectType Detects the type of the graph text. Takes into consideration the possible @@ -47,28 +33,9 @@ const diagramMatchers: Record<string, RegExp> = { */ export const detectType = function (text: string, config?: MermaidConfig): string { text = text.replace(directive, '').replace(anyComment, '\n'); - for (const [diagram, matcher] of Object.entries(diagramMatchers)) { - if (text.match(matcher)) { - return diagram; - } - } - - if (text.match(/^\s*classDiagram/)) { - if (config?.class?.defaultRenderer === 'dagre-wrapper') return 'classDiagram'; - return 'class'; - } - - if (text.match(/^\s*stateDiagram/)) { - if (config?.state?.defaultRenderer === 'dagre-wrapper') return 'stateDiagram'; - return 'state'; - } - - if (config?.flowchart?.defaultRenderer === 'dagre-wrapper') { - return 'flowchart-v2'; - } for (const [key, detector] of Object.entries(detectors)) { - if (detector(text)) { + if (detector(text, config)) { return key; } } diff --git a/src/diagram-api/diagram-orchestration.ts b/src/diagram-api/diagram-orchestration.ts index eb4317d7b..e5b5f3cc0 100644 --- a/src/diagram-api/diagram-orchestration.ts +++ b/src/diagram-api/diagram-orchestration.ts @@ -1,20 +1,336 @@ import { registerDiagram } from './diagramAPI'; -import * as mindmapDb from '../diagrams/mindmap/mindmapDb'; -import mindmapRenderer from '../diagrams/mindmap/mindmapRenderer'; -// @ts-ignore + +// @ts-ignore: TODO Fix ts errors import mindmapParser from '../diagrams/mindmap/parser/mindmap'; +import * as mindmapDb from '../diagrams/mindmap/mindmapDb'; import { mindmapDetector } from '../diagrams/mindmap/mindmapDetector'; +import mindmapRenderer from '../diagrams/mindmap/mindmapRenderer'; import mindmapStyles from '../diagrams/mindmap/styles'; -import gitGraphDb from '../diagrams/git/gitGraphAst'; -import gitGraphRenderer from '../diagrams/git/gitGraphRenderer'; -// @ts-ignore +// @ts-ignore: TODO Fix ts errors import gitGraphParser from '../diagrams/git/parser/gitGraph'; import { gitGraphDetector } from '../diagrams/git/gitGraphDetector'; +import gitGraphDb from '../diagrams/git/gitGraphAst'; +import gitGraphRenderer from '../diagrams/git/gitGraphRenderer'; import gitGraphStyles from '../diagrams/git/styles'; +// @ts-ignore: TODO Fix ts errors +import c4Parser from '../diagrams/c4/parser/c4Diagram'; +import { c4Detector } from '../diagrams/c4/c4Detector'; +import c4Db from '../diagrams/c4/c4Db'; +import c4Renderer from '../diagrams/c4/c4Renderer'; +import c4Styles from '../diagrams/c4/styles'; + +// @ts-ignore: TODO Fix ts errors +import classParser from '../diagrams/class/parser/classDiagram'; +import { classDetector } from '../diagrams/class/classDetector'; +import { classDetectorV2 } from '../diagrams/class/classDetector-V2'; +import classDb from '../diagrams/class/classDb'; +import classRenderer from '../diagrams/class/classRenderer'; +import classRendererV2 from '../diagrams/class/classRenderer-v2'; +import classStyles from '../diagrams/class/styles'; + +// @ts-ignore: TODO Fix ts errors +import erParser from '../diagrams/er/parser/erDiagram'; +import { erDetector } from '../diagrams/er/erDetector'; +import erDb from '../diagrams/er/erDb'; +import erRenderer from '../diagrams/er/erRenderer'; +import erStyles from '../diagrams/er/styles'; + +// @ts-ignore: TODO Fix ts errors +import flowParser from '../diagrams/flowchart/parser/flow'; +import { flowDetector } from '../diagrams/flowchart/flowDetector'; +import { flowDetectorV2 } from '../diagrams/flowchart/flowDetector-v2'; +import flowDb from '../diagrams/flowchart/flowDb'; +import flowRenderer from '../diagrams/flowchart/flowRenderer'; +import flowRendererV2 from '../diagrams/flowchart/flowRenderer-v2'; +import flowStyles from '../diagrams/flowchart/styles'; + +// @ts-ignore: TODO Fix ts errors +import ganttParser from '../diagrams/gantt/parser/gantt'; +import { ganttDetector } from '../diagrams/gantt/ganttDetector'; +import ganttDb from '../diagrams/gantt/ganttDb'; +import ganttRenderer from '../diagrams/gantt/ganttRenderer'; +import ganttStyles from '../diagrams/gantt/styles'; + +// @ts-ignore: TODO Fix ts errors +import infoParser from '../diagrams/info/parser/info'; +import infoDb from '../diagrams/info/infoDb'; +import infoRenderer from '../diagrams/info/infoRenderer'; +import { infoDetector } from '../diagrams/info/infoDetector'; +import infoStyles from '../diagrams/info/styles'; + +// @ts-ignore: TODO Fix ts errors +import pieParser from '../diagrams/pie/parser/pie'; +import { pieDetector } from '../diagrams/pie/pieDetector'; +import pieDb from '../diagrams/pie/pieDb'; +import pieRenderer from '../diagrams/pie/pieRenderer'; +import pieStyles from '../diagrams/pie/styles'; + +// @ts-ignore: TODO Fix ts errors +import requirementParser from '../diagrams/requirement/parser/requirementDiagram'; +import { requirementDetector } from '../diagrams/requirement/requirementDetector'; +import requirementDb from '../diagrams/requirement/requirementDb'; +import requirementRenderer from '../diagrams/requirement/requirementRenderer'; +import requirementStyles from '../diagrams/requirement/styles'; + +// @ts-ignore: TODO Fix ts errors +import sequenceParser from '../diagrams/sequence/parser/sequenceDiagram'; +import { sequenceDetector } from '../diagrams/sequence/sequenceDetector'; +import sequenceDb from '../diagrams/sequence/sequenceDb'; +import sequenceRenderer from '../diagrams/sequence/sequenceRenderer'; +import sequenceStyles from '../diagrams/sequence/styles'; + +// @ts-ignore: TODO Fix ts errors +import stateParser from '../diagrams/state/parser/stateDiagram'; +import { stateDetector } from '../diagrams/state/stateDetector'; +import { stateDetectorV2 } from '../diagrams/state/stateDetector-V2'; +import stateDb from '../diagrams/state/stateDb'; +import stateRenderer from '../diagrams/state/stateRenderer'; +import stateRendererV2 from '../diagrams/state/stateRenderer-v2'; +import stateStyles from '../diagrams/state/styles'; + +// @ts-ignore: TODO Fix ts errors +import journeyParser from '../diagrams/user-journey/parser/journey'; +import { journeyDetector } from '../diagrams/user-journey/journeyDetector'; +import journeyDb from '../diagrams/user-journey/journeyDb'; +import journeyRenderer from '../diagrams/user-journey/journeyRenderer'; +import journeyStyles from '../diagrams/user-journey/styles'; + +import errorRenderer from '../diagrams/error/errorRenderer'; +import errorStyles from '../diagrams/error/styles'; + export const addDiagrams = () => { - // Register mindmap and other built-in diagrams + registerDiagram( + 'error', + // Special diagram with error messages but setup as a regular diagram + { + db: { + clear: () => { + // Quite ok, clear needs to be there for error to work as a regular diagram + }, + }, + styles: errorStyles, + renderer: errorRenderer, + parser: { + parser: { yy: {} }, + parse: () => { + // no op + }, + }, + init: () => { + // no op + }, + }, + (text) => text.toLowerCase().trim() === 'error' + ); + registerDiagram( + 'c4', + { + parser: c4Parser, + db: c4Db, + renderer: c4Renderer, + styles: c4Styles, + init: (cnf) => { + c4Renderer.setConf(cnf.c4); + }, + }, + c4Detector + ); + registerDiagram( + 'class', + { + parser: classParser, + db: classDb, + renderer: classRenderer, + styles: classStyles, + init: (cnf) => { + if (!cnf.class) { + cnf.class = {}; + } + cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + classDb.clear(); + }, + }, + classDetector + ); + registerDiagram( + 'classDiagram', + { + parser: classParser, + db: classDb, + renderer: classRendererV2, + styles: classStyles, + init: (cnf) => { + if (!cnf.class) { + cnf.class = {}; + } + cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + classDb.clear(); + }, + }, + classDetectorV2 + ); + registerDiagram( + 'er', + { + parser: erParser, + db: erDb, + renderer: erRenderer, + styles: erStyles, + }, + erDetector + ); + registerDiagram( + 'gantt', + { + parser: ganttParser, + db: ganttDb, + renderer: ganttRenderer, + styles: ganttStyles, + }, + ganttDetector + ); + registerDiagram( + 'info', + { + parser: infoParser, + db: infoDb, + renderer: infoRenderer, + styles: infoStyles, + }, + infoDetector + ); + registerDiagram( + 'pie', + { + parser: pieParser, + db: pieDb, + renderer: pieRenderer, + styles: pieStyles, + }, + pieDetector + ); + registerDiagram( + 'requirement', + { + parser: requirementParser, + db: requirementDb, + renderer: requirementRenderer, + styles: requirementStyles, + }, + requirementDetector + ); + registerDiagram( + 'sequence', + { + parser: sequenceParser, + db: sequenceDb, + renderer: sequenceRenderer, + styles: sequenceStyles, + init: (cnf) => { + if (!cnf.sequence) { + cnf.sequence = {}; + } + cnf.sequence.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + if ('sequenceDiagram' in cnf) { + throw new Error( + '`mermaid config.sequenceDiagram` has been renamed to `config.sequence`. Please update your mermaid config.' + ); + } + sequenceDb.setWrap(cnf.wrap); + sequenceRenderer.setConf(cnf.sequence); + }, + }, + sequenceDetector + ); + registerDiagram( + 'state', + { + parser: stateParser, + db: stateDb, + renderer: stateRenderer, + styles: stateStyles, + init: (cnf) => { + if (!cnf.state) { + cnf.state = {}; + } + cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + stateDb.clear(); + }, + }, + stateDetector + ); + registerDiagram( + 'stateDiagram', + { + parser: stateParser, + db: stateDb, + renderer: stateRendererV2, + styles: stateStyles, + init: (cnf) => { + if (!cnf.state) { + cnf.state = {}; + } + cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + stateDb.clear(); + }, + }, + stateDetectorV2 + ); + registerDiagram( + 'journey', + { + parser: journeyParser, + db: journeyDb, + renderer: journeyRenderer, + styles: journeyStyles, + init: (cnf) => { + journeyRenderer.setConf(cnf.journey); + journeyDb.clear(); + }, + }, + journeyDetector + ); + + registerDiagram( + 'flowchart', + { + parser: flowParser, + db: flowDb, + renderer: flowRendererV2, + styles: flowStyles, + init: (cnf) => { + flowRenderer.setConf(cnf.flowchart); + if (!cnf.flowchart) { + cnf.flowchart = {}; + } + cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + flowDb.clear(); + flowDb.setGen('gen-1'); + }, + }, + flowDetector + ); + registerDiagram( + 'flowchart-v2', + { + parser: flowParser, + db: flowDb, + renderer: flowRendererV2, + styles: flowStyles, + init: (cnf) => { + flowRendererV2.setConf(cnf.flowchart); + if (!cnf.flowchart) { + cnf.flowchart = {}; + } + cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + flowDb.clear(); + flowDb.setGen('gen-2'); + }, + }, + flowDetectorV2 + ); registerDiagram( 'gitGraph', { parser: gitGraphParser, db: gitGraphDb, renderer: gitGraphRenderer, styles: gitGraphStyles }, diff --git a/src/diagram-api/diagramAPI.spec.ts b/src/diagram-api/diagramAPI.spec.ts index f72384c11..e0c7a283d 100644 --- a/src/diagram-api/diagramAPI.spec.ts +++ b/src/diagram-api/diagramAPI.spec.ts @@ -1,5 +1,8 @@ import { detectType } from './detectType'; import { getDiagram, registerDiagram } from './diagramAPI'; +import { addDiagrams } from './diagram-orchestration'; + +addDiagrams(); describe('DiagramAPI', () => { it('should return default diagrams', () => { diff --git a/src/diagram-api/diagramAPI.ts b/src/diagram-api/diagramAPI.ts index 51807e034..9a86c5b51 100644 --- a/src/diagram-api/diagramAPI.ts +++ b/src/diagram-api/diagramAPI.ts @@ -1,70 +1,23 @@ -import c4Db from '../diagrams/c4/c4Db'; -import c4Renderer from '../diagrams/c4/c4Renderer'; -import c4Styles from '../diagrams/c4/styles'; -// @ts-ignore -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 classStyles from '../diagrams/class/styles'; -// @ts-ignore -import classParser from '../diagrams/class/parser/classDiagram'; -import erDb from '../diagrams/er/erDb'; -import erRenderer from '../diagrams/er/erRenderer'; -// @ts-ignore -import erParser from '../diagrams/er/parser/erDiagram'; -import erStyles from '../diagrams/er/styles'; -import flowDb from '../diagrams/flowchart/flowDb'; -import flowRenderer from '../diagrams/flowchart/flowRenderer'; -import flowRendererV2 from '../diagrams/flowchart/flowRenderer-v2'; -import flowStyles from '../diagrams/flowchart/styles'; -// @ts-ignore -import flowParser from '../diagrams/flowchart/parser/flow'; -import ganttDb from '../diagrams/gantt/ganttDb'; -import ganttRenderer from '../diagrams/gantt/ganttRenderer'; -// @ts-ignore -import ganttParser from '../diagrams/gantt/parser/gantt'; -import ganttStyles from '../diagrams/gantt/styles'; - -import infoDb from '../diagrams/info/infoDb'; -import infoRenderer from '../diagrams/info/infoRenderer'; -// @ts-ignore -import infoParser from '../diagrams/info/parser/info'; -import infoStyles from '../diagrams/info/styles'; -// @ts-ignore -import pieParser from '../diagrams/pie/parser/pie'; -import pieDb from '../diagrams/pie/pieDb'; -import pieRenderer from '../diagrams/pie/pieRenderer'; -import pieStyles from '../diagrams/pie/styles'; -// @ts-ignore -import requirementParser from '../diagrams/requirement/parser/requirementDiagram'; -import requirementDb from '../diagrams/requirement/requirementDb'; -import requirementRenderer from '../diagrams/requirement/requirementRenderer'; -import requirementStyles from '../diagrams/requirement/styles'; -// @ts-ignore -import sequenceParser from '../diagrams/sequence/parser/sequenceDiagram'; -import sequenceDb from '../diagrams/sequence/sequenceDb'; -import sequenceRenderer from '../diagrams/sequence/sequenceRenderer'; -import sequenceStyles from '../diagrams/sequence/styles'; -// @ts-ignore -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 stateStyles from '../diagrams/state/styles'; -import journeyDb from '../diagrams/user-journey/journeyDb'; -import journeyRenderer from '../diagrams/user-journey/journeyRenderer'; -import journeyStyles from '../diagrams/user-journey/styles'; -// @ts-ignore -import journeyParser from '../diagrams/user-journey/parser/journey'; -import { addDetector, DiagramDetector } from './detectType'; -import { log as _log } from '../logger'; +import { addDetector, DiagramDetector as _DiagramDetector } from './detectType'; +import { log as _log, setLogLevel as _setLogLevel } from '../logger'; import { getConfig as _getConfig } from '../config'; import { sanitizeText as _sanitizeText } from '../diagrams/common/common'; import { MermaidConfig } from '../config.type'; import { setupGraphViewbox as _setupGraphViewbox } from '../setupGraphViewbox'; import { addStylesForDiagram } from '../styles'; +/* + Packaging and exposing resources for externa diagrams so that they can import + diagramAPI and have access to selct parts of mermaid common code reqiored to + create diagrams worling like the internal diagrams. +*/ +export const log = _log; +export const setLogLevel = _setLogLevel; +export type DiagramDetector = _DiagramDetector; +export const getConfig = _getConfig; +export const sanitizeText = (text: string) => _sanitizeText(text, getConfig()); +export const setupGraphViewbox = _setupGraphViewbox; + export interface DiagramDefinition { db: any; renderer: any; @@ -73,158 +26,7 @@ export interface DiagramDefinition { init?: (config: MermaidConfig) => void; } -const diagrams: Record<string, DiagramDefinition> = { - c4: { - db: c4Db, - renderer: c4Renderer, - parser: c4Parser, - init: (cnf) => { - c4Renderer.setConf(cnf.c4); - }, - styles: c4Styles, - }, - class: { - db: classDb, - renderer: classRenderer, - parser: classParser, - init: (cnf) => { - if (!cnf.class) { - cnf.class = {}; - } - cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - classDb.clear(); - }, - styles: classStyles, - }, - classDiagram: { - db: classDb, - renderer: classRendererV2, - parser: classParser, - init: (cnf) => { - if (!cnf.class) { - cnf.class = {}; - } - cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - classDb.clear(); - }, - styles: classStyles, - }, - er: { - db: erDb, - renderer: erRenderer, - parser: erParser, - styles: erStyles, - }, - flowchart: { - db: flowDb, - renderer: flowRenderer, - parser: flowParser, - init: (cnf) => { - flowRenderer.setConf(cnf.flowchart); - if (!cnf.flowchart) { - cnf.flowchart = {}; - } - cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - flowDb.clear(); - flowDb.setGen('gen-1'); - }, - styles: flowStyles, - }, - 'flowchart-v2': { - db: flowDb, - renderer: flowRendererV2, - parser: flowParser, - init: (cnf) => { - flowRendererV2.setConf(cnf.flowchart); - if (!cnf.flowchart) { - cnf.flowchart = {}; - } - cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - flowDb.clear(); - flowDb.setGen('gen-2'); - }, - styles: flowStyles, - }, - gantt: { - db: ganttDb, - renderer: ganttRenderer, - parser: ganttParser, - styles: ganttStyles, - }, - info: { - db: infoDb, - renderer: infoRenderer, - parser: infoParser, - styles: infoStyles, - }, - pie: { - db: pieDb, - renderer: pieRenderer, - parser: pieParser, - styles: pieStyles, - }, - requirement: { - db: requirementDb, - renderer: requirementRenderer, - parser: requirementParser, - styles: requirementStyles, - }, - sequence: { - db: sequenceDb, - renderer: sequenceRenderer, - parser: sequenceParser, - init: (cnf) => { - if (!cnf.sequence) { - cnf.sequence = {}; - } - cnf.sequence.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - if ('sequenceDiagram' in cnf) { - throw new Error( - '`mermaid config.sequenceDiagram` has been renamed to `config.sequence`. Please update your mermaid config.' - ); - } - sequenceDb.setWrap(cnf.wrap); - sequenceRenderer.setConf(cnf.sequence); - }, - styles: sequenceStyles, - }, - state: { - db: stateDb, - renderer: stateRenderer, - parser: stateParser, - init: (cnf) => { - if (!cnf.state) { - cnf.state = {}; - } - cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - stateDb.clear(); - }, - styles: stateStyles, - }, - stateDiagram: { - db: stateDb, - renderer: stateRendererV2, - parser: stateParser, - init: (cnf) => { - if (!cnf.state) { - cnf.state = {}; - } - cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - stateDb.clear(); - }, - styles: stateStyles, - }, - journey: { - db: journeyDb, - renderer: journeyRenderer, - parser: journeyParser, - init: (cnf) => { - journeyRenderer.setConf(cnf.journey); - journeyDb.clear(); - }, - styles: journeyStyles, - }, -}; +const diagrams: Record<string, DiagramDefinition> = {}; export const registerDiagram = ( id: string, @@ -245,8 +47,3 @@ export const getDiagram = (name: string): DiagramDefinition => { } throw new Error(`Diagram ${name} not found.`); }; - -export const log = _log; -export const getConfig = _getConfig; -export const sanitizeText = (text: string) => _sanitizeText(text, getConfig()); -export const setupGraphViewbox = _setupGraphViewbox; diff --git a/src/diagrams/c4/c4Db.js b/src/diagrams/c4/c4Db.js index d53d6d31f..79028a0c5 100644 --- a/src/diagrams/c4/c4Db.js +++ b/src/diagrams/c4/c4Db.js @@ -1,6 +1,5 @@ import mermaidAPI from '../../mermaidAPI'; import * as configApi from '../../config'; -import { log } from '../../logger'; import { sanitizeText } from '../common/common'; import { setAccTitle, getAccTitle, getAccDescription, setAccDescription } from '../../commonDb'; @@ -21,7 +20,6 @@ let boundarys = [ let rels = []; let title = ''; let wrapEnabled = false; -let description = ''; let c4ShapeInRow = 4; let c4BoundaryInRow = 2; var c4Type; @@ -636,13 +634,13 @@ export const updateLayoutConfig = function (typeC4Shape, c4ShapeInRowParam, c4Bo let c4BoundaryInRowValue = c4BoundaryInRow; if (typeof c4ShapeInRowParam === 'object') { - let [key, value] = Object.entries(c4ShapeInRowParam)[0]; + const value = Object.values(c4ShapeInRowParam)[0]; c4ShapeInRowValue = parseInt(value); } else { c4ShapeInRowValue = parseInt(c4ShapeInRowParam); } if (typeof c4BoundaryInRowParam === 'object') { - let [key, value] = Object.entries(c4BoundaryInRowParam)[0]; + const value = Object.values(c4BoundaryInRowParam)[0]; c4BoundaryInRowValue = parseInt(value); } else { c4BoundaryInRowValue = parseInt(c4BoundaryInRowParam); @@ -721,7 +719,6 @@ export const clear = function () { boundaryParseStack = ['']; title = ''; wrapEnabled = false; - description = ''; c4ShapeInRow = 4; c4BoundaryInRow = 2; }; diff --git a/src/diagrams/c4/c4Detector.ts b/src/diagrams/c4/c4Detector.ts new file mode 100644 index 000000000..2be62bff1 --- /dev/null +++ b/src/diagrams/c4/c4Detector.ts @@ -0,0 +1,5 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const c4Detector: DiagramDetector = (txt) => { + return txt.match(/^\s*C4Context|C4Container|C4Component|C4Dynamic|C4Deployment/) !== null; +}; diff --git a/src/diagrams/c4/c4Renderer.js b/src/diagrams/c4/c4Renderer.js index 409f38cbb..dceca2887 100644 --- a/src/diagrams/c4/c4Renderer.js +++ b/src/diagrams/c4/c4Renderer.js @@ -298,7 +298,7 @@ export const drawC4ShapeArray = function (currentBounds, diagram, c4ShapeArray, currentBounds.insert(c4Shape); - const height = svgDraw.drawC4Shape(diagram, c4Shape, conf); + svgDraw.drawC4Shape(diagram, c4Shape, conf); } currentBounds.bumpLastMargin(conf.c4ShapeMargin); @@ -616,7 +616,6 @@ export const draw = function (_text, id, _version, diagObj) { globalBoundaryMaxY = conf.diagramMarginY; const title = diagObj.db.getTitle(); - const c4type = diagObj.db.getC4Type(); let currentBoundarys = diagObj.db.getBoundarys(''); // switch (c4type) { // case 'C4Context': diff --git a/src/diagrams/c4/parser/c4Boundary.spec.js b/src/diagrams/c4/parser/c4Boundary.spec.js new file mode 100644 index 000000000..c7130f557 --- /dev/null +++ b/src/diagrams/c4/parser/c4Boundary.spec.js @@ -0,0 +1,110 @@ +import c4Db from '../c4Db'; +import c4 from './c4Diagram.jison'; +import { setConfig } from '../../../config'; + +setConfig({ + securityLevel: 'strict', +}); + +describe.each(['Boundary'])('parsing a C4 %s', function (macroName) { + beforeEach(function () { + c4.parser.yy = c4Db; + c4.parser.yy.clear(); + }); + + it('should parse a C4 diagram with one Boundary correctly', function () { + c4.parser.parse(`C4Context +title System Context diagram for Internet Banking System +${macroName}(b1, "BankBoundary") { +System(SystemAA, "Internet Banking System") +}`); + + const yy = c4.parser.yy; + + const boundaries = yy.getBoundarys(); + expect(boundaries.length).toBe(2); + const boundary = boundaries[1]; + + expect(boundary).toEqual({ + alias: 'b1', + label: { + text: 'BankBoundary', + }, + // TODO: Why are link, and tags undefined instead of not appearing at all? + // Compare to Person where they don't show up. + link: undefined, + tags: undefined, + parentBoundary: 'global', + type: { + // TODO: Why is this `system` instead of `boundary`? + text: 'system', + }, + wrap: false, + }); + }); + + it('should parse the alias', function () { + c4.parser.parse(`C4Context +${macroName}(b1, "BankBoundary") { +System(SystemAA, "Internet Banking System") +}`); + + expect(c4.parser.yy.getBoundarys()[1]).toMatchObject({ + alias: 'b1', + }); + }); + + it('should parse the label', function () { + c4.parser.parse(`C4Context +${macroName}(b1, "BankBoundary") { +System(SystemAA, "Internet Banking System") +}`); + + expect(c4.parser.yy.getBoundarys()[1]).toMatchObject({ + label: { + text: 'BankBoundary', + }, + }); + }); + + it('should parse the type', function () { + c4.parser.parse(`C4Context +${macroName}(b1, "", "company") { +System(SystemAA, "Internet Banking System") +}`); + + expect(c4.parser.yy.getBoundarys()[1]).toMatchObject({ + type: { text: 'company' }, + }); + }); + + it('should parse a link', function () { + c4.parser.parse(`C4Context +${macroName}(b1, $link="https://github.com/mermaidjs") { +System(SystemAA, "Internet Banking System") +}`); + + expect(c4.parser.yy.getBoundarys()[1]).toMatchObject({ + label: { + text: { + link: 'https://github.com/mermaidjs', + }, + }, + }); + }); + + it('should parse tags', function () { + c4.parser.parse(`C4Context +${macroName}(b1, $tags="tag1,tag2") { +System(SystemAA, "Internet Banking System") +}`); + + expect(c4.parser.yy.getBoundarys()[1]).toMatchObject({ + label: { + text: { + tags: 'tag1,tag2', + }, + }, + }); + }); +}); diff --git a/src/diagrams/c4/parser/c4Diagram.jison b/src/diagrams/c4/parser/c4Diagram.jison index 10783db53..03b851458 100644 --- a/src/diagrams/c4/parser/c4Diagram.jison +++ b/src/diagrams/c4/parser/c4Diagram.jison @@ -115,80 +115,80 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multiline");} "C4Dynamic" return 'C4_DYNAMIC'; "C4Deployment" return 'C4_DEPLOYMENT'; -"Person_Ext" { this.begin("person_ext"); console.log('begin person_ext'); return 'PERSON_EXT';} -"Person" { this.begin("person"); console.log('begin person'); return 'PERSON';} -"SystemQueue_Ext" { this.begin("system_ext_queue"); console.log('begin system_ext_queue'); return 'SYSTEM_EXT_QUEUE';} -"SystemDb_Ext" { this.begin("system_ext_db"); console.log('begin system_ext_db'); return 'SYSTEM_EXT_DB';} -"System_Ext" { this.begin("system_ext"); console.log('begin system_ext'); return 'SYSTEM_EXT';} -"SystemQueue" { this.begin("system_queue"); console.log('begin system_queue'); return 'SYSTEM_QUEUE';} -"SystemDb" { this.begin("system_db"); console.log('begin system_db'); return 'SYSTEM_DB';} -"System" { this.begin("system"); console.log('begin system'); return 'SYSTEM';} +"Person_Ext" { this.begin("person_ext"); return 'PERSON_EXT';} +"Person" { this.begin("person"); return 'PERSON';} +"SystemQueue_Ext" { this.begin("system_ext_queue"); return 'SYSTEM_EXT_QUEUE';} +"SystemDb_Ext" { this.begin("system_ext_db"); return 'SYSTEM_EXT_DB';} +"System_Ext" { this.begin("system_ext"); return 'SYSTEM_EXT';} +"SystemQueue" { this.begin("system_queue"); return 'SYSTEM_QUEUE';} +"SystemDb" { this.begin("system_db"); return 'SYSTEM_DB';} +"System" { this.begin("system"); return 'SYSTEM';} -"Boundary" { this.begin("boundary"); console.log('begin boundary'); return 'BOUNDARY';} -"Enterprise_Boundary" { this.begin("enterprise_boundary"); console.log('begin enterprise_boundary'); return 'ENTERPRISE_BOUNDARY';} -"System_Boundary" { this.begin("system_boundary"); console.log('begin system_boundary'); return 'SYSTEM_BOUNDARY';} +"Boundary" { this.begin("boundary"); return 'BOUNDARY';} +"Enterprise_Boundary" { this.begin("enterprise_boundary"); return 'ENTERPRISE_BOUNDARY';} +"System_Boundary" { this.begin("system_boundary"); return 'SYSTEM_BOUNDARY';} -"ContainerQueue_Ext" { this.begin("container_ext_queue"); console.log('begin container_ext_queue'); return 'CONTAINER_EXT_QUEUE';} -"ContainerDb_Ext" { this.begin("container_ext_db"); console.log('begin container_ext_db'); return 'CONTAINER_EXT_DB';} -"Container_Ext" { this.begin("container_ext"); console.log('begin container_ext'); return 'CONTAINER_EXT';} -"ContainerQueue" { this.begin("container_queue"); console.log('begin container_queue'); return 'CONTAINER_QUEUE';} -"ContainerDb" { this.begin("container_db"); console.log('begin container_db'); return 'CONTAINER_DB';} -"Container" { this.begin("container"); console.log('begin container'); return 'CONTAINER';} +"ContainerQueue_Ext" { this.begin("container_ext_queue"); return 'CONTAINER_EXT_QUEUE';} +"ContainerDb_Ext" { this.begin("container_ext_db"); return 'CONTAINER_EXT_DB';} +"Container_Ext" { this.begin("container_ext"); return 'CONTAINER_EXT';} +"ContainerQueue" { this.begin("container_queue"); return 'CONTAINER_QUEUE';} +"ContainerDb" { this.begin("container_db"); return 'CONTAINER_DB';} +"Container" { this.begin("container"); return 'CONTAINER';} -"Container_Boundary" { this.begin("container_boundary"); console.log('begin container_boundary'); return 'CONTAINER_BOUNDARY';} +"Container_Boundary" { this.begin("container_boundary"); return 'CONTAINER_BOUNDARY';} -"ComponentQueue_Ext" { this.begin("component_ext_queue"); console.log('begin component_ext_queue'); return 'COMPONENT_EXT_QUEUE';} -"ComponentDb_Ext" { this.begin("component_ext_db"); console.log('begin component_ext_db'); return 'COMPONENT_EXT_DB';} -"Component_Ext" { this.begin("component_ext"); console.log('begin component_ext'); return 'COMPONENT_EXT';} -"ComponentQueue" { this.begin("component_queue"); console.log('begin component_queue'); return 'COMPONENT_QUEUE';} -"ComponentDb" { this.begin("component_db"); console.log('begin component_db'); return 'COMPONENT_DB';} -"Component" { this.begin("component"); console.log('begin component'); return 'COMPONENT';} +"ComponentQueue_Ext" { this.begin("component_ext_queue"); return 'COMPONENT_EXT_QUEUE';} +"ComponentDb_Ext" { this.begin("component_ext_db"); return 'COMPONENT_EXT_DB';} +"Component_Ext" { this.begin("component_ext"); return 'COMPONENT_EXT';} +"ComponentQueue" { this.begin("component_queue"); return 'COMPONENT_QUEUE';} +"ComponentDb" { this.begin("component_db"); return 'COMPONENT_DB';} +"Component" { this.begin("component"); return 'COMPONENT';} -"Deployment_Node" { this.begin("node"); console.log('begin node'); return 'NODE';} -"Node" { this.begin("node"); console.log('begin node'); return 'NODE';} -"Node_L" { this.begin("node_l"); console.log('begin node_l'); return 'NODE_L';} -"Node_R" { this.begin("node_r"); console.log('begin node_r'); return 'NODE_R';} +"Deployment_Node" { this.begin("node"); return 'NODE';} +"Node" { this.begin("node"); return 'NODE';} +"Node_L" { this.begin("node_l"); return 'NODE_L';} +"Node_R" { this.begin("node_r"); return 'NODE_R';} -"Rel" { this.begin("rel"); console.log('begin rel'); return 'REL';} -"BiRel" { this.begin("birel"); console.log('begin birel'); return 'BIREL';} -"Rel_Up" { this.begin("rel_u"); console.log('begin rel_u'); return 'REL_U';} -"Rel_U" { this.begin("rel_u"); console.log('begin rel_u'); return 'REL_U';} -"Rel_Down" { this.begin("rel_d"); console.log('begin rel_d'); return 'REL_D';} -"Rel_D" { this.begin("rel_d"); console.log('begin rel_d'); return 'REL_D';} -"Rel_Left" { this.begin("rel_l"); console.log('begin rel_l'); return 'REL_L';} -"Rel_L" { this.begin("rel_l"); console.log('begin rel_l'); return 'REL_L';} -"Rel_Right" { this.begin("rel_r"); console.log('begin rel_r'); return 'REL_R';} -"Rel_R" { this.begin("rel_r"); console.log('begin rel_r'); return 'REL_R';} -"Rel_Back" { this.begin("rel_b"); console.log('begin rel_b'); return 'REL_B';} -"RelIndex" { this.begin("rel_index"); console.log('begin rel_index'); return 'REL_INDEX';} +"Rel" { this.begin("rel"); return 'REL';} +"BiRel" { this.begin("birel"); return 'BIREL';} +"Rel_Up" { this.begin("rel_u"); return 'REL_U';} +"Rel_U" { this.begin("rel_u"); return 'REL_U';} +"Rel_Down" { this.begin("rel_d"); return 'REL_D';} +"Rel_D" { this.begin("rel_d"); return 'REL_D';} +"Rel_Left" { this.begin("rel_l"); return 'REL_L';} +"Rel_L" { this.begin("rel_l"); return 'REL_L';} +"Rel_Right" { this.begin("rel_r"); return 'REL_R';} +"Rel_R" { this.begin("rel_r"); return 'REL_R';} +"Rel_Back" { this.begin("rel_b"); return 'REL_B';} +"RelIndex" { this.begin("rel_index"); return 'REL_INDEX';} -"UpdateElementStyle" { this.begin("update_el_style"); console.log('begin update_el_style'); return 'UPDATE_EL_STYLE';} -"UpdateRelStyle" { this.begin("update_rel_style"); console.log('begin update_rel_style'); return 'UPDATE_REL_STYLE';} -"UpdateLayoutConfig" { this.begin("update_layout_config"); console.log('begin update_layout_config'); return 'UPDATE_LAYOUT_CONFIG';} +"UpdateElementStyle" { this.begin("update_el_style"); return 'UPDATE_EL_STYLE';} +"UpdateRelStyle" { this.begin("update_rel_style"); return 'UPDATE_REL_STYLE';} +"UpdateLayoutConfig" { this.begin("update_layout_config"); return 'UPDATE_LAYOUT_CONFIG';} <person,person_ext,system_ext_queue,system_ext_db,system_ext,system_queue,system_db,system,boundary,enterprise_boundary,system_boundary,container_ext_db,container_ext,container_queue,container_db,container,container_boundary,component_ext_db,component_ext,component_queue,component_db,component,node,node_l,node_r,rel,birel,rel_u,rel_d,rel_l,rel_r,rel_b,rel_index,update_el_style,update_rel_style,update_layout_config><<EOF>> return "EOF_IN_STRUCT"; -<person,person_ext,system_ext_queue,system_ext_db,system_ext,system_queue,system_db,system,boundary,enterprise_boundary,system_boundary,container_ext_db,container_ext,container_queue,container_db,container,container_boundary,component_ext_db,component_ext,component_queue,component_db,component,node,node_l,node_r,rel,birel,rel_u,rel_d,rel_l,rel_r,rel_b,rel_index,update_el_style,update_rel_style,update_layout_config>[(][ ]*[,] { console.log('begin attribute with ATTRIBUTE_EMPTY'); this.begin("attribute"); return "ATTRIBUTE_EMPTY";} -<person,person_ext,system_ext_queue,system_ext_db,system_ext,system_queue,system_db,system,boundary,enterprise_boundary,system_boundary,container_ext_db,container_ext,container_queue,container_db,container,container_boundary,component_ext_db,component_ext,component_queue,component_db,component,node,node_l,node_r,rel,birel,rel_u,rel_d,rel_l,rel_r,rel_b,rel_index,update_el_style,update_rel_style,update_layout_config>[(] { console.log('begin attribute'); this.begin("attribute"); } -<person,person_ext,system_ext_queue,system_ext_db,system_ext,system_queue,system_db,system,boundary,enterprise_boundary,system_boundary,container_ext_db,container_ext,container_queue,container_db,container,container_boundary,component_ext_db,component_ext,component_queue,component_db,component,node,node_l,node_r,rel,birel,rel_u,rel_d,rel_l,rel_r,rel_b,rel_index,update_el_style,update_rel_style,update_layout_config,attribute>[)] { console.log('STOP attribute'); this.popState();console.log('STOP diagram'); this.popState();} +<person,person_ext,system_ext_queue,system_ext_db,system_ext,system_queue,system_db,system,boundary,enterprise_boundary,system_boundary,container_ext_db,container_ext,container_queue,container_db,container,container_boundary,component_ext_db,component_ext,component_queue,component_db,component,node,node_l,node_r,rel,birel,rel_u,rel_d,rel_l,rel_r,rel_b,rel_index,update_el_style,update_rel_style,update_layout_config>[(][ ]*[,] { this.begin("attribute"); return "ATTRIBUTE_EMPTY";} +<person,person_ext,system_ext_queue,system_ext_db,system_ext,system_queue,system_db,system,boundary,enterprise_boundary,system_boundary,container_ext_db,container_ext,container_queue,container_db,container,container_boundary,component_ext_db,component_ext,component_queue,component_db,component,node,node_l,node_r,rel,birel,rel_u,rel_d,rel_l,rel_r,rel_b,rel_index,update_el_style,update_rel_style,update_layout_config>[(] { this.begin("attribute"); } +<person,person_ext,system_ext_queue,system_ext_db,system_ext,system_queue,system_db,system,boundary,enterprise_boundary,system_boundary,container_ext_db,container_ext,container_queue,container_db,container,container_boundary,component_ext_db,component_ext,component_queue,component_db,component,node,node_l,node_r,rel,birel,rel_u,rel_d,rel_l,rel_r,rel_b,rel_index,update_el_style,update_rel_style,update_layout_config,attribute>[)] { this.popState();this.popState();} -<attribute>",," { console.log(',,'); return 'ATTRIBUTE_EMPTY';} -<attribute>"," { console.log(','); } -<attribute>[ ]*["]["] { console.log('ATTRIBUTE_EMPTY'); return 'ATTRIBUTE_EMPTY';} -<attribute>[ ]*["] { console.log('begin string'); this.begin("string");} -<string>["] { console.log('STOP string'); this.popState(); } -<string>[^"]* { console.log('STR'); return "STR";} +<attribute>",," { return 'ATTRIBUTE_EMPTY';} +<attribute>"," { } +<attribute>[ ]*["]["] { return 'ATTRIBUTE_EMPTY';} +<attribute>[ ]*["] { this.begin("string");} +<string>["] { this.popState(); } +<string>[^"]* { return "STR";} -<attribute>[ ]*[\$] { console.log('begin string_kv'); this.begin("string_kv");} -<string_kv>[^=]* { console.log('STR_KEY'); this.begin("string_kv_key"); return "STR_KEY";} -<string_kv_key>[=][ ]*["] { console.log('begin string_kv_value'); this.popState(); this.begin("string_kv_value"); } -<string_kv_value>[^"]+ { console.log('STR_VALUE'); return "STR_VALUE";} -<string_kv_value>["] { console.log('STOP string_kv_value'); this.popState(); this.popState(); } +<attribute>[ ]*[\$] { this.begin("string_kv");} +<string_kv>[^=]* { this.begin("string_kv_key"); return "STR_KEY";} +<string_kv_key>[=][ ]*["] { this.popState(); this.begin("string_kv_value"); } +<string_kv_value>[^"]+ { return "STR_VALUE";} +<string_kv_value>["] { this.popState(); this.popState(); } -<attribute>[^,]+ { console.log('not STR'); return "STR";} +<attribute>[^,]+ { return "STR";} -'{' { /* this.begin("lbrace"); */ console.log('begin boundary block'); return "LBRACE";} -'}' { /* this.popState(); */ console.log('STOP boundary block'); return "RBRACE";} +'{' { /* this.begin("lbrace"); */ return "LBRACE";} +'}' { /* this.popState(); */ return "RBRACE";} [\s]+ return 'SPACE'; [\n\r]+ return 'EOL'; @@ -231,7 +231,7 @@ directive ; openDirective - : open_directive { console.log("open_directive: ", $1); yy.parseDirective('%%{', 'open_directive'); } + : open_directive { yy.parseDirective('%%{', 'open_directive'); } ; typeDirective @@ -239,11 +239,11 @@ typeDirective ; argDirective - : arg_directive { $1 = $1.trim().replace(/'/g, '"'); console.log("arg_directive: ", $1); yy.parseDirective($1, 'arg_directive'); } + : arg_directive { $1 = $1.trim().replace(/'/g, '"'); yy.parseDirective($1, 'arg_directive'); } ; closeDirective - : close_directive { console.log("close_directive: ", $1); yy.parseDirective('}%%', 'close_directive', 'c4Context'); } + : close_directive { yy.parseDirective('}%%', 'close_directive', 'c4Context'); } ; graphConfig @@ -285,13 +285,13 @@ boundaryStartStatement ; boundaryStart - : ENTERPRISE_BOUNDARY attributes {console.log($1,JSON.stringify($2)); $2.splice(2, 0, 'ENTERPRISE'); yy.addPersonOrSystemBoundary(...$2); $$=$2;} - | SYSTEM_BOUNDARY attributes {console.log($1,JSON.stringify($2)); $2.splice(2, 0, 'ENTERPRISE'); yy.addPersonOrSystemBoundary(...$2); $$=$2;} - | BOUNDARY attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystemBoundary(...$2); $$=$2;} - | CONTAINER_BOUNDARY attributes {console.log($1,JSON.stringify($2)); $2.splice(2, 0, 'CONTAINER'); yy.addContainerBoundary(...$2); $$=$2;} - | NODE attributes {console.log($1,JSON.stringify($2)); yy.addDeploymentNode('node', ...$2); $$=$2;} - | NODE_L attributes {console.log($1,JSON.stringify($2)); yy.addDeploymentNode('nodeL', ...$2); $$=$2;} - | NODE_R attributes {console.log($1,JSON.stringify($2)); yy.addDeploymentNode('nodeR', ...$2); $$=$2;} + : ENTERPRISE_BOUNDARY attributes {$2.splice(2, 0, 'ENTERPRISE'); yy.addPersonOrSystemBoundary(...$2); $$=$2;} + | SYSTEM_BOUNDARY attributes {$2.splice(2, 0, 'ENTERPRISE'); yy.addPersonOrSystemBoundary(...$2); $$=$2;} + | BOUNDARY attributes {yy.addPersonOrSystemBoundary(...$2); $$=$2;} + | CONTAINER_BOUNDARY attributes {$2.splice(2, 0, 'CONTAINER'); yy.addContainerBoundary(...$2); $$=$2;} + | NODE attributes {yy.addDeploymentNode('node', ...$2); $$=$2;} + | NODE_L attributes {yy.addDeploymentNode('nodeL', ...$2); $$=$2;} + | NODE_R attributes {yy.addDeploymentNode('nodeR', ...$2); $$=$2;} ; boundaryStopStatement @@ -305,48 +305,48 @@ diagramStatements ; diagramStatement - : PERSON attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('person', ...$2); $$=$2;} - | PERSON_EXT attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('external_person', ...$2); $$=$2;} - | SYSTEM attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('system', ...$2); $$=$2;} - | SYSTEM_DB attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('system_db', ...$2); $$=$2;} - | SYSTEM_QUEUE attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('system_queue', ...$2); $$=$2;} - | SYSTEM_EXT attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('external_system', ...$2); $$=$2;} - | SYSTEM_EXT_DB attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('external_system_db', ...$2); $$=$2;} - | SYSTEM_EXT_QUEUE attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('external_system_queue', ...$2); $$=$2;} - | CONTAINER attributes {console.log($1,JSON.stringify($2)); yy.addContainer('container', ...$2); $$=$2;} - | CONTAINER_DB attributes {console.log($1,JSON.stringify($2)); yy.addContainer('container_db', ...$2); $$=$2;} - | CONTAINER_QUEUE attributes {console.log($1,JSON.stringify($2)); yy.addContainer('container_queue', ...$2); $$=$2;} - | CONTAINER_EXT attributes {console.log($1,JSON.stringify($2)); yy.addContainer('external_container', ...$2); $$=$2;} - | CONTAINER_EXT_DB attributes {console.log($1,JSON.stringify($2)); yy.addContainer('external_container_db', ...$2); $$=$2;} - | CONTAINER_EXT_QUEUE attributes {console.log($1,JSON.stringify($2)); yy.addContainer('external_container_queue', ...$2); $$=$2;} - | COMPONENT attributes {console.log($1,JSON.stringify($2)); yy.addComponent('component', ...$2); $$=$2;} - | COMPONENT_DB attributes {console.log($1,JSON.stringify($2)); yy.addComponent('component_db', ...$2); $$=$2;} - | COMPONENT_QUEUE attributes {console.log($1,JSON.stringify($2)); yy.addComponent('component_queue', ...$2); $$=$2;} - | COMPONENT_EXT attributes {console.log($1,JSON.stringify($2)); yy.addComponent('external_component', ...$2); $$=$2;} - | COMPONENT_EXT_DB attributes {console.log($1,JSON.stringify($2)); yy.addComponent('external_component_db', ...$2); $$=$2;} - | COMPONENT_EXT_QUEUE attributes {console.log($1,JSON.stringify($2)); yy.addComponent('external_component_queue', ...$2); $$=$2;} + : PERSON attributes {yy.addPersonOrSystem('person', ...$2); $$=$2;} + | PERSON_EXT attributes {yy.addPersonOrSystem('external_person', ...$2); $$=$2;} + | SYSTEM attributes {yy.addPersonOrSystem('system', ...$2); $$=$2;} + | SYSTEM_DB attributes {yy.addPersonOrSystem('system_db', ...$2); $$=$2;} + | SYSTEM_QUEUE attributes {yy.addPersonOrSystem('system_queue', ...$2); $$=$2;} + | SYSTEM_EXT attributes {yy.addPersonOrSystem('external_system', ...$2); $$=$2;} + | SYSTEM_EXT_DB attributes {yy.addPersonOrSystem('external_system_db', ...$2); $$=$2;} + | SYSTEM_EXT_QUEUE attributes {yy.addPersonOrSystem('external_system_queue', ...$2); $$=$2;} + | CONTAINER attributes {yy.addContainer('container', ...$2); $$=$2;} + | CONTAINER_DB attributes {yy.addContainer('container_db', ...$2); $$=$2;} + | CONTAINER_QUEUE attributes {yy.addContainer('container_queue', ...$2); $$=$2;} + | CONTAINER_EXT attributes {yy.addContainer('external_container', ...$2); $$=$2;} + | CONTAINER_EXT_DB attributes {yy.addContainer('external_container_db', ...$2); $$=$2;} + | CONTAINER_EXT_QUEUE attributes {yy.addContainer('external_container_queue', ...$2); $$=$2;} + | COMPONENT attributes {yy.addComponent('component', ...$2); $$=$2;} + | COMPONENT_DB attributes {yy.addComponent('component_db', ...$2); $$=$2;} + | COMPONENT_QUEUE attributes {yy.addComponent('component_queue', ...$2); $$=$2;} + | COMPONENT_EXT attributes {yy.addComponent('external_component', ...$2); $$=$2;} + | COMPONENT_EXT_DB attributes {yy.addComponent('external_component_db', ...$2); $$=$2;} + | COMPONENT_EXT_QUEUE attributes {yy.addComponent('external_component_queue', ...$2); $$=$2;} | boundaryStatement - | REL attributes {console.log($1,JSON.stringify($2)); yy.addRel('rel', ...$2); $$=$2;} - | BIREL attributes {console.log($1,JSON.stringify($2)); yy.addRel('birel', ...$2); $$=$2;} - | REL_U attributes {console.log($1,JSON.stringify($2)); yy.addRel('rel_u', ...$2); $$=$2;} - | REL_D attributes {console.log($1,JSON.stringify($2)); yy.addRel('rel_d', ...$2); $$=$2;} - | REL_L attributes {console.log($1,JSON.stringify($2)); yy.addRel('rel_l', ...$2); $$=$2;} - | REL_R attributes {console.log($1,JSON.stringify($2)); yy.addRel('rel_r', ...$2); $$=$2;} - | REL_B attributes {console.log($1,JSON.stringify($2)); yy.addRel('rel_b', ...$2); $$=$2;} - | REL_INDEX attributes {console.log($1,JSON.stringify($2)); $2.splice(0, 1); yy.addRel('rel', ...$2); $$=$2;} - | UPDATE_EL_STYLE attributes {console.log($1,JSON.stringify($2)); yy.updateElStyle('update_el_style', ...$2); $$=$2;} - | UPDATE_REL_STYLE attributes {console.log($1,JSON.stringify($2)); yy.updateRelStyle('update_rel_style', ...$2); $$=$2;} - | UPDATE_LAYOUT_CONFIG attributes {console.log($1,JSON.stringify($2)); yy.updateLayoutConfig('update_layout_config', ...$2); $$=$2;} + | REL attributes {yy.addRel('rel', ...$2); $$=$2;} + | BIREL attributes {yy.addRel('birel', ...$2); $$=$2;} + | REL_U attributes {yy.addRel('rel_u', ...$2); $$=$2;} + | REL_D attributes {yy.addRel('rel_d', ...$2); $$=$2;} + | REL_L attributes {yy.addRel('rel_l', ...$2); $$=$2;} + | REL_R attributes {yy.addRel('rel_r', ...$2); $$=$2;} + | REL_B attributes {yy.addRel('rel_b', ...$2); $$=$2;} + | REL_INDEX attributes {$2.splice(0, 1); yy.addRel('rel', ...$2); $$=$2;} + | UPDATE_EL_STYLE attributes {yy.updateElStyle('update_el_style', ...$2); $$=$2;} + | UPDATE_REL_STYLE attributes {yy.updateRelStyle('update_rel_style', ...$2); $$=$2;} + | UPDATE_LAYOUT_CONFIG attributes {yy.updateLayoutConfig('update_layout_config', ...$2); $$=$2;} ; attributes - : attribute { console.log('PUSH ATTRIBUTE: ', $1); $$ = [$1]; } - | attribute attributes { console.log('PUSH ATTRIBUTE: ', $1); $2.unshift($1); $$=$2;} + : attribute { $$ = [$1]; } + | attribute attributes { $2.unshift($1); $$=$2;} ; attribute : STR { $$ = $1.trim(); } - | STR_KEY STR_VALUE { console.log('kv: ', $1, $2); let kv={}; kv[$1.trim()]=$2.trim(); $$=kv; } + | STR_KEY STR_VALUE { let kv={}; kv[$1.trim()]=$2.trim(); $$=kv; } | ATTRIBUTE { $$ = $1.trim(); } | ATTRIBUTE_EMPTY { $$ = ""; } ; diff --git a/src/diagrams/c4/parser/flow.spec.js b/src/diagrams/c4/parser/c4Diagram.spec.js similarity index 50% rename from src/diagrams/c4/parser/flow.spec.js rename to src/diagrams/c4/parser/c4Diagram.spec.js index c01d99e40..b79934b84 100644 --- a/src/diagrams/c4/parser/flow.spec.js +++ b/src/diagrams/c4/parser/c4Diagram.spec.js @@ -1,49 +1,20 @@ -import flowDb from '../c4Db'; -import flow from './c4Diagram.jison'; +import c4Db from '../c4Db'; +import c4 from './c4Diagram.jison'; import { setConfig } from '../../../config'; setConfig({ securityLevel: 'strict', }); -describe('parsing a flow chart', function () { +describe('parsing a C4 diagram', function () { beforeEach(function () { - flow.parser.yy = flowDb; - flow.parser.yy.clear(); - }); - - it('should parse a C4 diagram with one Person correctly', function () { - flow.parser.parse(`C4Context -title System Context diagram for Internet Banking System -Person(customerA, "Banking Customer A", "A customer of the bank, with personal bank accounts.")`); - - const yy = flow.parser.yy; - expect(yy.getC4Type()).toBe('C4Context'); - expect(yy.getTitle()).toBe('System Context diagram for Internet Banking System'); - - const shapes = yy.getC4ShapeArray(); - expect(shapes.length).toBe(1); - const onlyShape = shapes[0]; - - expect(onlyShape).toEqual({ - alias: 'customerA', - descr: { - text: 'A customer of the bank, with personal bank accounts.', - }, - label: { - text: 'Banking Customer A', - }, - parentBoundary: 'global', - typeC4Shape: { - text: 'person', - }, - wrap: false, - }); + c4.parser.yy = c4Db; + c4.parser.yy.clear(); }); it('should handle a trailing whitespaces after statements', function () { const whitespace = ' '; - const rendered = flow.parser.parse(`C4Context${whitespace} + const rendered = c4.parser.parse(`C4Context${whitespace} title System Context diagram for Internet Banking System${whitespace} Person(customerA, "Banking Customer A", "A customer of the bank, with personal bank accounts.")${whitespace}`); @@ -51,11 +22,11 @@ Person(customerA, "Banking Customer A", "A customer of the bank, with personal b }); it('should handle parameter names that are keywords', function () { - flow.parser.parse(`C4Context + c4.parser.parse(`C4Context title title Person(Person, "Person", "Person")`); - const yy = flow.parser.yy; + const yy = c4.parser.yy; expect(yy.getTitle()).toBe('title'); const shapes = yy.getC4ShapeArray(); @@ -68,10 +39,10 @@ Person(Person, "Person", "Person")`); }); it('should allow default in the parameters', function () { - flow.parser.parse(`C4Context + c4.parser.parse(`C4Context Person(default, "default", "default")`); - const yy = flow.parser.yy; + const yy = c4.parser.yy; const shapes = yy.getC4ShapeArray(); expect(shapes.length).toBe(1); diff --git a/src/diagrams/c4/parser/c4Person.spec.js b/src/diagrams/c4/parser/c4Person.spec.js new file mode 100644 index 000000000..b504c0384 --- /dev/null +++ b/src/diagrams/c4/parser/c4Person.spec.js @@ -0,0 +1,111 @@ +import c4Db from '../c4Db'; +import c4 from './c4Diagram.jison'; +import { setConfig } from '../../../config'; + +setConfig({ + securityLevel: 'strict', +}); + +describe('parsing a C4 Person', function () { + beforeEach(function () { + c4.parser.yy = c4Db; + c4.parser.yy.clear(); + }); + + it('should parse a C4 diagram with one Person correctly', function () { + c4.parser.parse(`C4Context +title System Context diagram for Internet Banking System +Person(customerA, "Banking Customer A", "A customer of the bank, with personal bank accounts.")`); + + const yy = c4.parser.yy; + + const shapes = yy.getC4ShapeArray(); + expect(shapes.length).toBe(1); + const onlyShape = shapes[0]; + + expect(onlyShape).toEqual({ + alias: 'customerA', + descr: { + text: 'A customer of the bank, with personal bank accounts.', + }, + label: { + text: 'Banking Customer A', + }, + parentBoundary: 'global', + typeC4Shape: { + text: 'person', + }, + wrap: false, + }); + }); + + it('should parse the alias', function () { + c4.parser.parse(`C4Context +Person(customerA, "Banking Customer A")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + alias: 'customerA', + }); + }); + + it('should parse the label', function () { + c4.parser.parse(`C4Context +Person(customerA, "Banking Customer A")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + label: { + text: 'Banking Customer A', + }, + }); + }); + + it('should parse the description', function () { + c4.parser.parse(`C4Context +Person(customerA, "", "A customer of the bank, with personal bank accounts.")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + descr: { + text: 'A customer of the bank, with personal bank accounts.', + }, + }); + }); + + it('should parse a sprite', function () { + c4.parser.parse(`C4Context +Person(customerA, $sprite="users")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + label: { + text: { + sprite: 'users', + }, + }, + }); + }); + + it('should parse a link', function () { + c4.parser.parse(`C4Context +Person(customerA, $link="https://github.com/mermaidjs")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + label: { + text: { + link: 'https://github.com/mermaidjs', + }, + }, + }); + }); + + it('should parse tags', function () { + c4.parser.parse(`C4Context +Person(customerA, $tags="tag1,tag2")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + label: { + text: { + tags: 'tag1,tag2', + }, + }, + }); + }); +}); diff --git a/src/diagrams/c4/parser/c4PersonExt.spec.js b/src/diagrams/c4/parser/c4PersonExt.spec.js new file mode 100644 index 000000000..76547600a --- /dev/null +++ b/src/diagrams/c4/parser/c4PersonExt.spec.js @@ -0,0 +1,116 @@ +import c4Db from '../c4Db'; +import c4 from './c4Diagram.jison'; +import { setConfig } from '../../../config'; + +setConfig({ + securityLevel: 'strict', +}); + +describe('parsing a C4 Person_Ext', function () { + beforeEach(function () { + c4.parser.yy = c4Db; + c4.parser.yy.clear(); + }); + + it('should parse a C4 diagram with one Person_Ext correctly', function () { + c4.parser.parse(`C4Context +title System Context diagram for Internet Banking System +Person_Ext(customerA, "Banking Customer A", "A customer of the bank, with personal bank accounts.")`); + + const yy = c4.parser.yy; + + const shapes = yy.getC4ShapeArray(); + expect(shapes.length).toBe(1); + const onlyShape = shapes[0]; + + expect(onlyShape).toEqual({ + alias: 'customerA', + descr: { + text: 'A customer of the bank, with personal bank accounts.', + }, + label: { + text: 'Banking Customer A', + }, + // TODO: Why are link, sprite, and tags undefined instead of not appearing at all? + // Compare to Person where they don't show up. + link: undefined, + sprite: undefined, + tags: undefined, + parentBoundary: 'global', + typeC4Shape: { + text: 'external_person', + }, + wrap: false, + }); + }); + + it('should parse the alias', function () { + c4.parser.parse(`C4Context +Person_Ext(customerA, "Banking Customer A")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + alias: 'customerA', + }); + }); + + it('should parse the label', function () { + c4.parser.parse(`C4Context +Person_Ext(customerA, "Banking Customer A")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + label: { + text: 'Banking Customer A', + }, + }); + }); + + it('should parse the description', function () { + c4.parser.parse(`C4Context +Person_Ext(customerA, "", "A customer of the bank, with personal bank accounts.")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + descr: { + text: 'A customer of the bank, with personal bank accounts.', + }, + }); + }); + + it('should parse a sprite', function () { + c4.parser.parse(`C4Context +Person_Ext(customerA, $sprite="users")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + label: { + text: { + sprite: 'users', + }, + }, + }); + }); + + it('should parse a link', function () { + c4.parser.parse(`C4Context +Person_Ext(customerA, $link="https://github.com/mermaidjs")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + label: { + text: { + link: 'https://github.com/mermaidjs', + }, + }, + }); + }); + + it('should parse tags', function () { + c4.parser.parse(`C4Context +Person_Ext(customerA, $tags="tag1,tag2")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + label: { + text: { + tags: 'tag1,tag2', + }, + }, + }); + }); +}); diff --git a/src/diagrams/c4/parser/c4System.spec.js b/src/diagrams/c4/parser/c4System.spec.js new file mode 100644 index 000000000..6d81c7379 --- /dev/null +++ b/src/diagrams/c4/parser/c4System.spec.js @@ -0,0 +1,123 @@ +import c4Db from '../c4Db'; +import c4 from './c4Diagram.jison'; +import { setConfig } from '../../../config'; + +setConfig({ + securityLevel: 'strict', +}); + +describe.each([ + ['System', 'system'], + ['SystemDb', 'system_db'], + ['SystemQueue', 'system_queue'], + ['System_Ext', 'external_system'], + ['SystemDb_Ext', 'external_system_db'], + ['SystemQueue_Ext', 'external_system_queue'], +])('parsing a C4 %s', function (macroName, elementName) { + beforeEach(function () { + c4.parser.yy = c4Db; + c4.parser.yy.clear(); + }); + + it('should parse a C4 diagram with one System correctly', function () { + c4.parser.parse(`C4Context +title System Context diagram for Internet Banking System +${macroName}(SystemAA, "Internet Banking System", "Allows customers to view information about their bank accounts, and make payments.")`); + + const yy = c4.parser.yy; + + const shapes = yy.getC4ShapeArray(); + expect(shapes.length).toBe(1); + const onlyShape = shapes[0]; + + expect(onlyShape).toEqual({ + alias: 'SystemAA', + descr: { + text: 'Allows customers to view information about their bank accounts, and make payments.', + }, + label: { + text: 'Internet Banking System', + }, + // TODO: Why are link, sprite, and tags undefined instead of not appearing at all? + // Compare to Person where they don't show up. + link: undefined, + sprite: undefined, + tags: undefined, + parentBoundary: 'global', + typeC4Shape: { + text: elementName, + }, + wrap: false, + }); + }); + + it('should parse the alias', function () { + c4.parser.parse(`C4Context +${macroName}(SystemAA, "Internet Banking System")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + alias: 'SystemAA', + }); + }); + + it('should parse the label', function () { + c4.parser.parse(`C4Context +${macroName}(SystemAA, "Internet Banking System")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + label: { + text: 'Internet Banking System', + }, + }); + }); + + it('should parse the description', function () { + c4.parser.parse(`C4Context +${macroName}(SystemAA, "", "Allows customers to view information about their bank accounts, and make payments.")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + descr: { + text: 'Allows customers to view information about their bank accounts, and make payments.', + }, + }); + }); + + it('should parse a sprite', function () { + c4.parser.parse(`C4Context +${macroName}(SystemAA, $sprite="users")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + label: { + text: { + sprite: 'users', + }, + }, + }); + }); + + it('should parse a link', function () { + c4.parser.parse(`C4Context +${macroName}(SystemAA, $link="https://github.com/mermaidjs")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + label: { + text: { + link: 'https://github.com/mermaidjs', + }, + }, + }); + }); + + it('should parse tags', function () { + c4.parser.parse(`C4Context +${macroName}(SystemAA, $tags="tag1,tag2")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + label: { + text: { + tags: 'tag1,tag2', + }, + }, + }); + }); +}); diff --git a/src/diagrams/c4/svgDraw.js b/src/diagrams/c4/svgDraw.js index c67fb2649..5666d9f84 100644 --- a/src/diagrams/c4/svgDraw.js +++ b/src/diagrams/c4/svgDraw.js @@ -1,5 +1,4 @@ import common from '../common/common'; -import { addFunction } from '../../interactionDb'; import { sanitizeUrl } from '@braintree/sanitize-url'; export const drawRect = function (elem, rectData) { diff --git a/src/diagrams/class/classDetector-V2.ts b/src/diagrams/class/classDetector-V2.ts new file mode 100644 index 000000000..a0e270100 --- /dev/null +++ b/src/diagrams/class/classDetector-V2.ts @@ -0,0 +1,9 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const classDetectorV2: DiagramDetector = (txt, config) => { + // If we have confgured to use dagre-wrapper then we should return true in this function for classDiagram code thus making it use the new class diagram + if (txt.match(/^\s*classDiagram/) !== null && config?.class?.defaultRenderer === 'dagre-wrapper') + return true; + // We have not opted to use the new renderer so we should return true if we detect a class diagram + return txt.match(/^\s*classDiagram-v2/) !== null; +}; diff --git a/src/diagrams/class/classDetector.ts b/src/diagrams/class/classDetector.ts new file mode 100644 index 000000000..19d8bd2f5 --- /dev/null +++ b/src/diagrams/class/classDetector.ts @@ -0,0 +1,8 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const classDetector: DiagramDetector = (txt, config) => { + // If we have confgured to use dagre-wrapper then we should never return true in this function + if (config?.class?.defaultRenderer === 'dagre-wrapper') return false; + // We have not opted to use the new renderer so we should return true if we detect a class diagram + return txt.match(/^\s*classDiagram/) !== null; +}; diff --git a/src/diagrams/class/classDiagramGrammar.spec.js b/src/diagrams/class/classDiagramGrammar.spec.js index 0bc5af957..4e9e99c70 100644 --- a/src/diagrams/class/classDiagramGrammar.spec.js +++ b/src/diagrams/class/classDiagramGrammar.spec.js @@ -1,3 +1,4 @@ +// eslint-disable-next-line @typescript-eslint/no-var-requires const fs = require('fs'); import { LALRGenerator } from 'jison'; diff --git a/src/diagrams/class/classRenderer-v2.js b/src/diagrams/class/classRenderer-v2.js index a211ab552..20722e6d0 100644 --- a/src/diagrams/class/classRenderer-v2.js +++ b/src/diagrams/class/classRenderer-v2.js @@ -3,7 +3,6 @@ import graphlib from 'graphlib'; import { log } from '../../logger'; import { getConfig } from '../../config'; import { render } from '../../dagre-wrapper/index.js'; -// import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js'; import { curveLinear } from 'd3'; import { interpolateToCurve, getStylesFromArray } from '../../utils'; import { setupGraphViewbox } from '../../setupGraphViewbox'; @@ -11,7 +10,6 @@ import common from '../common/common'; import addSVGAccessibilityFields from '../../accessibility'; let idCache = {}; -const padding = 20; const sanitizeText = (txt) => common.sanitizeText(txt, getConfig()); @@ -235,20 +233,6 @@ export const addRelations = function (relations, g) { }); }; -/** - * Gets the ID with the same label as in the cache - * - * @param {string} label The label to look for - * @returns {string} The resulting ID - */ -const getGraphId = function (label) { - const foundEntry = Object.entries(idCache).find((entry) => entry[1].label === label); - - if (foundEntry) { - return foundEntry[0]; - } -}; - /** * Merges the value of `conf` with the passed `cnf` * diff --git a/src/diagrams/class/classRenderer.js b/src/diagrams/class/classRenderer.js index 6536cb5a1..c1236afea 100644 --- a/src/diagrams/class/classRenderer.js +++ b/src/diagrams/class/classRenderer.js @@ -10,12 +10,6 @@ import addSVGAccessibilityFields from '../../accessibility'; let idCache = {}; const padding = 20; -const confa = { - dividerMargin: 10, - padding: 5, - textHeight: 10, -}; - /** * Gets the ID with the same label as in the cache * @@ -163,7 +157,6 @@ export const draw = function (text, id, _version, diagObj) { securityLevel === 'sandbox' ? select(sandboxElement.nodes()[0].contentDocument.body) : select('body'); - const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; // Fetch the default direction, use TD if none was found const diagram = root.select(`[id='${id}']`); diff --git a/src/diagrams/er/erDb.js b/src/diagrams/er/erDb.js index 856d54979..ad3454f84 100644 --- a/src/diagrams/er/erDb.js +++ b/src/diagrams/er/erDb.js @@ -1,7 +1,7 @@ import { log } from '../../logger'; import mermaidAPI from '../../mermaidAPI'; import * as configApi from '../../config'; -import common from '../common/common'; + import { setAccTitle, getAccTitle, @@ -12,8 +12,6 @@ import { let entities = {}; let relationships = []; -let title = ''; -let description = ''; const Cardinality = { ZERO_OR_ONE: 'ZERO_OR_ONE', @@ -78,7 +76,6 @@ const getRelationships = () => relationships; const clear = function () { entities = {}; relationships = []; - title = ''; commonClear(); }; diff --git a/src/diagrams/er/erDetector.ts b/src/diagrams/er/erDetector.ts new file mode 100644 index 000000000..a17eafb81 --- /dev/null +++ b/src/diagrams/er/erDetector.ts @@ -0,0 +1,5 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const erDetector: DiagramDetector = (txt) => { + return txt.match(/^\s*erDiagram/) !== null; +}; diff --git a/src/errorRenderer.ts b/src/diagrams/error/errorRenderer.ts similarity index 91% rename from src/errorRenderer.ts rename to src/diagrams/error/errorRenderer.ts index de0b31886..df9ce2c6e 100644 --- a/src/errorRenderer.ts +++ b/src/diagrams/error/errorRenderer.ts @@ -1,7 +1,7 @@ /** Created by knut on 14-12-11. */ import { select } from 'd3'; -import { log } from './logger'; -import { getErrorMessage } from './utils'; +import { log } from '../../logger'; +import { getErrorMessage } from '../../utils'; let conf = {}; @@ -17,10 +17,11 @@ export const setConf = function (cnf: any) { /** * Draws a an info picture in the tag with id: id based on the graph definition in text. * + * @param text * @param {string} id The text for the error * @param {string} mermaidVersion The version */ -export const draw = (id: string, mermaidVersion: string) => { +export const draw = (text: string, id: string, mermaidVersion: string) => { try { log.debug('Renering svg for syntax error\n'); @@ -72,22 +73,22 @@ export const draw = (id: string, mermaidVersion: string) => { g.append('text') // text label for the x axis .attr('class', 'error-text') - .attr('x', 1240) + .attr('x', 1440) .attr('y', 250) .attr('font-size', '150px') .style('text-anchor', 'middle') .text('Syntax error in graph'); g.append('text') // text label for the x axis .attr('class', 'error-text') - .attr('x', 1050) + .attr('x', 1250) .attr('y', 400) .attr('font-size', '100px') .style('text-anchor', 'middle') .text('mermaid version ' + mermaidVersion); svg.attr('height', 100); - svg.attr('width', 400); - svg.attr('viewBox', '768 0 512 512'); + svg.attr('width', 500); + svg.attr('viewBox', '768 0 912 512'); } catch (e) { log.error('Error while rendering info diagram'); log.error(getErrorMessage(e)); diff --git a/src/diagrams/error/styles.js b/src/diagrams/error/styles.js new file mode 100644 index 000000000..0b0729813 --- /dev/null +++ b/src/diagrams/error/styles.js @@ -0,0 +1,3 @@ +const getStyles = () => ``; + +export default getStyles; diff --git a/src/diagrams/flowchart/flowDetector-v2.ts b/src/diagrams/flowchart/flowDetector-v2.ts new file mode 100644 index 000000000..f73748c79 --- /dev/null +++ b/src/diagrams/flowchart/flowDetector-v2.ts @@ -0,0 +1,8 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const flowDetectorV2: DiagramDetector = (txt, config) => { + // If we have confgured to use dagre-wrapper then we should return true in this function for graph code thus making it use the new flowchart diagram + if (config?.flowchart?.defaultRenderer === 'dagre-wrapper' && txt.match(/^\s*graph/) !== null) + return true; + return txt.match(/^\s*flowchart/) !== null; +}; diff --git a/src/diagrams/flowchart/flowDetector.ts b/src/diagrams/flowchart/flowDetector.ts new file mode 100644 index 000000000..edc9096c0 --- /dev/null +++ b/src/diagrams/flowchart/flowDetector.ts @@ -0,0 +1,8 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const flowDetector: DiagramDetector = (txt, config) => { + // If we have confired to only use new flow charts this function shohuld always return false + // as in not signalling true for a legacy flowchart + if (config?.flowchart?.defaultRenderer === 'dagre-wrapper') return false; + return txt.match(/^\s*graph/) !== null; +}; diff --git a/src/diagrams/flowchart/flowRenderer.addEdges.spec.js b/src/diagrams/flowchart/flowRenderer.addEdges.spec.js new file mode 100644 index 000000000..41868e203 --- /dev/null +++ b/src/diagrams/flowchart/flowRenderer.addEdges.spec.js @@ -0,0 +1,151 @@ +import flowDb from './flowDb'; +import flowParser from './parser/flow'; +import flowRenderer from './flowRenderer'; +import Diagram from '../../Diagram'; +import { addDiagrams } from '../../diagram-api/diagram-orchestration'; +addDiagrams(); + +describe('when using mermaid and ', function () { + describe('when calling addEdges ', function () { + beforeEach(function () { + flowParser.parser.yy = flowDb; + flowDb.clear(); + flowDb.setGen('gen-2'); + }); + it('should handle edges with text', function () { + const diag = new Diagram('graph TD;A-->|text ex|B;'); + diag.db.getVertices(); + const edges = diag.db.getEdges(); + + const mockG = { + setEdge: function (start, end, options) { + expect(start).toContain('flowchart-A-'); + expect(end).toContain('flowchart-B-'); + expect(options.arrowhead).toBe('normal'); + expect(options.label.match('text ex')).toBeTruthy(); + }, + }; + + flowRenderer.addEdges(edges, mockG, diag); + }); + + it('should handle edges without text', function () { + const diag = new Diagram('graph TD;A-->B;'); + diag.db.getVertices(); + const edges = diag.db.getEdges(); + + const mockG = { + setEdge: function (start, end, options) { + expect(start).toContain('flowchart-A-'); + expect(end).toContain('flowchart-B-'); + expect(options.arrowhead).toBe('normal'); + }, + }; + + flowRenderer.addEdges(edges, mockG, diag); + }); + + it('should handle open-ended edges', function () { + const diag = new Diagram('graph TD;A---B;'); + diag.db.getVertices(); + const edges = diag.db.getEdges(); + + const mockG = { + setEdge: function (start, end, options) { + expect(start).toContain('flowchart-A-'); + expect(end).toContain('flowchart-B-'); + expect(options.arrowhead).toBe('none'); + }, + }; + + flowRenderer.addEdges(edges, mockG, diag); + }); + + it('should handle edges with styles defined', function () { + const diag = new Diagram('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;'); + diag.db.getVertices(); + const edges = diag.db.getEdges(); + + const mockG = { + setEdge: function (start, end, options) { + expect(start).toContain('flowchart-A-'); + expect(end).toContain('flowchart-B-'); + expect(options.arrowhead).toBe('none'); + expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;'); + }, + }; + + flowRenderer.addEdges(edges, mockG, diag); + }); + it('should handle edges with interpolation defined', function () { + const diag = new Diagram('graph TD;A---B; linkStyle 0 interpolate basis'); + diag.db.getVertices(); + const edges = diag.db.getEdges(); + + const mockG = { + setEdge: function (start, end, options) { + expect(start).toContain('flowchart-A-'); + expect(end).toContain('flowchart-B-'); + expect(options.arrowhead).toBe('none'); + expect(options.curve).toBe('basis'); // mocked as string + }, + }; + + flowRenderer.addEdges(edges, mockG, diag); + }); + it('should handle edges with text and styles defined', function () { + const diag = new Diagram( + 'graph TD;A---|the text|B; linkStyle 0 stroke:val1,stroke-width:val2;' + ); + diag.db.getVertices(); + const edges = diag.db.getEdges(); + + const mockG = { + setEdge: function (start, end, options) { + expect(start).toContain('flowchart-A-'); + expect(end).toContain('flowchart-B-'); + expect(options.arrowhead).toBe('none'); + expect(options.label.match('the text')).toBeTruthy(); + expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;'); + }, + }; + + flowRenderer.addEdges(edges, mockG, diag); + }); + + it('should set fill to "none" by default when handling edges', function () { + const diag = new Diagram('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;'); + diag.db.getVertices(); + const edges = diag.db.getEdges(); + + const mockG = { + setEdge: function (start, end, options) { + expect(start).toContain('flowchart-A-'); + expect(end).toContain('flowchart-B'); + expect(options.arrowhead).toBe('none'); + expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;'); + }, + }; + + flowRenderer.addEdges(edges, mockG, diag); + }); + + it('should not set fill to none if fill is set in linkStyle', function () { + const diag = new Diagram( + 'graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2,fill:blue;' + ); + diag.db.getVertices(); + const edges = diag.db.getEdges(); + const mockG = { + setEdge: function (start, end, options) { + expect(start).toContain('flowchart-A-'); + expect(end).toContain('flowchart-B-'); + expect(options.arrowhead).toBe('none'); + expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:blue;'); + }, + }; + + flowRenderer.addEdges(edges, mockG, diag); + }); + }); +}); diff --git a/src/diagrams/flowchart/flowRenderer.js b/src/diagrams/flowchart/flowRenderer.js index 5b14330dd..0c3aa3623 100644 --- a/src/diagrams/flowchart/flowRenderer.js +++ b/src/diagrams/flowchart/flowRenderer.js @@ -29,8 +29,6 @@ export const setConf = function (cnf) { * @param diagObj */ export const addVertices = function (vert, g, svgId, root, _doc, diagObj) { - const securityLevel = getConfig().securityLevel; - const svg = !root ? select(`[id="${svgId}"]`) : root.select(`[id="${svgId}"]`); const doc = !_doc ? document : _doc; const keys = Object.keys(vert); diff --git a/src/diagrams/gantt/ganttDb.js b/src/diagrams/gantt/ganttDb.js index f6a526759..5d072b903 100644 --- a/src/diagrams/gantt/ganttDb.js +++ b/src/diagrams/gantt/ganttDb.js @@ -4,7 +4,7 @@ import { log } from '../../logger'; import * as configApi from '../../config'; import utils from '../../utils'; import mermaidAPI from '../../mermaidAPI'; -import common from '../common/common'; + import { setAccTitle, getAccTitle, @@ -21,8 +21,6 @@ let todayMarker = ''; let includes = []; let excludes = []; let links = {}; -let title = ''; -let accDescription = ''; let sections = []; let tasks = []; let currentSection = ''; @@ -34,10 +32,6 @@ let topAxis = false; // The serial order of the task in the script let lastOrder = 0; -const sanitizeText = function (txt) { - return common.sanitizeText(txt, configApi.getConfig()); -}; - export const parseDirective = function (statement, context, type) { mermaidAPI.parseDirective(this, statement, context, type); }; @@ -47,7 +41,6 @@ export const clear = function () { tasks = []; currentSection = ''; funs = []; - title = ''; taskCnt = 0; lastTask = undefined; lastTaskID = undefined; @@ -247,7 +240,8 @@ const getStartDate = function (prevTime, dateFormat, str) { * - `ms` for milliseconds * * @param {string} str - A string representing the duration. - * @returns {moment.Duration} A moment duration, including an invalid moment for invalid input string. + * @returns {moment.Duration} A moment duration, including an invalid moment for invalid input + * string. */ const parseDuration = function (str) { const statement = /^(\d+(?:\.\d+)?)([yMwdhms]|ms)$/.exec(str.trim()); diff --git a/src/diagrams/gantt/ganttDetector.ts b/src/diagrams/gantt/ganttDetector.ts new file mode 100644 index 000000000..926792dcf --- /dev/null +++ b/src/diagrams/gantt/ganttDetector.ts @@ -0,0 +1,5 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const ganttDetector: DiagramDetector = (txt) => { + return txt.match(/^\s*gantt/) !== null; +}; diff --git a/src/diagrams/gantt/ganttRenderer.js b/src/diagrams/gantt/ganttRenderer.js index 5a24d6d3f..3b12bc191 100644 --- a/src/diagrams/gantt/ganttRenderer.js +++ b/src/diagrams/gantt/ganttRenderer.js @@ -391,7 +391,6 @@ export const draw = function (text, id, version, diagObj) { if (securityLevel === 'sandbox') { let sandboxElement; sandboxElement = select('#i' + id); - const root = select(sandboxElement.nodes()[0].contentDocument.body); const doc = sandboxElement.nodes()[0].contentDocument; rectangles diff --git a/src/diagrams/git/gitGraphParserV2.spec.js b/src/diagrams/git/gitGraphParserV2.spec.js index 9a33e288f..b6c9c2459 100644 --- a/src/diagrams/git/gitGraphParserV2.spec.js +++ b/src/diagrams/git/gitGraphParserV2.spec.js @@ -363,6 +363,37 @@ describe('when parsing a gitGraph', function () { expect(Object.keys(parser.yy.getBranches()).length).toBe(2); }); + it('should allow branch names starting with unusual prefixes', function () { + const str = `gitGraph: + commit + %% branch names starting with numbers are not recommended, but are supported by git + branch branch01 + branch checkout02 + branch cherry-pick03 + branch branch/example-branch + branch merge/test_merge + %% single character branch name + branch A + `; + + parser.parse(str); + const commits = parser.yy.getCommits(); + expect(Object.keys(commits).length).toBe(1); + expect(parser.yy.getCurrentBranch()).toBe('A'); + expect(parser.yy.getDirection()).toBe('LR'); + expect(Object.keys(parser.yy.getBranches()).length).toBe(7); + expect(Object.keys(parser.yy.getBranches())).toEqual( + expect.arrayContaining([ + 'branch01', + 'checkout02', + 'cherry-pick03', + 'branch/example-branch', + 'merge/test_merge', + 'A', + ]) + ); + }); + it('should handle new branch checkout', function () { const str = `gitGraph: commit @@ -550,8 +581,6 @@ describe('when parsing a gitGraph', function () { testBranch3Merge, ] = Object.values(commits); - console.log(Object.keys(commits)); - expect(mainCommit.branch).toBe('main'); expect(mainCommit.parents).toStrictEqual([]); diff --git a/src/diagrams/git/gitGraphRenderer.js b/src/diagrams/git/gitGraphRenderer.js index 5a9036b88..68905c0d2 100644 --- a/src/diagrams/git/gitGraphRenderer.js +++ b/src/diagrams/git/gitGraphRenderer.js @@ -5,7 +5,6 @@ import { getConfig } from '../../config'; import addSVGAccessibilityFields from '../../accessibility'; let allCommitsDict = {}; -let branchNum; const commitType = { NORMAL: 0, @@ -83,7 +82,7 @@ const drawCommits = (svg, commits, modifyGraph) => { const sortedKeys = keys.sort((a, b) => { return commits[a].seq - commits[b].seq; }); - sortedKeys.forEach((key, index) => { + sortedKeys.forEach((key) => { const commit = commits[key]; const y = branchPos[commit.branch].pos; @@ -92,7 +91,9 @@ const drawCommits = (svg, commits, modifyGraph) => { if (modifyGraph) { let typeClass; let commitSymbolType = - typeof commit.customType !== 'undefined' ? commit.customType : commit.type; + typeof commit.customType !== 'undefined' && commit.customType !== '' + ? commit.customType + : commit.type; switch (commitSymbolType) { case commitType.NORMAL: typeClass = 'commit-normal'; @@ -290,18 +291,15 @@ const drawCommits = (svg, commits, modifyGraph) => { }; /** - * Detect if there are other commits between commit1's x-position and commit2's x-position on the same - * branch as commit2. + * Detect if there are other commits between commit1's x-position and commit2's x-position on the + * same branch as commit2. * * @param {any} commit1 * @param {any} commit2 * @param allCommits - * @returns {boolean} if there are commits between commit1's x-position and commit2's x-position + * @returns {boolean} If there are commits between commit1's x-position and commit2's x-position */ const hasOverlappingCommits = (commit1, commit2, allCommits) => { - const commit1Pos = commitPos[commit2.id]; - const commit2Pos = commitPos[commit1.id]; - // Find commits on the same branch as commit2 const keys = Object.keys(allCommits); const overlappingComits = keys.filter((key) => { @@ -322,7 +320,7 @@ const hasOverlappingCommits = (commit1, commit2, allCommits) => { * @param {any} y1 * @param {any} y2 * @param {any} _depth - * @returns {number} y value between y1 and y2 + * @returns {number} Y value between y1 and y2 */ const findLane = (y1, y2, _depth) => { const depth = _depth || 0; @@ -355,25 +353,11 @@ const findLane = (y1, y2, _depth) => { * @param {any} allCommits */ const drawArrow = (svg, commit1, commit2, allCommits) => { - const conf = getConfig(); - const p1 = commitPos[commit1.id]; const p2 = commitPos[commit2.id]; const overlappingCommits = hasOverlappingCommits(commit1, commit2, allCommits); // log.debug('drawArrow', p1, p2, overlappingCommits, commit1.id, commit2.id); - let url = ''; - if (conf.arrowMarkerAbsolute) { - url = - window.location.protocol + - '//' + - window.location.host + - window.location.pathname + - window.location.search; - url = url.replace(/\(/g, '\\('); - url = url.replace(/\)/g, '\\)'); - } - let arc = ''; let arc2 = ''; let radius = 0; @@ -431,7 +415,7 @@ const drawArrow = (svg, commit1, commit2, allCommits) => { } ${p2.y}`; } } - const arrow = svg + svg .append('path') .attr('d', lineDef) .attr('class', 'arrow arrow' + (colorClassNum % THEME_COLOR_LIMIT)); @@ -439,10 +423,7 @@ const drawArrow = (svg, commit1, commit2, allCommits) => { const drawArrows = (svg, commits) => { const gArrows = svg.append('g').attr('class', 'commit-arrows'); - let pos = 0; - - const k = Object.keys(commits); - k.forEach((key, index) => { + Object.keys(commits).forEach((key) => { const commit = commits[key]; if (commit.parents && commit.parents.length > 0) { commit.parents.forEach((parent) => { diff --git a/src/diagrams/git/mockDb.js b/src/diagrams/git/mockDb.js index 9ebaf23d3..dbca4dcdb 100644 --- a/src/diagrams/git/mockDb.js +++ b/src/diagrams/git/mockDb.js @@ -173,7 +173,9 @@ export const getCommits = () => { }, }; }; -export const clear = () => {}; +export const clear = () => { + //no-op +}; export const getBranchesAsObjArray = () => [ { name: 'master', diff --git a/src/diagrams/git/parser/gitGraph.jison b/src/diagrams/git/parser/gitGraph.jison index 29edec808..f35dbcde3 100644 --- a/src/diagrams/git/parser/gitGraph.jison +++ b/src/diagrams/git/parser/gitGraph.jison @@ -36,7 +36,7 @@ accDescr\s*"{"\s* { this.begin("ac \#[^\n]* /* skip comments */ \%%[^\n]* /* skip comments */ "gitGraph" return 'GG'; -"commit" return 'COMMIT'; +commit(?=\s|$) return 'COMMIT'; "id:" return 'COMMIT_ID'; "type:" return 'COMMIT_TYPE'; "msg:" return 'COMMIT_MSG'; @@ -44,12 +44,12 @@ accDescr\s*"{"\s* { this.begin("ac "REVERSE" return 'REVERSE'; "HIGHLIGHT" return 'HIGHLIGHT'; "tag:" return 'COMMIT_TAG'; -"branch" return 'BRANCH'; +branch(?=\s|$) return 'BRANCH'; "order:" return 'ORDER'; -"merge" return 'MERGE'; -"cherry-pick" return 'CHERRY_PICK'; +merge(?=\s|$) return 'MERGE'; +cherry-pick(?=\s|$) return 'CHERRY_PICK'; // "reset" return 'RESET'; -"checkout" return 'CHECKOUT'; +checkout(?=\s|$) return 'CHECKOUT'; "LR" return 'DIR'; "BT" return 'DIR'; ":" return ':'; @@ -61,7 +61,7 @@ accDescr\s*"{"\s* { this.begin("ac <string>["] this.popState(); <string>[^"]* return 'STR'; [0-9]+(?=\s|$) return 'NUM'; -\w[-\./\w]*[-\w] return 'ID'; // only a subset of https://git-scm.com/docs/git-check-ref-format +\w([-\./\w]*[-\w])? return 'ID'; // only a subset of https://git-scm.com/docs/git-check-ref-format <<EOF>> return 'EOF'; \s+ /* skip all whitespace */ // lowest priority so we can use lookaheads in earlier regex diff --git a/src/diagrams/info/info.spec.js b/src/diagrams/info/info.spec.js index e9c288166..8bcce51d4 100644 --- a/src/diagrams/info/info.spec.js +++ b/src/diagrams/info/info.spec.js @@ -1,14 +1,14 @@ import { parser } from './parser/info'; import infoDb from './infoDb'; describe('when parsing an info graph it', function () { - var ex; + let ex; beforeEach(function () { ex = parser; ex.yy = infoDb; }); it('should handle an info definition', function () { - var str = `info + let str = `info showInfo`; ex.parse(str); diff --git a/src/diagrams/info/infoDetector.ts b/src/diagrams/info/infoDetector.ts new file mode 100644 index 000000000..68f2ac794 --- /dev/null +++ b/src/diagrams/info/infoDetector.ts @@ -0,0 +1,5 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const infoDetector: DiagramDetector = (txt) => { + return txt.match(/^\s*info/) !== null; +}; diff --git a/src/diagrams/info/infoRenderer.js b/src/diagrams/info/infoRenderer.js index 8976abb75..b50178481 100644 --- a/src/diagrams/info/infoRenderer.js +++ b/src/diagrams/info/infoRenderer.js @@ -27,7 +27,6 @@ export const draw = (text, id, version, diagObj) => { 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); @@ -49,7 +48,6 @@ export const draw = (text, id, version, diagObj) => { svg.attr('width', 400); // svg.attr('viewBox', '0 0 300 150'); } catch (e) { - console.error(e); log.error('Error while rendering info diagram'); log.error(e.message); } diff --git a/src/diagrams/mindmap/mindmap.spec.js b/src/diagrams/mindmap/mindmap.spec.js index d194c094e..e7909ef50 100644 --- a/src/diagrams/mindmap/mindmap.spec.js +++ b/src/diagrams/mindmap/mindmap.spec.js @@ -1,15 +1,15 @@ +import { parser as mindmap } from './parser/mindmap'; import * as mindmapDB from './mindmapDb'; -import { parser } from './parser/mindmap'; +import { setLogLevel } from '../../diagram-api/diagramAPI'; describe('when parsing a mindmap ', function () { - let mindmap; beforeEach(function () { - mindmap = parser; mindmap.yy = mindmapDB; mindmap.yy.clear(); + setLogLevel('trace'); }); describe('hiearchy', function () { - it('should handle a simple root definition', function () { + it('MMP-1 should handle a simple root definition abc122', function () { let str = `mindmap root`; @@ -17,7 +17,7 @@ describe('when parsing a mindmap ', function () { // console.log('Time for checks', mindmap.yy.getMindmap().descr); expect(mindmap.yy.getMindmap().descr).toEqual('root'); }); - it('should handle a hierachial mindmap definition', function () { + it('MMP-2 should handle a hierachial mindmap definition', function () { let str = `mindmap root child1 @@ -32,7 +32,7 @@ describe('when parsing a mindmap ', function () { expect(mm.children[1].descr).toEqual('child2'); }); - it('should handle a simple root definition with a shape and without an id abc123', function () { + it('3 should handle a simple root definition with a shape and without an id abc123', function () { let str = `mindmap (root)`; @@ -41,7 +41,7 @@ describe('when parsing a mindmap ', function () { expect(mindmap.yy.getMindmap().descr).toEqual('root'); }); - it('should handle a deeper hierachial mindmap definition', function () { + it('MMP-4 should handle a deeper hierachial mindmap definition', function () { let str = `mindmap root child1 @@ -56,7 +56,7 @@ describe('when parsing a mindmap ', function () { expect(mm.children[0].children[0].descr).toEqual('leaf1'); expect(mm.children[1].descr).toEqual('child2'); }); - it('Multiple roots are illegal', function () { + it('5 Multiple roots are illegal', function () { let str = `mindmap root fakeRoot`; @@ -71,7 +71,7 @@ describe('when parsing a mindmap ', function () { ); } }); - it('real root in wrong place', function () { + it('MMP-6 real root in wrong place', function () { let str = `mindmap root fakeRoot @@ -89,7 +89,7 @@ describe('when parsing a mindmap ', function () { }); }); describe('nodes', function () { - it('should handle an id and type for a node definition', function () { + it('MMP-7 should handle an id and type for a node definition', function () { let str = `mindmap root[The root] `; @@ -100,7 +100,7 @@ describe('when parsing a mindmap ', function () { expect(mm.descr).toEqual('The root'); expect(mm.type).toEqual(mindmap.yy.nodeType.RECT); }); - it('should handle an id and type for a node definition', function () { + it('MMP-8 should handle an id and type for a node definition', function () { let str = `mindmap root theId(child1)`; @@ -114,7 +114,7 @@ describe('when parsing a mindmap ', function () { expect(child.nodeId).toEqual('theId'); expect(child.type).toEqual(mindmap.yy.nodeType.ROUNDED_RECT); }); - it('should handle an id and type for a node definition', function () { + it('MMP-9 should handle an id and type for a node definition', function () { let str = `mindmap root theId(child1)`; @@ -128,10 +128,10 @@ root expect(child.nodeId).toEqual('theId'); expect(child.type).toEqual(mindmap.yy.nodeType.ROUNDED_RECT); }); - it('mutiple types (circle)', function () { + it('MMP-10 mutiple types (circle)', function () { let str = `mindmap root((the root)) -`; + `; mindmap.parse(str); const mm = mindmap.yy.getMindmap(); @@ -140,7 +140,7 @@ root expect(mm.type).toEqual(mindmap.yy.nodeType.CIRCLE); }); - it('mutiple types (cloud)', function () { + it('MMP-11 mutiple types (cloud)', function () { let str = `mindmap root)the root( `; @@ -151,7 +151,7 @@ root expect(mm.children.length).toEqual(0); expect(mm.type).toEqual(mindmap.yy.nodeType.CLOUD); }); - it('mutiple types (bang)', function () { + it('MMP-12 mutiple types (bang)', function () { let str = `mindmap root))the root(( `; @@ -164,7 +164,7 @@ root }); }); describe('decorations', function () { - it('should be possible to set an icon for the node', function () { + it('MMP-13 should be possible to set an icon for the node', function () { let str = `mindmap root[The root] ::icon(bomb) @@ -178,7 +178,7 @@ root expect(mm.type).toEqual(mindmap.yy.nodeType.RECT); expect(mm.icon).toEqual('bomb'); }); - it('should be possible to set classes for the node', function () { + it('MMP-14 should be possible to set classes for the node', function () { let str = `mindmap root[The root] :::m-4 p-8 @@ -192,7 +192,7 @@ root expect(mm.type).toEqual(mindmap.yy.nodeType.RECT); expect(mm.class).toEqual('m-4 p-8'); }); - it('should be possible to set both classes and icon for the node', function () { + it('MMP-15 should be possible to set both classes and icon for the node', function () { let str = `mindmap root[The root] :::m-4 p-8 @@ -208,7 +208,7 @@ root expect(mm.class).toEqual('m-4 p-8'); expect(mm.icon).toEqual('bomb'); }); - it('should be possible to set both classes and icon for the node', function () { + it('MMP-16 should be possible to set both classes and icon for the node', function () { let str = `mindmap root[The root] ::icon(bomb) @@ -226,7 +226,7 @@ root }); }); describe('descriptions', function () { - it('should be possible to use node syntax in the descriptions', function () { + it('MMP-17 should be possible to use node syntax in the descriptions', function () { let str = `mindmap root["String containing []"] `; @@ -235,7 +235,7 @@ root expect(mm.nodeId).toEqual('root'); expect(mm.descr).toEqual('String containing []'); }); - it('should be possible to use node syntax in the descriptions in children', function () { + it('MMP-18 should be possible to use node syntax in the descriptions in children', function () { let str = `mindmap root["String containing []"] child1["String containing ()"] @@ -247,7 +247,7 @@ root expect(mm.children.length).toEqual(1); expect(mm.children[0].descr).toEqual('String containing ()'); }); - it('should be possible to have a child after a class assignment', function () { + it('MMP-19 should be possible to have a child after a class assignment', function () { let str = `mindmap root(Root) Child(Child) @@ -267,7 +267,7 @@ root expect(child.children[1].nodeId).toEqual('b'); }); }); - it('should be possible to have meaningless empty rows in a mindmap abc124', function () { + it('MMP-20 should be possible to have meaningless empty rows in a mindmap abc124', function () { let str = `mindmap root(Root) Child(Child) @@ -286,7 +286,7 @@ root expect(child.children.length).toEqual(2); expect(child.children[1].nodeId).toEqual('b'); }); - it('should be possible to have comments in a mindmap', function () { + it('MMP-21 should be possible to have comments in a mindmap', function () { let str = `mindmap root(Root) Child(Child) @@ -307,7 +307,7 @@ root expect(child.children[1].nodeId).toEqual('b'); }); - it('should be possible to have comments at the end of a line', function () { + it('MMP-22 should be possible to have comments at the end of a line', function () { let str = `mindmap root(Root) Child(Child) diff --git a/src/diagrams/mindmap/mindmapDb.js b/src/diagrams/mindmap/mindmapDb.js index 370b3f7d9..68906c5fb 100644 --- a/src/diagrams/mindmap/mindmapDb.js +++ b/src/diagrams/mindmap/mindmapDb.js @@ -1,6 +1,5 @@ /** Created by knut on 15-01-14. */ -import { sanitizeText, getConfig } from '../../diagram-api/diagramAPI'; -import { log } from '../../logger'; +import { sanitizeText, getConfig, log as _log } from '../../diagram-api/diagramAPI'; let nodes = []; let cnt = 0; @@ -25,7 +24,7 @@ export const getMindmap = () => { return nodes.length > 0 ? nodes[0] : null; }; export const addNode = (level, id, descr, type) => { - console.info('addNode', level, id, descr, type); + log.info('addNode', level, id, descr, type); const conf = getConfig(); const node = { id: cnt++, @@ -132,7 +131,8 @@ export const type2Str = (type) => { return 'no-border'; } }; - +// Expose logger to grammar +export const log = _log; export const getNodeById = (id) => nodes[id]; export const getElementById = (id) => elements[id]; // export default { diff --git a/src/diagrams/mindmap/mindmapRenderer.js b/src/diagrams/mindmap/mindmapRenderer.js index caa8baedb..2f2b06292 100644 --- a/src/diagrams/mindmap/mindmapRenderer.js +++ b/src/diagrams/mindmap/mindmapRenderer.js @@ -2,7 +2,7 @@ import { select } from 'd3'; import { log, getConfig, setupGraphViewbox } from '../../diagram-api/diagramAPI'; import svgDraw from './svgDraw'; -import { BoundingBox, Layout, Tree } from 'non-layered-tidy-tree-layout'; +import { BoundingBox, Layout } from 'non-layered-tidy-tree-layout'; import clone from 'fast-clone'; import * as db from './mindmapDb'; @@ -85,9 +85,8 @@ function rightToLeft(mindmap) { /** * @param mindmap * @param dir - * @param conf */ -function layout(mindmap, dir, conf) { +function layout(mindmap, dir) { const bb = new BoundingBox(30, 60); const layout = new Layout(bb); @@ -192,8 +191,7 @@ function layoutMindmap(node, conf) { }); // Merge the trees into a single tree - const result = mergeTrees(node, trees); - eachNode; + mergeTrees(node, trees); return node; } /** @@ -232,13 +230,11 @@ export const draw = (text, id, version, diagObj) => { securityLevel === 'sandbox' ? select(sandboxElement.nodes()[0].contentDocument.body) : select('body'); - const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; - // Parse the graph definition const svg = root.select('#' + id); - const g = svg.append('g'); + svg.append('g'); const mm = diagObj.db.getMindmap(); // Draw the graph and start with drawing the nodes without proper position diff --git a/src/diagrams/mindmap/parser/mindmap.jison b/src/diagrams/mindmap/parser/mindmap.jison index d84c09495..f8c72787c 100644 --- a/src/diagrams/mindmap/parser/mindmap.jison +++ b/src/diagrams/mindmap/parser/mindmap.jison @@ -17,20 +17,21 @@ %% -\s*\%\%.*\n {console.log('Found comment',yytext);} +\s*\%\%.* {yy.log.trace('Found comment',yytext);} // \%\%[^\n]*\n /* skip comments */ "mindmap" return 'MINDMAP'; ":::" { this.begin('CLASS'); } <CLASS>.+ { this.popState();return 'CLASS'; } <CLASS>\n { this.popState();} -[\n\s]*"::icon(" { this.begin('ICON'); } -[\n]+ /* return 'NL'; */ +// [\s]*"::icon(" { this.begin('ICON'); } +"::icon(" { yy.log.trace('Begin icon');this.begin('ICON'); } +[\n]+ return 'NL'; <ICON>[^\)]+ { return 'ICON'; } -<ICON>\) {this.popState();} -"-)" { console.log('Exploding node'); this.begin('NODE');return 'NODE_DSTART'; } -"(-" { console.log('Cloud'); this.begin('NODE');return 'NODE_DSTART'; } -"))" { console.log('Explosion Bang'); this.begin('NODE');return 'NODE_DSTART'; } -")" { console.log('Cloud Bang'); this.begin('NODE');return 'NODE_DSTART'; } +<ICON>\) {yy.log.trace('end icon');this.popState();} +"-)" { yy.log.trace('Exploding node'); this.begin('NODE');return 'NODE_DSTART'; } +"(-" { yy.log.trace('Cloud'); this.begin('NODE');return 'NODE_DSTART'; } +"))" { yy.log.trace('Explosion Bang'); this.begin('NODE');return 'NODE_DSTART'; } +")" { yy.log.trace('Cloud Bang'); this.begin('NODE');return 'NODE_DSTART'; } "((" { this.begin('NODE');return 'NODE_DSTART'; } "(" { this.begin('NODE');return 'NODE_DSTART'; } "[" { this.begin('NODE');return 'NODE_DSTART'; } @@ -38,18 +39,18 @@ // !(-\() return 'NODE_ID'; [^\(\[\n\-\)]+ return 'NODE_ID'; <<EOF>> return 'EOF'; -<NODE>["] { console.log('Starting NSTR');this.begin("NSTR");} -<NSTR>[^"]+ { console.log('description:', yytext); return "NODE_DESCR";} +<NODE>["] { yy.log.trace('Starting NSTR');this.begin("NSTR");} +<NSTR>[^"]+ { yy.log.trace('description:', yytext); return "NODE_DESCR";} <NSTR>["] {this.popState();} -<NODE>[\)]\) {this.popState();console.log('node end ))');return "NODE_DEND";} -<NODE>[\)] {this.popState();console.log('node end )');return "NODE_DEND";} -<NODE>[\]] {this.popState();console.log('node end ...');return "NODE_DEND";} -<NODE>"(-" {this.popState();console.log('node end (-');return "NODE_DEND";} -<NODE>"-)" {this.popState();console.log('node end (-');return "NODE_DEND";} -<NODE>"((" {this.popState();console.log('node end ((');return "NODE_DEND";} -<NODE>"(" {this.popState();console.log('node end ((');return "NODE_DEND";} -<NODE>[^\)\]\(]+ { console.log('Long description:', yytext); return 'NODE_DESCR';} -<NODE>.+(?!\(\() { console.log('Long description:', yytext); return 'NODE_DESCR';} +<NODE>[\)]\) {this.popState();yy.log.trace('node end ))');return "NODE_DEND";} +<NODE>[\)] {this.popState();yy.log.trace('node end )');return "NODE_DEND";} +<NODE>[\]] {this.popState();yy.log.trace('node end ...',yytext);return "NODE_DEND";} +<NODE>"(-" {this.popState();yy.log.trace('node end (-');return "NODE_DEND";} +<NODE>"-)" {this.popState();yy.log.trace('node end (-');return "NODE_DEND";} +<NODE>"((" {this.popState();yy.log.trace('node end ((');return "NODE_DEND";} +<NODE>"(" {this.popState();yy.log.trace('node end ((');return "NODE_DEND";} +<NODE>[^\)\]\(]+ { yy.log.trace('Long description:', yytext); return 'NODE_DESCR';} +<NODE>.+(?!\(\() { yy.log.trace('Long description:', yytext); return 'NODE_DESCR';} // [\[] return 'NODE_START'; // .+ return 'TXT' ; @@ -62,29 +63,33 @@ start // %{ : info document 'EOF' { return yy; } } : MINDMAP document { return yy; } + | MINDMAP NL document { return yy; } | SPACELIST MINDMAP document { return yy; } ; +stop + : NL {yy.log.trace('Stop NL ');} + | EOF {yy.log.trace('Stop EOF ');} + | stop NL {yy.log.trace('Stop NL2 ');} + | stop EOF {yy.log.trace('Stop EOF2 ');} + ; document - : document line - | line - ; - -line - : statement { } + : document statement stop + | statement stop ; statement - : SPACELIST node { yy.addNode($1.length, $2.id, $2.descr, $2.type); } - | SPACELIST ICON { yy.decorateNode({icon: $2}); } - | SPACELIST EOF - | SPACELIST NL - | node { console.log($1.id);yy.addNode(0, $1.id, $1.descr, $1.type); } + : SPACELIST node { yy.log.trace('Node: ',$2.id);yy.addNode($1.length, $2.id, $2.descr, $2.type); } + | SPACELIST ICON { yy.log.trace('Icon: ',$2);yy.decorateNode({icon: $2}); } + | SPACELIST CLASS { yy.decorateNode({class: $2}); } + | node { yy.log.trace('Node: ',$1.id);yy.addNode(0, $1.id, $1.descr, $1.type); } | ICON { yy.decorateNode({icon: $1}); } - | SPACELIST CLASS { yy.decorateNode({class: $2}); } - | CLASS { yy.decorateNode({class: $1}); } - | EOF + | CLASS { yy.decorateNode({class: $1}); } + | SPACELIST ; + + + node :nodeWithId |nodeWithoutId @@ -92,12 +97,12 @@ node nodeWithoutId : NODE_DSTART NODE_DESCR NODE_DEND - { console.log("node found ..", $1); $$ = { id: $2, descr: $2, type: yy.getType($1, $3) }; } + { yy.log.trace("node found ..", $1); $$ = { id: $2, descr: $2, type: yy.getType($1, $3) }; } ; nodeWithId : NODE_ID { $$ = { id: $1, descr: $1, type: yy.nodeType.DEFAULT }; } | NODE_ID NODE_DSTART NODE_DESCR NODE_DEND - { console.log("node found ..", $1); $$ = { id: $1, descr: $3, type: yy.getType($2, $4) }; } + { yy.log.trace("node found ..", $1); $$ = { id: $1, descr: $3, type: yy.getType($2, $4) }; } ; %% diff --git a/src/diagrams/mindmap/styles.js b/src/diagrams/mindmap/styles.js index 76d6a9c1b..f6afaa612 100644 --- a/src/diagrams/mindmap/styles.js +++ b/src/diagrams/mindmap/styles.js @@ -1,4 +1,4 @@ -import { darken, lighten, adjust, invert, isDark } from 'khroma'; +import { darken, lighten, isDark } from 'khroma'; const genSections = (options) => { let sections = ''; diff --git a/src/diagrams/mindmap/svgDraw.js b/src/diagrams/mindmap/svgDraw.js index 511c46e20..7d6804f24 100644 --- a/src/diagrams/mindmap/svgDraw.js +++ b/src/diagrams/mindmap/svgDraw.js @@ -1,4 +1,3 @@ -const lineBreakRegex = /<br\s*\/?>/gi; import { select } from 'd3'; import * as db from './mindmapDb'; @@ -15,7 +14,6 @@ function wrap(text, width) { .reverse(), word, line = [], - lineNumber = 0, lineHeight = 1.1, // ems y = text.attr('y'), dy = parseFloat(text.attr('dy')), @@ -49,9 +47,9 @@ function wrap(text, width) { }); } -const defaultBkg = function (elem, node, section, conf) { +const defaultBkg = function (elem, node, section) { const rd = 5; - const r = elem + elem .append('path') .attr('id', 'node-' + node.id) .attr('class', 'node-bkg node-' + db.type2Str(node.type)) @@ -70,25 +68,22 @@ const defaultBkg = function (elem, node, section, conf) { .attr('x2', node.width) .attr('y2', node.height); }; -const rectBkg = function (elem, node, section, conf) { - const r = elem +const rectBkg = function (elem, node) { + elem .append('rect') .attr('id', 'node-' + node.id) .attr('class', 'node-bkg node-' + db.type2Str(node.type)) .attr('height', node.height) .attr('width', node.width); }; -const cloudBkg = function (elem, node, section, conf) { - const rd = 5; - const r = elem; +const cloudBkg = function (elem, node) { const w = node.width; const h = node.height; - const r0 = 0.1 * w; const r1 = 0.15 * w; const r2 = 0.25 * w; const r3 = 0.35 * w; const r4 = 0.2 * w; - const p = elem + elem .append('path') .attr('id', 'node-' + node.id) .attr('class', 'node-bkg node-' + db.type2Str(node.type)) @@ -111,12 +106,11 @@ const cloudBkg = function (elem, node, section, conf) { H0 V0 Z` ); }; -const bangBkg = function (elem, node, section, conf) { - const rd = 5; +const bangBkg = function (elem, node) { const w = node.width; const h = node.height; const r = 0.15 * w; - const p = elem + elem .append('path') .attr('id', 'node-' + node.id) .attr('class', 'node-bkg node-' + db.type2Str(node.type)) @@ -143,16 +137,15 @@ const bangBkg = function (elem, node, section, conf) { H0 V0 Z` ); }; -const circleBkg = function (elem, node, section, conf) { - const r = elem +const circleBkg = function (elem, node) { + elem .append('circle') .attr('id', 'node-' + node.id) .attr('class', 'node-bkg node-' + db.type2Str(node.type)) .attr('r', node.width / 2); - // .attr('width', node.width); }; -const roundedRectBkg = function (elem, node, section, conf) { - const r = elem +const roundedRectBkg = function (elem, node) { + elem .append('rect') .attr('id', 'node-' + node.id) .attr('class', 'node-bkg node-' + db.type2Str(node.type)) @@ -185,7 +178,6 @@ export const drawNode = function (elem, node, section, conf) { .append('text') .text(node.descr) .attr('dy', '1em') - // .attr('dy', '0') .attr('alignment-baseline', 'middle') .attr('dominant-baseline', 'middle') .attr('text-anchor', 'middle') @@ -197,18 +189,12 @@ export const drawNode = function (elem, node, section, conf) { if (node.icon) { if (node.type === db.nodeType.CIRCLE) { node.height += 50; - const orgWidth = node.width; node.width += 50; - // node.width = Math.max(orgWidth, 100); - const widthDiff = Math.abs(node.width - orgWidth); const icon = nodeElem .append('foreignObject') .attr('height', '50px') .attr('width', node.width) .attr('style', 'text-align: center;'); - // .attr('x', 0) - // .attr('y', 0) - // .attr('class', 'node-icon ' + node.icon); icon .append('div') .attr('class', 'icon-container') @@ -228,9 +214,7 @@ export const drawNode = function (elem, node, section, conf) { .attr('width', '60px') .attr('height', node.height) .attr('style', 'text-align: center;margin-top:' + heightDiff / 2 + 'px;'); - // .attr('x', 0) - // .attr('y', 0) - // .attr('class', 'node-icon ' + node.icon); + icon .append('div') .attr('class', 'icon-container') @@ -260,15 +244,11 @@ export const drawNode = function (elem, node, section, conf) { circleBkg(bkgElem, node, section, conf); break; case db.nodeType.CLOUD: - // bkgElem.attr('transform', 'translate(' + node.width / 2 + ', ' + +node.height / 2 + ')'); cloudBkg(bkgElem, node, section, conf); break; case db.nodeType.BANG: - // bkgElem.attr('transform', 'translate(' + node.width / 2 + ', ' + +node.height / 2 + ')'); bangBkg(bkgElem, node, section, conf); break; - default: - // defaultBkg(bkgElem, node, section, conf); } // Position the node to its coordinate @@ -279,17 +259,7 @@ export const drawNode = function (elem, node, section, conf) { return node.height; }; -export const drawEdge = function drawEdge(edgesElem, mindmap, parent, depth, section, conf) { - // edgesElem - // .append('line') - // .attr('x1', parent.x + parent.width / 2) - // .attr('y1', parent.y + parent.height / 2) - // .attr('x2', mindmap.x + mindmap.width / 2) - // .attr('y2', mindmap.y + mindmap.height / 2) - // .attr('class', 'edge section-edge-' + section + ' edge-depth-' + depth); - - //<path d="M100,250 Q250,100 400,250 T700,250" /> - +export const drawEdge = function drawEdge(edgesElem, mindmap, parent, depth, section) { const sx = parent.x + parent.width / 2; const sy = parent.y + parent.height / 2; const ex = mindmap.x + mindmap.width / 2; @@ -310,7 +280,7 @@ export const drawEdge = function drawEdge(edgesElem, mindmap, parent, depth, sec .attr('class', 'edge section-edge-' + section + ' edge-depth-' + depth); }; -export const positionNode = function (node, conf) { +export const positionNode = function (node) { const nodeElem = db.getElementById(node.id); const x = node.x || 0; diff --git a/src/diagrams/pie/pieDb.js b/src/diagrams/pie/pieDb.js index def0242a3..8ef4d9efc 100644 --- a/src/diagrams/pie/pieDb.js +++ b/src/diagrams/pie/pieDb.js @@ -13,8 +13,6 @@ import { } from '../../commonDb'; let sections = {}; -let title = ''; -let description = ''; let showData = false; export const parseDirective = function (statement, context, type) { @@ -49,7 +47,6 @@ const cleanupValue = function (value) { const clear = function () { sections = {}; - title = ''; showData = false; commonClear(); }; diff --git a/src/diagrams/pie/pieDetector.ts b/src/diagrams/pie/pieDetector.ts new file mode 100644 index 000000000..1e122b0e0 --- /dev/null +++ b/src/diagrams/pie/pieDetector.ts @@ -0,0 +1,5 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const pieDetector: DiagramDetector = (txt) => { + return txt.match(/^\s*pie/) !== null; +}; diff --git a/src/diagrams/requirement/requirementDb.js b/src/diagrams/requirement/requirementDb.js index f78bd5509..9d48f0b2d 100644 --- a/src/diagrams/requirement/requirementDb.js +++ b/src/diagrams/requirement/requirementDb.js @@ -1,7 +1,7 @@ import * as configApi from '../../config'; import { log } from '../../logger'; import mermaidAPI from '../../mermaidAPI'; -import common from '../common/common'; + import { setAccTitle, getAccTitle, @@ -15,10 +15,6 @@ let latestRequirement = {}; let requirements = {}; let latestElement = {}; let elements = {}; -let title = ''; -let accDescription = ''; - -const sanitizeText = (txt) => common.sanitizeText(txt, configApi.getConfig()); const RequirementType = { REQUIREMENT: 'Requirement', diff --git a/src/diagrams/requirement/requirementDetector.ts b/src/diagrams/requirement/requirementDetector.ts new file mode 100644 index 000000000..2e1aa93ae --- /dev/null +++ b/src/diagrams/requirement/requirementDetector.ts @@ -0,0 +1,5 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const requirementDetector: DiagramDetector = (txt) => { + return txt.match(/^\s*requirement(Diagram)?/) !== null; +}; diff --git a/src/diagrams/requirement/requirementRenderer.js b/src/diagrams/requirement/requirementRenderer.js index 7a43edaee..d10c43066 100644 --- a/src/diagrams/requirement/requirementRenderer.js +++ b/src/diagrams/requirement/requirementRenderer.js @@ -320,7 +320,6 @@ export const draw = (text, id, _version, diagObj) => { securityLevel === 'sandbox' ? select(sandboxElement.nodes()[0].contentDocument.body) : select('body'); - const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; const svg = root.select(`[id='${id}']`); markers.insertLineEndings(svg, conf); diff --git a/src/diagrams/sequence/sequenceDb.js b/src/diagrams/sequence/sequenceDb.js index 7d0309127..6c863e204 100644 --- a/src/diagrams/sequence/sequenceDb.js +++ b/src/diagrams/sequence/sequenceDb.js @@ -16,8 +16,6 @@ let prevActor = undefined; let actors = {}; let messages = []; const notes = []; -let diagramTitle = ''; -let description = ''; let sequenceNumbersEnabled = false; let wrapEnabled; @@ -153,7 +151,6 @@ export const clear = function () { actors = {}; messages = []; sequenceNumbersEnabled = false; - diagramTitle = ''; commonClear(); }; diff --git a/src/diagrams/sequence/sequenceDetector.ts b/src/diagrams/sequence/sequenceDetector.ts new file mode 100644 index 000000000..e68433255 --- /dev/null +++ b/src/diagrams/sequence/sequenceDetector.ts @@ -0,0 +1,5 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const sequenceDetector: DiagramDetector = (txt) => { + return txt.match(/^\s*sequenceDiagram/) !== null; +}; diff --git a/src/diagrams/sequence/sequenceDiagram.spec.js b/src/diagrams/sequence/sequenceDiagram.spec.js index 7b10ded12..5b3d9b05d 100644 --- a/src/diagrams/sequence/sequenceDiagram.spec.js +++ b/src/diagrams/sequence/sequenceDiagram.spec.js @@ -1,12 +1,8 @@ -// import sequence from './parser/sequenceDiagram'; -// import sequenceDb from './sequenceDb'; import * as configApi from '../../config'; -// import renderer from './sequenceRenderer'; import mermaidAPI from '../../mermaidAPI'; -// import '../../diagram-api/diagramAPI'; import Diagram from '../../Diagram'; - -// console.log('sequenceDiagram', sequenceDb); +import { addDiagrams } from '../../diagram-api/diagram-orchestration'; +addDiagrams(); /** * @param conf * @param key diff --git a/src/diagrams/sequence/sequenceRenderer.ts b/src/diagrams/sequence/sequenceRenderer.ts index 9fae76743..19352ca72 100644 --- a/src/diagrams/sequence/sequenceRenderer.ts +++ b/src/diagrams/sequence/sequenceRenderer.ts @@ -1,4 +1,4 @@ -// @ts-nocheck +// @ts-nocheck TODO: fix file import { select, selectAll } from 'd3'; import svgDraw, { drawText, fixLifeLineHeights } from './svgDraw'; import { log } from '../../logger'; @@ -97,6 +97,7 @@ export const bounds = { } }, updateBounds: function (startx, starty, stopx, stopy) { + // eslint-disable-next-line @typescript-eslint/no-this-alias const _self = this; let cnt = 0; /** @param {any} type */ @@ -217,7 +218,7 @@ const drawNote = function (elem, noteModel) { rect.width = noteModel.width || conf.width; rect.class = 'note'; - let g = elem.append('g'); + const g = elem.append('g'); const rectElem = svgDraw.drawRect(g, rect); const textObj = svgDraw.getTextObj(); textObj.x = noteModel.startx; @@ -233,9 +234,9 @@ const drawNote = function (elem, noteModel) { textObj.textMargin = conf.noteMargin; textObj.valign = 'center'; - let textElem = drawText(g, textObj); + const textElem = drawText(g, textObj); - let textHeight = Math.round( + const textHeight = Math.round( textElem .map((te) => (te._groups || te)[0][0].getBBox().height) .reduce((acc, curr) => acc + curr) @@ -285,7 +286,7 @@ const boundMessage = function (diagram, msgModel) { bounds.bumpVerticalPos(10); const { startx, stopx, message } = msgModel; const lines = common.splitBreaks(message).length; - let textDims = utils.calculateTextDimensions(message, messageFont(conf)); + const textDims = utils.calculateTextDimensions(message, messageFont(conf)); const lineHeight = textDims.height / lines; msgModel.height += lineHeight; @@ -293,7 +294,7 @@ const boundMessage = function (diagram, msgModel) { let lineStarty; let totalOffset = textDims.height - 10; - let textWidth = textDims.width; + const textWidth = textDims.width; if (startx === stopx) { lineStarty = bounds.getVerticalPos() + totalOffset; @@ -332,7 +333,7 @@ const boundMessage = function (diagram, msgModel) { */ const drawMessage = function (diagram, msgModel, lineStarty, diagObj) { const { startx, stopx, starty, message, type, sequenceIndex, sequenceVisible } = msgModel; - let textDims = utils.calculateTextDimensions(message, messageFont(conf)); + const textDims = utils.calculateTextDimensions(message, messageFont(conf)); const textObj = svgDraw.getTextObj(); textObj.x = startx; textObj.y = starty + 10; @@ -350,7 +351,7 @@ const drawMessage = function (diagram, msgModel, lineStarty, diagObj) { drawText(diagram, textObj); - let textWidth = textDims.width; + const textWidth = textDims.width; let line; if (startx === stopx) { @@ -495,12 +496,12 @@ export const drawActors = function ( }; export const drawActorsPopup = function (diagram, actors, actorKeys, doc) { - var maxHeight = 0; - var maxWidth = 0; + let maxHeight = 0; + let maxWidth = 0; for (let i = 0; i < actorKeys.length; i++) { const actor = actors[actorKeys[i]]; const minMenuWidth = getRequiredPopupWidth(actor); - var menuDimensions = svgDraw.drawPopup( + const menuDimensions = svgDraw.drawPopup( diagram, actor, minMenuWidth, @@ -564,8 +565,8 @@ function adjustLoopHeightForWrap(loopWidths, msg, preMargin, postMargin, addLoop bounds.bumpVerticalPos(preMargin); let heightAdjust = postMargin; if (msg.id && msg.message && loopWidths[msg.id]) { - let loopWidth = loopWidths[msg.id].width; - let textConf = messageFont(conf); + const loopWidth = loopWidths[msg.id].width; + const textConf = messageFont(conf); msg.message = utils.wrapLabel(`[${msg.message}]`, loopWidth - 2 * conf.wrapPadding, textConf); msg.width = loopWidth; msg.wrap = true; @@ -654,7 +655,7 @@ export const draw = function (_text, id, _version, diagObj) { // Draw the messages/signals let sequenceIndex = 1; let sequenceIndexStep = 1; - let messagesToDraw = Array(); + const messagesToDraw = []; messages.forEach(function (msg) { let loopModel, noteModel, msgModel; @@ -810,7 +811,7 @@ export const draw = function (_text, id, _version, diagObj) { msgModel.starty = bounds.getVerticalPos(); msgModel.sequenceIndex = sequenceIndex; msgModel.sequenceVisible = diagObj.db.showSequenceNumbers(); - let lineStarty = boundMessage(diagram, msgModel); + const lineStarty = boundMessage(diagram, msgModel); messagesToDraw.push({ messageModel: msgModel, lineStarty: lineStarty }); bounds.models.addMessage(msgModel); } catch (e) { @@ -846,7 +847,7 @@ export const draw = function (_text, id, _version, diagObj) { } // only draw popups for the top row of actors. - var requiredBoxSize = drawActorsPopup(diagram, actors, actorKeys, doc); + const requiredBoxSize = drawActorsPopup(diagram, actors, actorKeys, doc); const { bounds: box } = bounds.getBounds(); @@ -932,7 +933,7 @@ const getMaxMessageWidthPerActor = function (actors, messages, diagObj) { const isMessage = !isNote; const textFont = isNote ? noteFont(conf) : messageFont(conf); - let wrappedMessage = msg.wrap + const wrappedMessage = msg.wrap ? utils.wrapLabel(msg.message, conf.width - 2 * conf.wrapPadding, textFont) : msg.message; const messageDimensions = utils.calculateTextDimensions(wrappedMessage, textFont); @@ -1009,9 +1010,9 @@ const getMaxMessageWidthPerActor = function (actors, messages, diagObj) { const getRequiredPopupWidth = function (actor) { let requiredPopupWidth = 0; const textFont = actorFont(conf); - for (let key in actor.links) { - let labelDimensions = utils.calculateTextDimensions(key, textFont); - let labelWidth = labelDimensions.width + 2 * conf.wrapPadding + 2 * conf.boxMargin; + for (const key in actor.links) { + const labelDimensions = utils.calculateTextDimensions(key, textFont); + const labelWidth = labelDimensions.width + 2 * conf.wrapPadding + 2 * conf.boxMargin; if (requiredPopupWidth < labelWidth) { requiredPopupWidth = labelWidth; } @@ -1049,7 +1050,7 @@ const calculateActorMargins = function (actors, actorToMessageWidth) { maxHeight = Math.max(maxHeight, actor.height); }); - for (let actorKey in actorToMessageWidth) { + for (const actorKey in actorToMessageWidth) { const actor = actors[actorKey]; if (!actor) { @@ -1073,15 +1074,15 @@ const calculateActorMargins = function (actors, actorToMessageWidth) { }; const buildNoteModel = function (msg, actors, diagObj) { - let startx = actors[msg.from].x; - let stopx = actors[msg.to].x; - let shouldWrap = msg.wrap && msg.message; + const startx = actors[msg.from].x; + const stopx = actors[msg.to].x; + const shouldWrap = msg.wrap && msg.message; let textDimensions = utils.calculateTextDimensions( shouldWrap ? utils.wrapLabel(msg.message, conf.width, noteFont(conf)) : msg.message, noteFont(conf) ); - let noteModel = { + const noteModel = { width: shouldWrap ? conf.width : Math.max(conf.width, textDimensions.width + 2 * conf.noteMargin), @@ -1277,8 +1278,8 @@ const calculateLoopBounds = function (messages, actors, _maxWidthPerActor, diagO stack.forEach((stk) => { current = stk; if (msgModel.startx === msgModel.stopx) { - let from = actors[msg.from]; - let to = actors[msg.to]; + const from = actors[msg.from]; + const to = actors[msg.to]; current.from = Math.min( from.x - msgModel.width / 2, from.x - from.width / 2, diff --git a/src/diagrams/state/stateDb.js b/src/diagrams/state/stateDb.js index 7092cf1d6..96f92af8a 100644 --- a/src/diagrams/state/stateDb.js +++ b/src/diagrams/state/stateDb.js @@ -11,8 +11,6 @@ import { clear as commonClear, } from '../../commonDb'; -const sanitizeText = (txt) => common.sanitizeText(txt, configApi.getConfig()); - const clone = (o) => JSON.parse(JSON.stringify(o)); let rootDoc = []; @@ -121,10 +119,6 @@ let documents = { let currentDocument = documents.root; let startCnt = 0; -let endCnt = 0; // let stateCnt = 0; - -let title = 'State diagram'; -let description = ''; /** * Function called by parser when a node definition has been found. @@ -179,7 +173,6 @@ export const clear = function (saveCommon) { currentDocument = documents.root; startCnt = 0; - endCnt = 0; classes = []; if (!saveCommon) { commonClear(); @@ -211,7 +204,6 @@ export const addRelation = function (_id1, _id2, title) { type1 = 'start'; } if (_id2 === '[*]') { - endCnt++; id2 = 'end' + startCnt; type2 = 'end'; } diff --git a/src/diagrams/state/stateDetector-V2.ts b/src/diagrams/state/stateDetector-V2.ts new file mode 100644 index 000000000..8082a47bd --- /dev/null +++ b/src/diagrams/state/stateDetector-V2.ts @@ -0,0 +1,8 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const stateDetectorV2: DiagramDetector = (text, config) => { + if (text.match(/^\s*stateDiagram-v2/) !== null) return true; + if (text.match(/^\s*stateDiagram/) && config?.state?.defaultRenderer === 'dagre-wrapper') + return true; + return false; +}; diff --git a/src/diagrams/state/stateDetector.ts b/src/diagrams/state/stateDetector.ts new file mode 100644 index 000000000..79dd6586b --- /dev/null +++ b/src/diagrams/state/stateDetector.ts @@ -0,0 +1,8 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const stateDetector: DiagramDetector = (txt, config) => { + // If we have confired to only use new state diagrams this function should always return false + // as in not signalling true for a legacy state diagram + if (config?.state?.defaultRenderer === 'dagre-wrapper') return false; + return txt.match(/^\s*stateDiagram/) !== null; +}; diff --git a/src/diagrams/state/stateRenderer-v2.js b/src/diagrams/state/stateRenderer-v2.js index 4452f9491..13c474b5e 100644 --- a/src/diagrams/state/stateRenderer-v2.js +++ b/src/diagrams/state/stateRenderer-v2.js @@ -283,7 +283,6 @@ export const draw = function (text, id, _version, diag) { securityLevel === 'sandbox' ? select(sandboxElement.nodes()[0].contentDocument.body) : select('body'); - const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; const svg = root.select(`[id="${id}"]`); // Run the renderer. This is what draws the final graph. diff --git a/src/diagrams/state/stateRenderer.js b/src/diagrams/state/stateRenderer.js index 363ca23f7..75368c557 100644 --- a/src/diagrams/state/stateRenderer.js +++ b/src/diagrams/state/stateRenderer.js @@ -13,7 +13,9 @@ let conf; const transformationLog = {}; -export const setConf = function () {}; +export const setConf = function () { + //no-op +}; /** * Setup arrow head and define the marker. The result is appended to the svg. diff --git a/src/diagrams/user-journey/journeyDb.js b/src/diagrams/user-journey/journeyDb.js index d8f27b93c..0707636f5 100644 --- a/src/diagrams/user-journey/journeyDb.js +++ b/src/diagrams/user-journey/journeyDb.js @@ -1,6 +1,5 @@ import mermaidAPI from '../../mermaidAPI'; import * as configApi from '../../config'; -import common from '../common/common'; import { setAccTitle, getAccTitle, @@ -11,10 +10,6 @@ import { clear as commonClear, } from '../../commonDb'; -const sanitizeText = (txt) => common.sanitizeText(txt, configApi.getConfig()); - -let title = ''; -let description = ''; let currentSection = ''; const sections = []; @@ -29,8 +24,6 @@ export const clear = function () { sections.length = 0; tasks.length = 0; currentSection = ''; - title = ''; - description = ''; rawTasks.length = 0; commonClear(); }; diff --git a/src/diagrams/user-journey/journeyDetector.ts b/src/diagrams/user-journey/journeyDetector.ts new file mode 100644 index 000000000..77c8688ae --- /dev/null +++ b/src/diagrams/user-journey/journeyDetector.ts @@ -0,0 +1,5 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const journeyDetector: DiagramDetector = (txt) => { + return txt.match(/^\s*journey/) !== null; +}; diff --git a/src/diagrams/user-journey/journeyRenderer.ts b/src/diagrams/user-journey/journeyRenderer.ts index e638eeb00..e3ebb839c 100644 --- a/src/diagrams/user-journey/journeyRenderer.ts +++ b/src/diagrams/user-journey/journeyRenderer.ts @@ -1,4 +1,4 @@ -// @ts-nocheck +// @ts-nocheck TODO: fix file import { select } from 'd3'; import svgDraw from './svgDraw'; import { getConfig } from '../../config'; @@ -74,7 +74,7 @@ export const draw = function (text, id, version, diagObj) { const title = diagObj.db.getDiagramTitle(); const actorNames = diagObj.db.getActors(); - for (let member in actors) delete actors[member]; + for (const member in actors) delete actors[member]; let actorPos = 0; actorNames.forEach((actorName) => { actors[actorName] = { @@ -152,6 +152,7 @@ export const bounds = { }, updateBounds: function (startx, starty, stopx, stopy) { const conf = getConfig().journey; + // eslint-disable-next-line @typescript-eslint/no-this-alias const _self = this; let cnt = 0; /** @param {any} type */ @@ -219,7 +220,7 @@ export const drawTasks = function (diagram, tasks, verticalPos) { // Draw the tasks for (let i = 0; i < tasks.length; i++) { - let task = tasks[i]; + const task = tasks[i]; if (lastSection !== task.section) { fill = fills[sectionNumber % fills.length]; num = sectionNumber % fills.length; diff --git a/src/docs.mts b/src/docs.mts index 76594c4bf..06a1f4bff 100644 --- a/src/docs.mts +++ b/src/docs.mts @@ -1,40 +1,152 @@ -import { remark } from 'remark'; -import type { Code, Root } from 'mdast'; +/* eslint-disable no-console */ + +/** + * @file Transform documentation source files into files suitable for publishing + * and optionally copy the transformed files from the source directory to the + * directory used for the final, published documentation directory. The list + * of files transformed and copied to final documentation directory are logged + * to the console. If a file in the source directory has the same contents in + * the final directory, nothing is done (the final directory is up-to-date). + * @example + * docs + * Run with no option flags + * + * @example + * docs --verify + * If the --verify option is used, it only _verifies_ that the final directory has been updated with the transformed files in the source directory. + * No files will be copied to the final documentation directory, but the list of files to be changed is shown on the console. + * If the final documentation directory does not have the transformed files from source directory + * - a message to the console will show that this command should be run without the --verify flag so that the final directory is updated, and + * - it will return a fail exit code (1) + * + * @example + * docs --git + * If the --git option is used, the command `git add docs` will be run after all transformations (and/or verifications) have completed successfully + * If not files were transformed, the git command is not run. + * + * @todo Ensure that the documentation source and final paths are correct by + * using process.cwd() to get their absolute paths. Ensures that the location + * of those 2 directories is not dependent on where this file resides. + * + * @todo Write a test file for this. (Will need to be able to deal .mts file. + * Jest has trouble with it.) + */ import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs'; -// @ts-ignore -import flatmap from 'unist-util-flatmap'; -import { globby } from 'globby'; -import { join, dirname } from 'path'; import { exec } from 'child_process'; +import { globby } from 'globby'; +import { JSDOM } from 'jsdom'; +import type { Code, Root } from 'mdast'; +import { join, dirname } from 'path'; import prettier from 'prettier'; +import { remark } from 'remark'; +// @ts-ignore No typescript declaration file +import flatmap from 'unist-util-flatmap'; -const verify = process.argv.includes('--verify'); -const git = process.argv.includes('--git'); -let fileChanged = false; -// Possible Improvement: combine with lint-staged to only copy files that have changed -const prepareOutFile = (file: string): string => { - const outFile = join('docs', file.replace('src/docs/', '')); - mkdirSync(dirname(outFile), { recursive: true }); - return outFile; +const SOURCE_DOCS_DIR = 'src/docs'; +const FINAL_DOCS_DIR = 'docs'; + +const AUTOGENERATED_TEXT = `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in ${SOURCE_DOCS_DIR}.`; + +const LOGMSG_TRANSFORMED = 'transformed'; +const LOGMSG_TO_BE_TRANSFORMED = 'to be transformed'; +const LOGMSG_COPIED = `, and copied to ${FINAL_DOCS_DIR}`; + +const WARN_DOCSDIR_DOESNT_MATCH = `Changed files were transformed in ${SOURCE_DOCS_DIR} but do not match the files in ${FINAL_DOCS_DIR}. Please run yarn docs:build after making changes to ${SOURCE_DOCS_DIR} to update the ${FINAL_DOCS_DIR} directory with the transformed files.`; + +const verifyOnly: boolean = process.argv.includes('--verify'); +const git: boolean = process.argv.includes('--git'); + +// TODO: Read from .prettierrc? +const prettierConfig: prettier.Config = { + useTabs: false, + tabWidth: 2, + endOfLine: 'auto', + printWidth: 100, + singleQuote: true, }; -const verifyAndCopy = (file: string, content?: string) => { - const outFile = prepareOutFile(file); - const existingBuffer = existsSync(outFile) ? readFileSync(outFile) : Buffer.from('#NEW FILE#'); - const newBuffer = content ? Buffer.from(content) : readFileSync(file); +let filesWereTransformed = false; + +/** + * Given a source file name and path, return the documentation destination full + * path and file name Create the destination path if it does not already exist. + * + * @param {string} file - Name of the file (including full path) + * @returns {string} Name of the file with the path changed from the source + * directory to final documentation directory + * @todo Possible Improvement: combine with lint-staged to only copy files that + * have changed + */ +const changeToFinalDocDir = (file: string): string => { + const newDir = file.replace(SOURCE_DOCS_DIR, FINAL_DOCS_DIR); + mkdirSync(dirname(newDir), { recursive: true }); + return newDir; +}; + +/** + * Log messages to the console showing if the transformed file copied to the + * final documentation directory or still needs to be copied. + * + * @param {string} filename Name of the file that was transformed + * @param {boolean} wasCopied Whether or not the file was copied + */ +const logWasOrShouldBeTransformed = (filename: string, wasCopied: boolean) => { + const changeMsg = wasCopied ? LOGMSG_TRANSFORMED : LOGMSG_TO_BE_TRANSFORMED; + let logMsg: string; + logMsg = ` File ${changeMsg}: ${filename}`; + if (wasCopied) { + logMsg += LOGMSG_COPIED; + } + console.log(logMsg); +}; + +/** + * If the file contents were transformed, set the _filesWereTransformed_ flag to + * true and copy the transformed contents to the final documentation directory + * if the doCopy flag is true. Log messages to the console. + * + * @param {string} filename Name of the file that will be verified + * @param {boolean} [doCopy=false] Whether we should copy that + * transformedContents to the final documentation directory. Default is + * `false`. Default is `false` + * @param {string} [transformedContent] New contents for the file + */ +const copyTransformedContents = (filename: string, doCopy = false, transformedContent?: string) => { + const fileInFinalDocDir = changeToFinalDocDir(filename); + const existingBuffer = existsSync(fileInFinalDocDir) + ? readFileSync(fileInFinalDocDir) + : Buffer.from('#NEW FILE#'); + const newBuffer = transformedContent ? Buffer.from(transformedContent) : readFileSync(filename); if (existingBuffer.equals(newBuffer)) { - // Files are same, skip. - return; + return; // Files are same, skip. } - console.log(`File changed: ${outFile}`); - fileChanged = true; - if (!verify) { - writeFileSync(outFile, newBuffer); + + filesWereTransformed = true; + if (doCopy) { + writeFileSync(fileInFinalDocDir, newBuffer); } + logWasOrShouldBeTransformed(fileInFinalDocDir, doCopy); }; -const transform = (file: string) => { - const doc = readFileSync(file, 'utf8'); +const readSyncedUTF8file = (filename: string): string => { + return readFileSync(filename, 'utf8'); +}; + +/** + * Transform a markdown file and write the transformed file to the directory for + * published documentation + * + * 1. Add a `mermaid-example` block before every `mermaid` or `mmd` block On the + * docsify site (one place where the documentation is published), this will + * show the code used for the mermaid diagram + * 2. Add the text that says the file is automatically generated + * 3. Use prettier to format the file Verify that the file has been changed and + * write out the changes + * + * @param file {string} name of the file that will be verified + */ +const transformMarkdown = (file: string) => { + const doc = readSyncedUTF8file(file); const ast: Root = remark.parse(doc); const out = flatmap(ast, (c: Code) => { if (c.type !== 'code' || !c.lang?.startsWith('mermaid')) { @@ -46,38 +158,82 @@ const transform = (file: string) => { return [c, Object.assign({}, c, { lang: 'mermaid' })]; }); - const transformed = `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit corresponding file in src/docs.\n${remark.stringify( - out - )}`; - verifyAndCopy( - file, - prettier.format(transformed, { - parser: 'markdown', - useTabs: false, - tabWidth: 2, - endOfLine: 'auto', - printWidth: 100, - singleQuote: true, - }) - ); + // Add the AUTOGENERATED_TEXT to the start of the file + const transformed = `${AUTOGENERATED_TEXT}\n${remark.stringify(out)}`; + const formatted = prettier.format(transformed, { + parser: 'markdown', + ...prettierConfig, + }); + copyTransformedContents(file, !verifyOnly, formatted); }; -(async () => { - const mdFiles = await globby(['./src/docs/**/*.md'], { dot: true }); - mdFiles.forEach(transform); - const nonMDFiles = await globby(['src/docs/**', '!**/*.md'], { dot: true }); - nonMDFiles.forEach((file) => { - verifyAndCopy(file); +/** + * Transform an HTML file and write the transformed file to the directory for + * published documentation + * + * - Add the text that says the file is automatically generated Verify that the + * file has been changed and write out the changes + * + * @param filename {string} name of the HTML file to transform + */ +const transformHtml = (filename: string) => { + /** + * Insert the '...auto generated...' comment into an HTML file after the<html> element + * + * @param fileName {string} file name that should have the comment inserted + * @returns {string} The contents of the file with the comment inserted + */ + const insertAutoGeneratedComment = (fileName: string): string => { + const fileContents = readSyncedUTF8file(fileName); + const jsdom = new JSDOM(fileContents); + const htmlDoc = jsdom.window.document; + const autoGeneratedComment = jsdom.window.document.createComment(AUTOGENERATED_TEXT); + + const rootElement = htmlDoc.documentElement; + rootElement.prepend(autoGeneratedComment); + return jsdom.serialize(); + }; + + const transformedHTML = insertAutoGeneratedComment(filename); + const formattedHTML = prettier.format(transformedHTML, { + parser: 'html', + ...prettierConfig, }); - if (fileChanged) { - if (verify) { - console.log( - "Changes detected in files in `docs`. Please run `yarn docs:build` after making changes to 'src/docs' to update the `docs` folder." - ); + copyTransformedContents(filename, !verifyOnly, formattedHTML); +}; + +/** Main method (entry point) */ +(async () => { + const sourceDirGlob = join('.', SOURCE_DOCS_DIR, '**'); + const includeFilesStartingWithDot = true; + + console.log('Transforming markdown files...'); + const mdFiles = await globby([join(sourceDirGlob, '*.md')], { + dot: includeFilesStartingWithDot, + }); + mdFiles.forEach(transformMarkdown); + + console.log('Transforming html files...'); + const htmlFiles = await globby([join(sourceDirGlob, '*.html')], { + dot: includeFilesStartingWithDot, + }); + htmlFiles.forEach(transformHtml); + + console.log('Transforming all other files...'); + const otherFiles = await globby([sourceDirGlob, '!**/*.md', '!**/*.html'], { + dot: includeFilesStartingWithDot, + }); + otherFiles.forEach((file: string) => { + copyTransformedContents(file, !verifyOnly); // no transformation + }); + + if (filesWereTransformed) { + if (verifyOnly) { + console.log(WARN_DOCSDIR_DOESNT_MATCH); process.exit(1); } if (git) { - console.log('Adding changes in docs folder to git'); + console.log('Adding changes in ${FINAL_DOCS_DIR} folder to git'); exec('git add docs'); } } diff --git a/src/docs/Setup.md b/src/docs/Setup.md index 41e706825..aae2ae9c0 100644 --- a/src/docs/Setup.md +++ b/src/docs/Setup.md @@ -2,13 +2,10 @@ ## mermaidAPI -Edit this -Page[\[N|Solid\](img/GitHub-Mark-32px.png)][1] - This is the API to be used when optionally handling the integration with the web page, instead of using the default integration provided by mermaid.js. -The core of this api is the [**render**][2] function which, given a graph +The core of this api is the [**render**][1] function which, given a graph definition as text, renders the graph/diagram and returns an svg element for the graph. It is then up to the user of the API to make use of the svg, either insert it somewhere in the @@ -19,7 +16,7 @@ In addition to the render function, a number of behavioral configuration options ## Configuration **Configuration methods in Mermaid version 8.6.0 have been updated, to learn more\[[click -here][3]].** +here][2]].** ## **What follows are config instructions for older versions** @@ -34,7 +31,7 @@ htmlLabels:true, curve:'cardinal', }, }; mermaid.initialize(config); </script> </pre> -A summary of all options and their defaults is found [here][4]. +A summary of all options and their defaults is found [here][3]. A description of each option follows below. ## theme @@ -222,7 +219,7 @@ Default value: true Decides which rendering engine that is to be used for the rendering. Legal values are: dagre-d3 dagre-wrapper - wrapper for dagre implemented in mermaid -Default value: 'dagre-d3' +Default value: 'dagre-wrapper' ## sequence @@ -365,7 +362,8 @@ Default value: true **Notes:** -This will display arrows that start and begin at the same node as right angles, rather than a curve +This will display arrows that start and begin at the same node as right angles, rather than a +curve Default value: false @@ -717,7 +715,8 @@ Default value: true **Notes:** -This will display arrows that start and begin at the same node as right angles, rather than a curves +This will display arrows that start and begin at the same node as right angles, rather than a +curves Default value: false @@ -1409,10 +1408,10 @@ This sets the auto-wrap padding for the diagram (sides only) ### Parameters -- `text` **[string][5]** -- `parseError` **[Function][6]?** +- `text` **[string][4]** +- `parseError` **[Function][5]?** -Returns **[boolean][7]** +Returns **[boolean][6]** ## setSiteConfig @@ -1431,7 +1430,7 @@ function _Default value: At default, will mirror Global Config_ - `conf` **MermaidConfig** The base currentConfig to use as siteConfig -Returns **[object][8]** The siteConfig +Returns **[object][7]** The siteConfig ## getSiteConfig @@ -1443,7 +1442,7 @@ Returns **[object][8]** The siteConfig **Notes**: Returns **any** values in siteConfig. -Returns **[object][8]** The siteConfig +Returns **[object][7]** The siteConfig ## setConfig @@ -1482,10 +1481,10 @@ $(function () { ### Parameters -- `id` **[string][5]** The id of the element to be rendered -- `text` **[string][5]** The graph definition -- `cb` **function (svgCode: [string][5], bindFunctions: function (element: [Element][9]): void): void** -- `container` **[Element][9]** Selector to element in which a div with the graph temporarily will be +- `id` **[string][4]** The id of the element to be rendered +- `text` **[string][4]** The graph definition +- `cb` **function (svgCode: [string][4], bindFunctions: function (element: [Element][8]): void): void** +- `container` **[Element][8]** Selector to element in which a div with the graph temporarily will be inserted. If one is provided a hidden div will be inserted in the body of the page instead. The element will be removed when rendering is completed. @@ -1524,7 +1523,7 @@ Pushes in a directive to the configuration ### Parameters -- `directive` **[object][8]** The directive to push in +- `directive` **[object][7]** The directive to push in ## reset @@ -1618,12 +1617,11 @@ Returns **void** </script> ``` -[1]: https://github.com/mermaid-js/mermaid/blob/develop/src/mermaidAPI.js -[2]: Setup.md?id=render -[3]: 8.6.0_docs.md -[4]: #mermaidapi-configuration-defaults -[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String -[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function -[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean -[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object -[9]: https://developer.mozilla.org/docs/Web/API/Element +[1]: Setup.md?id=render +[2]: 8.6.0_docs.md +[3]: #mermaidapi-configuration-defaults +[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String +[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function +[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean +[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object +[8]: https://developer.mozilla.org/docs/Web/API/Element diff --git a/src/docs/development.md b/src/docs/development.md index 96da46c11..95e5fe417 100644 --- a/src/docs/development.md +++ b/src/docs/development.md @@ -6,7 +6,7 @@ So you want to help? That's great! Here are a few things to get you started on the right path. -**The Docs Structure is dictated by [sidebar.md](https://github.com/mermaid-js/mermaid/edit/develop/docs/_sidebar.md)** +**The Docs Structure is dictated by [sidebar.md](https://github.com/mermaid-js/mermaid/edit/develop/src/docs/_sidebar.md)** **Note: Commits and Pull Requests should be directed to the develop branch.** @@ -44,9 +44,9 @@ Start with the type, such as **feature** or **bug**, followed by the issue numbe If it is not in the documentation, it's like it never happened. Wouldn't that be sad? With all the effort that was put into the feature? -The docs are located in the `src/docs` folder and are written in Markdown. Just pick the right section and start typing. If you want to propose changes to the structure of the documentation, such as adding a new section or a new file you do that via the **[sidebar](https://github.com/mermaid-js/mermaid/edit/develop/docs/_sidebar.md)**. +The docs are located in the `src/docs` folder and are written in Markdown. Just pick the right section and start typing. If you want to propose changes to the structure of the documentation, such as adding a new section or a new file you do that via the **[sidebar](https://github.com/mermaid-js/mermaid/edit/develop/src/docs/_sidebar.md)**. -> **All the documents displayed in the github.io page are listed in [sidebar.md](https://github.com/mermaid-js/mermaid/edit/develop/docs/_sidebar.md)**. +> **All the documents displayed in the GitHub.io page are listed in [sidebar.md](https://github.com/mermaid-js/mermaid/edit/develop/src/docs/_sidebar.md)**. The contents of [https://mermaid-js.github.io/mermaid/](https://mermaid-js.github.io/mermaid/) are based on the docs from the `master` branch. Updates committed to the `master` branch are reflected in the [Mermaid Docs](https://mermaid-js.github.io/mermaid/) once released. @@ -58,7 +58,7 @@ The documentation is located in the `src/docs` directory and organized according The `docs` folder will be automatically generated when committing to `src/docs` and should not be edited manually. -We encourage contributions to the documentation at [mermaid-js/mermaid/docs](https://github.com/mermaid-js/mermaid/tree/develop/docs). We publish documentation using GitHub Pages with [Docsify](https://www.youtube.com/watch?v=TV88lp7egMw&t=3s) +We encourage contributions to the documentation at [mermaid-js/mermaid/src/docs](https://github.com/mermaid-js/mermaid/tree/develop/src/docs). We publish documentation using GitHub Pages with [Docsify](https://www.youtube.com/watch?v=TV88lp7egMw&t=3s) ### Add Unit Tests for Parsing @@ -71,7 +71,7 @@ This tests the rendering and visual appearance of the diagrams. This ensures tha To start working with the e2e tests: 1. Run `yarn dev` to start the dev server -2. Start **Cypress** by running `cypress open` in the **mermaid** folder. +2. Start **Cypress** by running `cypress open` in the **mermaid** folder. (Make sure you have path to Cypress in order, the binary is located in `node_modules/.bin`). The rendering tests are very straightforward to create. There is a function `imgSnapshotTest`, which takes a diagram in text form and the mermaid options, and it renders that diagram in Cypress. @@ -112,7 +112,7 @@ Markdown is used to format the text, for more information about Markdown [see th To edit Docs on your computer: -1. Find the Markdown file (.md) to edit in the [mermaid-js/mermaid/docs](https://github.com/mermaid-js/mermaid/tree/develop/docs) directory in the `develop` branch. +1. Find the Markdown file (.md) to edit in the [mermaid-js/mermaid/src/docs](https://github.com/mermaid-js/mermaid/tree/develop/src/docs) directory in the `develop` branch. 2. Create a fork of the develop branch. 3. Make changes or add new documentation. 4. Commit changes to your fork and push it to GitHub. @@ -121,7 +121,7 @@ To edit Docs on your computer: To edit Docs on GitHub: 1. Login to [GitHub.com](https://www.github.com). -2. Navigate to [mermaid-js/mermaid/docs](https://github.com/mermaid-js/mermaid/tree/develop/docs). +2. Navigate to [mermaid-js/mermaid/src/docs](https://github.com/mermaid-js/mermaid/tree/develop/src/docs). 3. To edit a file, click the pencil icon at the top-right of the file contents panel. 4. Describe what you changed in the **Propose file change** section, located at the bottom of the page. 5. Submit your changes by clicking the button **Propose file change** at the bottom (by automatic creation of a fork and a new branch). diff --git a/src/docs/index.html b/src/docs/index.html index 39d454533..ea3969c77 100644 --- a/src/docs/index.html +++ b/src/docs/index.html @@ -21,22 +21,13 @@ rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css" /> - <script src="//cdn.jsdelivr.net/npm/mermaid@9.1.6/dist/mermaid.min.js"></script> + <script src="//cdn.jsdelivr.net/npm/mermaid@9.1.7/dist/mermaid.min.js"></script> <!-- <script src="http://localhost:9000/mermaid.js"></script> --> - <script> - // prettier-ignore - (function (i, s, o, g, r, a, m) { - i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () { - (i[r].q = i[r].q || []).push(arguments) - }, i[r].l = 1 * new Date(); a = s.createElement(o), - m = s.getElementsByTagName(o)[0]; a.async = 1; a.src = g; m.parentNode.insertBefore(a, m) - })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga'); - - ga('create', 'UA-153180559-1', 'auto'); - if (location) { - ga('send', 'pageview', location.hash); - } - </script> + <script + defer + data-domain="mermaid-js.github.io" + src="https://plausible.io/js/plausible.js" + ></script> <script> var require = { paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.29.1/min/vs' }, diff --git a/src/docs/mindmap.md b/src/docs/mindmap.md index 141808514..85a05e04b 100644 --- a/src/docs/mindmap.md +++ b/src/docs/mindmap.md @@ -1,7 +1,5 @@ # Mindmap -**Edit this Page** [![N|Solid](img/GitHub-Mark-32px.png)](https://github.com/mermaid-js/mermaid/blob/develop/docs/mindmap.md) - > Mindmap: This is an experimental diagram for now. The syntax and properties can change in future releases. The syntax is stabel except for the icon integration which is the experimental part. "A mind map is a diagram used to visually organize information into a hierarchy, showing relationships among pieces of the whole. It is often created around a single concept, drawn as an image in the center of a blank page, to which associated representations of ideas such as images, words and parts of words are added. Major ideas are connected directly to the central concept, and other ideas branch out from those major ideas." Wikipedia @@ -43,7 +41,7 @@ mindmap C ``` -In summary is is a simple text outline where there are one node at the root level called `Root` which has one child `A`. A in turn has two children `B`and `C`. In the diagram below we can see this rendered as a mindmap. +In summary is a simple text outline where there are one node at the root level called `Root` which has one child `A`. `A` in turn has two children `B`and `C`. In the diagram below we can see this rendered as a mindmap. ```mermaid mindmap @@ -109,7 +107,7 @@ More shapes will be added, beginning with the shapes available in flowcharts. ## icons -As with flowcharts you can add icons to your nodes but with an updated syntax. The styling for the font based icons are added during the integration so that they are available for the web page. _This is not something a diagram author can do but has to be done with the site administrator or the integrator_. Once the icon fonts are in place you add them to the mind map nodes using the `::icon()` syntax. You place the classes for the icon within the parethesis like in the following example where icons for material design and fontwaresome 4. is displayed. The intention is that this approach should be used for all diagrams supporting icons. **Expermental feature:** This wider scope is also the reason Mindmaps are experimental as this syntax and approach could change. +As with flowcharts you can add icons to your nodes but with an updated syntax. The styling for the font based icons are added during the integration so that they are available for the web page. _This is not something a diagram author can do but has to be done with the site administrator or the integrator_. Once the icon fonts are in place you add them to the mind map nodes using the `::icon()` syntax. You place the classes for the icon within the parenthesis like in the following example where icons for material design and fontawesome 4 are displayed. The intention is that this approach should be used for all diagrams supporting icons. **Experimental feature:** This wider scope is also the reason Mindmaps are experimental as this syntax and approach could change. ```mermaid-example mindmap @@ -122,7 +120,7 @@ mindmap ## Classes -Again the syntax for adding classes is similar to flowcharts and you can add classes using a tripple colon following a numver of css classes separated by space. In the following example one of the nodes has two custom classes attached urgent turning the background red and the text whiet and large increasing the font size: +Again the syntax for adding classes is similar to flowcharts. You can add classes using a triple colon following a number of css classes separated by space. In the following example one of the nodes has two custom classes attached urgent turning the background red and the text white and large increasing the font size: ```mermaid-example mindmap @@ -147,7 +145,7 @@ mindmap C ``` -This outline is unclear as `B` clearly is a child of `A` but when we move on to `C` the clarity is lost. `C` is not a child of `B` with a highter indentation nor does ot haver the same indentation as `B`. The only thing that is clear is that the first node with smaller indentation, indicating a parent, is A. Then Mermaid relies on this known truth and compensates for the unclear indentation and selects `A` as a parent of `C` leading till the same diagram with `B` and `C` as sieblings. +This outline is unclear as `B` clearly is a child of `A` but when we move on to `C` the clarity is lost. `C` is not a child of `B` with a higher indentation nor does it have the same indentation as `B`. The only thing that is clear is that the first node with smaller indentation, indicating a parent, is A. Then Mermaid relies on this known truth and compensates for the unclear indentation and selects `A` as a parent of `C` leading till the same diagram with `B` and `C` as siblings. ```mermaid mindmap diff --git a/src/interactionDb.ts b/src/interactionDb.ts index 379685c83..06150b927 100644 --- a/src/interactionDb.ts +++ b/src/interactionDb.ts @@ -1,5 +1,5 @@ -let interactionFunctions: (() => {})[] = []; -export const addFunction = (func: () => {}) => { +let interactionFunctions: (() => void)[] = []; +export const addFunction = (func: () => void) => { interactionFunctions.push(func); }; export const attachFunctions = () => { diff --git a/src/jison/transformer.js b/src/jison/transformer.js index 9100235fe..f1f036d13 100644 --- a/src/jison/transformer.js +++ b/src/jison/transformer.js @@ -1,3 +1,4 @@ +// eslint-disable-next-line @typescript-eslint/no-var-requires const { Generator } = require('jison'); module.exports = { diff --git a/src/logger.ts b/src/logger.ts index 195cde7f3..b01934e88 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -1,3 +1,7 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable @typescript-eslint/no-empty-function */ +/* eslint-disable no-console */ import moment from 'moment-mini'; export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal'; @@ -32,6 +36,8 @@ export const setLogLevel = function (level: keyof typeof LEVELS | number | strin if (level in LEVELS) { numericLevel = LEVELS[level as keyof typeof LEVELS]; } + } else if (typeof level === 'number') { + numericLevel = level; } log.trace = () => {}; log.debug = () => {}; diff --git a/src/mermaid.spec.ts b/src/mermaid.spec.ts index b429d07ec..7ba8c9c04 100644 --- a/src/mermaid.spec.ts +++ b/src/mermaid.spec.ts @@ -1,11 +1,6 @@ import mermaid from './mermaid'; import { mermaidAPI } from './mermaidAPI'; -import flowDb from './diagrams/flowchart/flowDb'; -// @ts-ignore -import flowParser from './diagrams/flowchart/parser/flow'; -import flowRenderer from './diagrams/flowchart/flowRenderer'; -import Diagram from './Diagram'; -import { vi, describe, it, beforeEach, afterEach } from 'vitest'; +import { vi, describe, it, beforeEach, afterEach, expect } from 'vitest'; const spyOn = vi.spyOn; vi.mock('./mermaidAPI'); @@ -60,159 +55,7 @@ describe('when using mermaid and ', function () { }); }); - describe('when calling addEdges ', function () { - beforeEach(function () { - flowParser.parser.yy = flowDb; - flowDb.clear(); - flowDb.setGen('gen-2'); - }); - it('should handle edges with text', function () { - const diag = new Diagram('graph TD;A-->|text ex|B;'); - diag.db.getVertices(); - const edges = diag.db.getEdges(); - - const mockG = { - setEdge: function (start: any, end: any, options: { arrowhead: any; label: string }) { - expect(start).toContain('flowchart-A-'); - expect(end).toContain('flowchart-B-'); - expect(options.arrowhead).toBe('normal'); - expect(options.label.match('text ex')).toBeTruthy(); - }, - }; - - flowRenderer.addEdges(edges, mockG, diag); - }); - - it('should handle edges without text', function () { - const diag = new Diagram('graph TD;A-->B;'); - diag.db.getVertices(); - const edges = diag.db.getEdges(); - - const mockG = { - setEdge: function (start: any, end: any, options: { arrowhead: any }) { - expect(start).toContain('flowchart-A-'); - expect(end).toContain('flowchart-B-'); - expect(options.arrowhead).toBe('normal'); - }, - }; - - flowRenderer.addEdges(edges, mockG, diag); - }); - - it('should handle open-ended edges', function () { - const diag = new Diagram('graph TD;A---B;'); - diag.db.getVertices(); - const edges = diag.db.getEdges(); - - const mockG = { - setEdge: function (start: any, end: any, options: { arrowhead: any }) { - expect(start).toContain('flowchart-A-'); - expect(end).toContain('flowchart-B-'); - expect(options.arrowhead).toBe('none'); - }, - }; - - flowRenderer.addEdges(edges, mockG, diag); - }); - - it('should handle edges with styles defined', function () { - const diag = new Diagram('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;'); - diag.db.getVertices(); - const edges = diag.db.getEdges(); - - const mockG = { - setEdge: function (start: any, end: any, options: { arrowhead: any; style: any }) { - expect(start).toContain('flowchart-A-'); - expect(end).toContain('flowchart-B-'); - expect(options.arrowhead).toBe('none'); - expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;'); - }, - }; - - flowRenderer.addEdges(edges, mockG, diag); - }); - it('should handle edges with interpolation defined', function () { - const diag = new Diagram('graph TD;A---B; linkStyle 0 interpolate basis'); - diag.db.getVertices(); - const edges = diag.db.getEdges(); - - const mockG = { - setEdge: function (start: any, end: any, options: { arrowhead: any; curve: any }) { - expect(start).toContain('flowchart-A-'); - expect(end).toContain('flowchart-B-'); - expect(options.arrowhead).toBe('none'); - expect(options.curve).toBe('basis'); // mocked as string - }, - }; - - flowRenderer.addEdges(edges, mockG, diag); - }); - it('should handle edges with text and styles defined', function () { - const diag = new Diagram( - 'graph TD;A---|the text|B; linkStyle 0 stroke:val1,stroke-width:val2;' - ); - diag.db.getVertices(); - const edges = diag.db.getEdges(); - - const mockG = { - setEdge: function ( - start: any, - end: any, - options: { arrowhead: any; label: string; style: any } - ) { - expect(start).toContain('flowchart-A-'); - expect(end).toContain('flowchart-B-'); - expect(options.arrowhead).toBe('none'); - expect(options.label.match('the text')).toBeTruthy(); - expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;'); - }, - }; - - flowRenderer.addEdges(edges, mockG, diag); - }); - - it('should set fill to "none" by default when handling edges', function () { - const diag = new Diagram('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;'); - diag.db.getVertices(); - const edges = diag.db.getEdges(); - - const mockG = { - setEdge: function (start: any, end: any, options: { arrowhead: any; style: any }) { - expect(start).toContain('flowchart-A-'); - expect(end).toContain('flowchart-B'); - expect(options.arrowhead).toBe('none'); - expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;'); - }, - }; - - flowRenderer.addEdges(edges, mockG, diag); - }); - - it('should not set fill to none if fill is set in linkStyle', function () { - const diag = new Diagram( - 'graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2,fill:blue;' - ); - diag.db.getVertices(); - const edges = diag.db.getEdges(); - const mockG = { - setEdge: function (start: any, end: any, options: { arrowhead: any; style: any }) { - expect(start).toContain('flowchart-A-'); - expect(end).toContain('flowchart-B-'); - expect(options.arrowhead).toBe('none'); - expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:blue;'); - }, - }; - - flowRenderer.addEdges(edges, mockG, diag); - }); - }); - describe('checking validity of input ', function () { - beforeEach(function () { - flowParser.parser.yy = flowDb; - flowDb.clear(); - flowDb.setGen('gen-2'); - }); it('should throw for an invalid definition', function () { expect(() => mermaid.parse('this is not a mermaid diagram definition')).toThrow(); }); diff --git a/src/mermaid.ts b/src/mermaid.ts index d22ff1922..6eec7ea66 100644 --- a/src/mermaid.ts +++ b/src/mermaid.ts @@ -1,3 +1,4 @@ +'use strict'; /** * Web page integration module for the mermaid framework. It uses the mermaidAPI for mermaid * functionality and to render the diagrams to svg code. @@ -14,7 +15,8 @@ import { isDetailedError } from './utils'; * Function that goes through the document to find the chart definitions in there and render them. * * The function tags the processed attributes with the attribute data-processed and ignores found - * elements with the attribute already set. This way the init function can be triggered several times. + * elements with the attribute already set. This way the init function can be triggered several + * times. * * Optionally, `init` can accept in the second argument one of the following: * @@ -30,6 +32,7 @@ import { isDetailedError } from './utils'; * ``` * * Renders the mermaid diagrams + * * @param config * @param nodes * @param callback @@ -38,6 +41,7 @@ const init = function ( config?: MermaidConfig, // eslint-disable-next-line no-undef nodes?: string | HTMLElement | NodeListOf<HTMLElement>, + // eslint-disable-next-line @typescript-eslint/ban-types callback?: Function ) { try { @@ -57,13 +61,14 @@ const initThrowsErrors = function ( config?: MermaidConfig, // eslint-disable-next-line no-undef nodes?: string | HTMLElement | NodeListOf<HTMLElement>, + // eslint-disable-next-line @typescript-eslint/ban-types callback?: Function ) { const conf = mermaidAPI.getConfig(); // console.log('Starting rendering diagrams (init) - mermaid.init', conf); if (config) { // This is a legacy way of setting config. It is not documented and should be removed in the future. - // @ts-ignore + // @ts-ignore: TODO Fix ts errors mermaid.sequenceConfig = config; } @@ -91,9 +96,11 @@ const initThrowsErrors = function ( const idGenerator = new utils.initIdGenerator(conf.deterministicIds, conf.deterministicIDSeed); let txt; + const errors = []; // element is the current div with mermaid class for (const element of Array.from(nodesToProcess)) { + log.info('Rendering diagram: ' + element.id); /*! Check if previously processed */ if (element.getAttribute('data-processed')) { continue; @@ -130,11 +137,18 @@ const initThrowsErrors = function ( ); } catch (error) { log.warn('Catching Error (bootstrap)', error); - // @ts-ignore - // TODO: We should be throwing an error object. - throw { error, message: error.str }; + // @ts-ignore: TODO Fix ts errors + const mermaidError = { error, str: error.str, hash: error.hash, message: error.str }; + if (typeof mermaid.parseError === 'function') { + mermaid.parseError(mermaidError); + } + errors.push(mermaidError); } } + if (errors.length > 0) { + // TODO: We should be throwing an error object. + throw errors[0]; + } }; const initialize = function (config: MermaidConfig) { @@ -143,7 +157,8 @@ const initialize = function (config: MermaidConfig) { /** * ##contentLoaded Callback function that is called when page is loaded. This functions fetches - * configuration for mermaid rendering and calls init for rendering the mermaid diagrams on the page. + * configuration for mermaid rendering and calls init for rendering the mermaid diagrams on the + * page. */ const contentLoaded = function () { if (mermaid.startOnLoad) { @@ -158,13 +173,7 @@ if (typeof document !== 'undefined') { /*! * Wait for document loaded before starting the execution */ - window.addEventListener( - 'load', - function () { - contentLoaded(); - }, - false - ); + window.addEventListener('load', contentLoaded, false); } /** @@ -192,6 +201,7 @@ const parse = (txt: string) => { const mermaid: { startOnLoad: boolean; diagrams: any; + // eslint-disable-next-line @typescript-eslint/ban-types parseError?: Function; mermaidAPI: typeof mermaidAPI; parse: typeof parse; diff --git a/src/mermaidAPI.spec.js b/src/mermaidAPI.spec.js index 3c4a28ca9..241b5ec86 100644 --- a/src/mermaidAPI.spec.js +++ b/src/mermaidAPI.spec.js @@ -1,3 +1,4 @@ +'use strict'; import mermaid from './mermaid'; import mermaidAPI from './mermaidAPI'; import assignWithDepth from './assignWithDepth'; diff --git a/src/mermaidAPI.ts b/src/mermaidAPI.ts index 3f3e97d3b..db1f8d453 100644 --- a/src/mermaidAPI.ts +++ b/src/mermaidAPI.ts @@ -1,7 +1,4 @@ /** - * Edit this - * Page[[N|Solid](img/GitHub-Mark-32px.png)](https://github.com/mermaid-js/mermaid/blob/develop/src/mermaidAPI.js) - * * This is the API to be used when optionally handling the integration with the web page, instead of * using the default integration provided by mermaid.js. * @@ -17,7 +14,7 @@ */ import { select } from 'd3'; import { compile, serialize, stringify } from 'stylis'; -// @ts-ignore +// @ts-ignore: TODO Fix ts errors import pkg from '../package.json'; import * as configApi from './config'; import { addDiagrams } from './diagram-api/diagram-orchestration'; @@ -26,7 +23,7 @@ import flowDb from './diagrams/flowchart/flowDb'; import flowRenderer from './diagrams/flowchart/flowRenderer'; import ganttDb from './diagrams/gantt/ganttDb'; import Diagram from './Diagram'; -import errorRenderer from './errorRenderer'; +import errorRenderer from './diagrams/error/errorRenderer'; import { attachFunctions } from './interactionDb'; import { log, setLogLevel } from './logger'; import getStyles from './styles'; @@ -42,6 +39,7 @@ let hasLoadedDiagrams = false; * @param text * @param parseError */ +// eslint-disable-next-line @typescript-eslint/ban-types function parse(text: string, parseError?: Function): boolean { if (!hasLoadedDiagrams) { addDiagrams(); @@ -123,6 +121,10 @@ const render = function ( cb: (svgCode: string, bindFunctions?: (element: Element) => void) => void, container?: Element ): void { + if (!hasLoadedDiagrams) { + addDiagrams(); + hasLoadedDiagrams = true; + } configApi.reset(); text = text.replace(/\r\n?/g, '\n'); // parser problems on CRLF ignore all CR and leave LF;; const graphInit = utils.detectInit(text); @@ -130,7 +132,7 @@ const render = function ( directiveSanitizer(graphInit); configApi.addDirective(graphInit); } - let cnf = configApi.getConfig(); + const cnf = configApi.getConfig(); log.debug(cnf); @@ -227,7 +229,14 @@ const render = function ( text = encodeEntities(text); // Important that we do not create the diagram until after the directives have been included - const diag = new Diagram(text); + let diag; + let parseEncounteredException; + try { + diag = new Diagram(text); + } catch (error) { + diag = new Diagram('error'); + parseEncounteredException = error; + } // Get the tmp element containing the the svg const element = root.select('#d' + id).node(); const graphType = diag.type; @@ -300,7 +309,7 @@ const render = function ( try { diag.renderer.draw(text, id, pkg.version, diag); } catch (e) { - errorRenderer.draw(id, pkg.version); + errorRenderer.draw(text, id, pkg.version); throw e; } @@ -323,8 +332,8 @@ const render = function ( svgCode = svgCode.replace(/<br>/g, '<br/>'); if (cnf.securityLevel === 'sandbox') { - let svgEl = root.select('#d' + id + ' svg').node(); - let width = '100%'; + const svgEl = root.select('#d' + id + ' svg').node(); + const width = '100%'; let height = '100%'; if (svgEl) { height = svgEl.viewBox.baseVal.height + 'px'; @@ -370,6 +379,10 @@ const render = function ( node.remove(); } + if (parseEncounteredException) { + throw parseEncounteredException; + } + return svgCode; }; @@ -401,7 +414,7 @@ const parseDirective = function (p: any, statement: string, context: string, typ log.error( `Error while rendering sequenceDiagram directive: ${statement} jison context: ${context}` ); - // @ts-ignore + // @ts-ignore: TODO Fix ts errors log.error(error.message); } }; diff --git a/src/styles.ts b/src/styles.ts index b0201f649..0c4a7e1a5 100644 --- a/src/styles.ts +++ b/src/styles.ts @@ -1,5 +1,6 @@ import classDiagram from './diagrams/class/styles'; import er from './diagrams/er/styles'; +import error from './diagrams/error/styles'; import flowchart from './diagrams/flowchart/styles'; import gantt from './diagrams/gantt/styles'; // import gitGraph from './diagrams/git/styles'; @@ -14,7 +15,7 @@ import { FlowChartStyleOptions } from './diagrams/flowchart/styles'; import { log } from './logger'; // TODO @knut: Inject from registerDiagram. -const themes = { +const themes: Record<string, any> = { flowchart, 'flowchart-v2': flowchart, sequence, @@ -28,6 +29,7 @@ const themes = { info, pie, er, + error, journey, requirement, c4, @@ -45,7 +47,7 @@ const getStyles = ( lineColor: string; } & FlowChartStyleOptions ) => { - let diagramStyles: string = ''; + let diagramStyles = ''; if (type in themes && themes[type as keyof typeof themes]) { diagramStyles = themes[type as keyof typeof themes](options); } else { @@ -103,8 +105,7 @@ const getStyles = ( `; }; -export const addStylesForDiagram = (type: string, diagramTheme: any) => { - // @ts-ignore +export const addStylesForDiagram = (type: string, diagramTheme: unknown): void => { themes[type] = diagramTheme; }; diff --git a/src/utils.spec.js b/src/utils.spec.js index 3c50310c6..f1523aca5 100644 --- a/src/utils.spec.js +++ b/src/utils.spec.js @@ -3,6 +3,7 @@ import utils from './utils'; import assignWithDepth from './assignWithDepth'; import { detectType } from './diagram-api/detectType'; import { addDiagrams } from './diagram-api/diagram-orchestration'; +import memoize from 'lodash/memoize'; addDiagrams(); describe('when assignWithDepth: should merge objects within objects', function () { @@ -122,20 +123,30 @@ describe('when assignWithDepth: should merge objects within objects', function ( }); describe('when memoizing', function () { it('should return the same value', function () { - const fib = utils.memoize(function (n, canary) { - canary.flag = true; - if (n < 2) { - return 1; - } else { - //We'll console.log a loader every time we have to recurse - return fib(n - 2, canary) + fib(n - 1, canary); - } - }); + const fib = memoize( + function (n, x, canary) { + canary.flag = true; + if (n < 2) { + return 1; + } else { + //We'll console.log a loader every time we have to recurse + return fib(n - 2, x, canary) + fib(n - 1, x, canary); + } + }, + (n, x, _) => `${n}${x}` + ); let canary = { flag: false }; - fib(10, canary); + fib(10, 'a', canary); expect(canary.flag).toBe(true); canary = { flag: false }; - fib(10, canary); + fib(10, 'a', canary); + expect(canary.flag).toBe(false); + fib(10, 'b', canary); + fib(10, 'b', canary); + expect(canary.flag).toBe(true); + canary = { flag: false }; + fib(10, 'b', canary); + fib(10, 'a', canary); expect(canary.flag).toBe(false); }); }); diff --git a/src/utils.ts b/src/utils.ts index f88327367..d6b317034 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,4 +1,4 @@ -// @ts-nocheck +// @ts-nocheck : TODO Fix ts errors import { sanitizeUrl } from '@braintree/sanitize-url'; import { curveBasis, @@ -20,6 +20,7 @@ import { log } from './logger'; import { detectType } from './diagram-api/detectType'; import assignWithDepth from './assignWithDepth'; import { MermaidConfig } from './config.type'; +import memoize from 'lodash/memoize'; // Effectively an enum of the supported curve types, accessible by name const d3CurveTypes = { @@ -39,22 +40,22 @@ const directive = /[%]{2}[{]\s*(?:(?:(\w+)\s*:|(\w+))\s*(?:(?:(\w+))|((?:(?![}][%]{2}).|\r?\n)*))?\s*)(?:[}][%]{2})?/gi; const directiveWithoutOpen = /\s*(?:(?:(\w+)(?=:):|(\w+))\s*(?:(?:(\w+))|((?:(?![}][%]{2}).|\r?\n)*))?\s*)(?:[}][%]{2})?/gi; -const anyComment = /\s*%%.*\n/gm; /** * @function detectInit Detects the init config object from the text - * * @param config + * * ```mermaid + * * %%{init: {"theme": "debug", "logLevel": 1 }}%% * graph LR - * a-->b - * b-->c - * c-->d - * d-->e - * e-->f - * f-->g - * g-->h + * a-->b + * b-->c + * c-->d + * d-->e + * e-->f + * f-->g + * g-->h * ``` * * Or @@ -71,15 +72,15 @@ const anyComment = /\s*%%.*\n/gm; * g-->h * ``` * @param {string} text The text defining the graph - * @param {any} cnf + * @param {any} config * @returns {object} The json object representing the init passed to mermaid.initialize() */ export const detectInit = function (text: string, config?: MermaidConfig): MermaidConfig { - let inits = detectDirective(text, /(?:init\b)|(?:initialize\b)/); + const inits = detectDirective(text, /(?:init\b)|(?:initialize\b)/); let results = {}; if (Array.isArray(inits)) { - let args = inits.map((init) => init.args); + const args = inits.map((init) => init.args); directiveSanitizer(args); results = assignWithDepth(results, [...args]); @@ -134,8 +135,8 @@ export const detectDirective = function (text, type = null) { log.debug( `Detecting diagram directive${type !== null ? ' type:' + type : ''} based on the text:${text}` ); - let match, - result = []; + let match; + const result = []; while ((match = directive.exec(text)) !== null) { // This is necessary to avoid infinite loops with zero-width matches if (match.index === directive.lastIndex) { @@ -146,8 +147,8 @@ export const detectDirective = function (text, type = null) { (type && match[1] && match[1].match(type)) || (type && match[2] && match[2].match(type)) ) { - let type = match[1] ? match[1] : match[2]; - let args = match[3] ? match[3].trim() : match[4] ? JSON.parse(match[4].trim()) : null; + const type = match[1] ? match[1] : match[2]; + const args = match[3] ? match[3].trim() : match[4] ? JSON.parse(match[4].trim()) : null; result.push({ type, args }); } } @@ -165,27 +166,6 @@ export const detectDirective = function (text, type = null) { } }; -/** - * Caches results of functions based on input - * - * @param {Function} fn Function to run - * @param {Function} resolver Function that resolves to an ID given arguments the `fn` takes - * @returns {Function} An optimized caching function - */ -const memoize = (fn, resolver) => { - let cache = {}; - return (...args) => { - let n = resolver ? resolver.apply(this, args) : args[0]; - if (n in cache) { - return cache[n]; - } else { - let result = fn(...args); - cache[n] = result; - return result; - } - }; -}; - /** * @function isSubstringInArray Detects whether a substring in present in a given array * @param {string} str The substring to detect @@ -222,7 +202,7 @@ export const interpolateToCurve = (interpolate, defaultCurve) => { * @returns {string | undefined} The formatted URL */ export const formatUrl = (linkStr, config) => { - let url = linkStr.trim(); + const url = linkStr.trim(); if (url) { if (config.securityLevel !== 'loose') { @@ -327,7 +307,6 @@ const calcLabelPosition = (points) => { const calcCardinalityPosition = (isRelationTypePresent, points, initialPosition) => { let prevPoint; - let totalDistance = 0; log.info('our points', points); if (points[0] !== initialPosition) { points = points.reverse(); @@ -365,10 +344,10 @@ const calcCardinalityPosition = (isRelationTypePresent, points, initialPosition) prevPoint = point; }); // if relation is present (Arrows will be added), change cardinality point off-set distance (d) - let d = isRelationTypePresent ? 10 : 5; + const d = isRelationTypePresent ? 10 : 5; //Calculate Angle for x and y axis - let angle = Math.atan2(points[0].y - center.y, points[0].x - center.x); - let cardinalityPosition = { x: 0, y: 0 }; + const angle = Math.atan2(points[0].y - center.y, points[0].x - center.x); + const cardinalityPosition = { x: 0, y: 0 }; //Calculation cardinality position using angle, center point on the line/curve but pendicular and with offset-distance cardinalityPosition.x = Math.sin(angle) * d + (points[0].x + center.x) / 2; cardinalityPosition.y = -Math.cos(angle) * d + (points[0].y + center.y) / 2; @@ -387,14 +366,12 @@ const calcTerminalLabelPosition = (terminalMarkerSize, position, _points) => { // Todo looking to faster cloning method let points = JSON.parse(JSON.stringify(_points)); let prevPoint; - let totalDistance = 0; log.info('our points', points); if (position !== 'start_left' && position !== 'start_right') { points = points.reverse(); } points.forEach((point) => { - totalDistance += distance(point, prevPoint); prevPoint = point; }); @@ -426,11 +403,11 @@ const calcTerminalLabelPosition = (terminalMarkerSize, position, _points) => { prevPoint = point; }); // if relation is present (Arrows will be added), change cardinality point off-set distance (d) - let d = 10 + terminalMarkerSize * 0.5; + const d = 10 + terminalMarkerSize * 0.5; //Calculate Angle for x and y axis - let angle = Math.atan2(points[0].y - center.y, points[0].x - center.x); + const angle = Math.atan2(points[0].y - center.y, points[0].x - center.x); - let cardinalityPosition = { x: 0, y: 0 }; + const cardinalityPosition = { x: 0, y: 0 }; //Calculation cardinality position using angle, center point on the line/curve but pendicular and with offset-distance @@ -486,10 +463,10 @@ export const generateId = () => { * @returns {any} */ function makeid(length) { - var result = ''; - var characters = '0123456789abcdef'; - var charactersLength = characters.length; - for (var i = 0; i < length; i++) { + let result = ''; + const characters = '0123456789abcdef'; + const charactersLength = characters.length; + for (let i = 0; i < length; i++) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); } return result; @@ -594,7 +571,7 @@ export const wrapLabel = memoize( return completedLines.filter((line) => line !== '').join(config.joinWith); }, (label, maxWidth, config) => - `${label}-${maxWidth}-${config.fontSize}-${config.fontWeight}-${config.fontFamily}-${config.joinWith}` + `${label}${maxWidth}${config.fontSize}${config.fontWeight}${config.fontFamily}${config.joinWith}` ); const breakString = memoize( @@ -622,7 +599,7 @@ const breakString = memoize( return { hyphenatedStrings: lines, remainingWord: currentLine }; }, (word, maxWidth, hyphenCharacter = '-', config) => - `${word}-${maxWidth}-${hyphenCharacter}-${config.fontSize}-${config.fontWeight}-${config.fontFamily}` + `${word}${maxWidth}${hyphenCharacter}${config.fontSize}${config.fontWeight}${config.fontFamily}` ); /** @@ -632,7 +609,8 @@ const breakString = memoize( * If the wrapped text text has greater height, we extend the height, so it's value won't overflow. * * @param {any} text The text to measure - * @param {any} config - The config for fontSize, fontFamily, and fontWeight all impacting the resulting size + * @param {any} config - The config for fontSize, fontFamily, and fontWeight all impacting the + * resulting size * @returns {any} - The height for the given text */ export const calculateTextHeight = function (text, config) { @@ -647,7 +625,8 @@ export const calculateTextHeight = function (text, config) { * This calculates the width of the given text, font size and family. * * @param {any} text - The text to calculate the width of - * @param {any} config - The config for fontSize, fontFamily, and fontWeight all impacting the resulting size + * @param {any} config - The config for fontSize, fontFamily, and fontWeight all impacting the + * resulting size * @returns {any} - The width for the given text */ export const calculateTextWidth = function (text, config) { @@ -656,7 +635,8 @@ export const calculateTextWidth = function (text, config) { }; /** - * This calculates the dimensions of the given text, font size, font family, font weight, and margins. + * This calculates the dimensions of the given text, font size, font family, font weight, and + * margins. * * @param {any} text - The text to calculate the width of * @param {any} config - The config for fontSize, fontFamily, fontWeight, and margin all impacting @@ -676,7 +656,7 @@ export const calculateTextDimensions = memoize( // of sans-serif. const fontFamilies = ['sans-serif', fontFamily]; const lines = text.split(common.lineBreakRegex); - let dims = []; + const dims = []; const body = select('body'); // We don't want to leak DOM elements - if a removal operation isn't available @@ -687,10 +667,10 @@ export const calculateTextDimensions = memoize( const g = body.append('svg'); - for (let fontFamily of fontFamilies) { + for (const fontFamily of fontFamilies) { let cheight = 0; - let dim = { width: 0, height: 0, lineHeight: 0 }; - for (let line of lines) { + const dim = { width: 0, height: 0, lineHeight: 0 }; + for (const line of lines) { const textObj = getTextObj(); textObj.text = line; const textElem = drawSimpleText(g, textObj) @@ -698,7 +678,7 @@ export const calculateTextDimensions = memoize( .style('font-weight', fontWeight) .style('font-family', fontFamily); - let bBox = (textElem._groups || textElem)[0][0].getBBox(); + const bBox = (textElem._groups || textElem)[0][0].getBBox(); dim.width = Math.round(Math.max(dim.width, bBox.width)); cheight = Math.round(bBox.height); dim.height += cheight; @@ -709,7 +689,7 @@ export const calculateTextDimensions = memoize( g.remove(); - let index = + const index = isNaN(dims[1].height) || isNaN(dims[1].width) || isNaN(dims[1].lineHeight) || @@ -720,21 +700,9 @@ export const calculateTextDimensions = memoize( : 1; return dims[index]; }, - (text, config) => `${text}-${config.fontSize}-${config.fontWeight}-${config.fontFamily}` + (text, config) => `${text}${config.fontSize}${config.fontWeight}${config.fontFamily}` ); -/** - * Applys d3 attributes - * - * @param {any} d3Elem D3 Element to apply the attributes onto - * @param {[string, string][]} attrs Object.keys equivalent format of key to value mapping of attributes - */ -const d3Attrs = function (d3Elem, attrs) { - for (let attr of attrs) { - d3Elem.attr(attr[0], attr[1]); - } -}; - export const initIdGenerator = class iterator { constructor(deterministic, seed) { this.deterministic = deterministic; @@ -757,7 +725,7 @@ let decoder; * Decodes HTML, source: {@link https://github.com/shrpne/entity-decode/blob/v2.0.1/browser.js} * * @param {string} html HTML as a string - * @returns Unescaped HTML + * @returns {string} Unescaped HTML */ export const entityDecode = function (html) { decoder = decoder || document.createElement('div'); @@ -860,18 +828,12 @@ export interface DetailedError { hash: any; } -/** - * - * @param error - */ +/** @param error */ export function isDetailedError(error: unknown): error is DetailedError { return 'str' in error; } -/** - * - * @param error - */ +/** @param error */ export function getErrorMessage(error: unknown): string { if (error instanceof Error) return error.message; return String(error); @@ -894,7 +856,6 @@ export default { getStylesFromArray, generateId, random, - memoize, runFunc, entityDecode, initIdGenerator: initIdGenerator, diff --git a/test.js b/test.js deleted file mode 100644 index fa728c6ed..000000000 --- a/test.js +++ /dev/null @@ -1,8 +0,0 @@ -/** - * - */ -function apa() { - // comment's - const a = 1; - return 'apa' + a; -} diff --git a/yarn.lock b/yarn.lock index 23aec9c07..c71948568 100644 --- a/yarn.lock +++ b/yarn.lock @@ -239,10 +239,10 @@ dependencies: "@babel/highlight" "^7.18.6" -"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.18.8": - version "7.18.8" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.18.8.tgz#2483f565faca607b8535590e84e7de323f27764d" - integrity sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ== +"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.18.8", "@babel/compat-data@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.19.0.tgz#2a592fd89bacb1fcde68de31bee4f2f2dacb0e86" + integrity sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw== "@babel/core@7.12.3": version "7.12.3" @@ -266,21 +266,21 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.14.6": - version "7.18.13" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.18.13.tgz#9be8c44512751b05094a4d3ab05fc53a47ce00ac" - integrity sha512-ZisbOvRRusFktksHSG6pjj1CSvkPkcZq/KHD45LAkVP/oiHJkNBZWfpvlLmX8OtHDG8IuzsFlVRWo08w7Qxn0A== +"@babel/core@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.19.0.tgz#d2f5f4f2033c00de8096be3c9f45772563e150c3" + integrity sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ== dependencies: "@ampproject/remapping" "^2.1.0" "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.18.13" - "@babel/helper-compilation-targets" "^7.18.9" - "@babel/helper-module-transforms" "^7.18.9" - "@babel/helpers" "^7.18.9" - "@babel/parser" "^7.18.13" + "@babel/generator" "^7.19.0" + "@babel/helper-compilation-targets" "^7.19.0" + "@babel/helper-module-transforms" "^7.19.0" + "@babel/helpers" "^7.19.0" + "@babel/parser" "^7.19.0" "@babel/template" "^7.18.10" - "@babel/traverse" "^7.18.13" - "@babel/types" "^7.18.13" + "@babel/traverse" "^7.19.0" + "@babel/types" "^7.19.0" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" @@ -305,12 +305,12 @@ jsesc "^2.5.1" source-map "^0.5.0" -"@babel/generator@^7.12.1", "@babel/generator@^7.18.13": - version "7.18.13" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.18.13.tgz#59550cbb9ae79b8def15587bdfbaa388c4abf212" - integrity sha512-CkPg8ySSPuHTYPJYo7IRALdqyjM9HCbt/3uOBEFbzyGVP6Mn8bwFPB0jX6982JVNBlYzM1nnPkfjuXSOPtQeEQ== +"@babel/generator@^7.12.1", "@babel/generator@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.19.0.tgz#785596c06425e59334df2ccee63ab166b738419a" + integrity sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg== dependencies: - "@babel/types" "^7.18.13" + "@babel/types" "^7.19.0" "@jridgewell/gen-mapping" "^0.3.2" jsesc "^2.5.1" @@ -336,12 +336,12 @@ "@babel/helper-explode-assignable-expression" "^7.18.6" "@babel/types" "^7.18.6" -"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz#69e64f57b524cde3e5ff6cc5a9f4a387ee5563bf" - integrity sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg== +"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.0.tgz#537ec8339d53e806ed422f1e06c8f17d55b96bb0" + integrity sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA== dependencies: - "@babel/compat-data" "^7.18.8" + "@babel/compat-data" "^7.19.0" "@babel/helper-validator-option" "^7.18.6" browserslist "^4.20.2" semver "^6.3.0" @@ -380,6 +380,14 @@ "@babel/helper-annotate-as-pure" "^7.18.6" regexpu-core "^5.1.0" +"@babel/helper-create-regexp-features-plugin@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz#7976aca61c0984202baca73d84e2337a5424a41b" + integrity sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + regexpu-core "^5.1.0" + "@babel/helper-define-polyfill-provider@^0.3.2": version "0.3.2" resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.2.tgz#bd10d0aca18e8ce012755395b05a79f45eca5073" @@ -438,6 +446,14 @@ "@babel/template" "^7.18.6" "@babel/types" "^7.18.9" +"@babel/helper-function-name@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" + integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== + dependencies: + "@babel/template" "^7.18.10" + "@babel/types" "^7.19.0" + "@babel/helper-hoist-variables@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" @@ -480,19 +496,19 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz#5a1079c005135ed627442df31a42887e80fcb712" - integrity sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g== +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz#309b230f04e22c58c6a2c0c0c7e50b216d350c30" + integrity sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ== dependencies: "@babel/helper-environment-visitor" "^7.18.9" "@babel/helper-module-imports" "^7.18.6" "@babel/helper-simple-access" "^7.18.6" "@babel/helper-split-export-declaration" "^7.18.6" "@babel/helper-validator-identifier" "^7.18.6" - "@babel/template" "^7.18.6" - "@babel/traverse" "^7.18.9" - "@babel/types" "^7.18.9" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.19.0" + "@babel/types" "^7.19.0" "@babel/helper-optimise-call-expression@^7.16.7": version "7.16.7" @@ -508,10 +524,10 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz#4b8aea3b069d8cb8a72cdfe28ddf5ceca695ef2f" - integrity sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w== +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz#4796bb14961521f0f8715990bee2fb6e51ce21bf" + integrity sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw== "@babel/helper-remap-async-to-generator@^7.18.6": version "7.18.6" @@ -639,14 +655,14 @@ "@babel/traverse" "^7.18.10" "@babel/types" "^7.18.10" -"@babel/helpers@^7.12.1", "@babel/helpers@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.18.9.tgz#4bef3b893f253a1eced04516824ede94dcfe7ff9" - integrity sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ== +"@babel/helpers@^7.12.1", "@babel/helpers@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.19.0.tgz#f30534657faf246ae96551d88dd31e9d1fa1fc18" + integrity sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg== dependencies: - "@babel/template" "^7.18.6" - "@babel/traverse" "^7.18.9" - "@babel/types" "^7.18.9" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.19.0" + "@babel/types" "^7.19.0" "@babel/highlight@^7.18.6": version "7.18.6" @@ -662,10 +678,10 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.3.tgz#a305415ebe7a6c7023b40b5122a0662d928334cd" integrity sha512-kFsOS0IbsuhO5ojF8Hc8z/8vEIOkylVBrjiZUbLTE3XFe0Qi+uu6HjzQixkFaqr0ZPAMZcBVxEwmsnsLPZ2Xsw== -"@babel/parser@^7.10.5", "@babel/parser@^7.12.3", "@babel/parser@^7.18.10", "@babel/parser@^7.18.13": - version "7.18.13" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.13.tgz#5b2dd21cae4a2c5145f1fbd8ca103f9313d3b7e4" - integrity sha512-dgXcIfMuQ0kgzLB2b9tRZs7TTFFaGM2AbtA4fJgUUYukzGH4jwsS7hzQHEGs67jdehpm22vkgKwvbU+aEflgwg== +"@babel/parser@^7.10.5", "@babel/parser@^7.12.3", "@babel/parser@^7.18.10", "@babel/parser@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.0.tgz#497fcafb1d5b61376959c1c338745ef0577aa02c" + integrity sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw== "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": version "7.18.6" @@ -683,13 +699,13 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" "@babel/plugin-proposal-optional-chaining" "^7.18.9" -"@babel/plugin-proposal-async-generator-functions@^7.18.10": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.10.tgz#85ea478c98b0095c3e4102bff3b67d306ed24952" - integrity sha512-1mFuY2TOsR1hxbjCo4QL+qlIjV07p4H4EUYw2J/WCqsvFV6V9X9z9YhXbWndc/4fw+hYGlDT7egYxliMp5O6Ew== +"@babel/plugin-proposal-async-generator-functions@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.19.0.tgz#cf5740194f170467df20581712400487efc79ff1" + integrity sha512-nhEByMUTx3uZueJ/QkJuSlCfN4FGg+xy+vRsfGQGzSauq5ks2Deid2+05Q3KhfaUjvec1IGhw/Zm3cFm8JigTQ== dependencies: "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.19.0" "@babel/helper-remap-async-to-generator" "^7.18.9" "@babel/plugin-syntax-async-generators" "^7.8.4" @@ -1075,16 +1091,17 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.9" -"@babel/plugin-transform-classes@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.9.tgz#90818efc5b9746879b869d5ce83eb2aa48bbc3da" - integrity sha512-EkRQxsxoytpTlKJmSPYrsOMjCILacAjtSVkd4gChEe2kXjFCun3yohhW5I7plXJhCemM0gKsaGMcO8tinvCA5g== +"@babel/plugin-transform-classes@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.19.0.tgz#0e61ec257fba409c41372175e7c1e606dc79bb20" + integrity sha512-YfeEE9kCjqTS9IitkgfJuxjcEtLUHMqa8yUJ6zdz8vR7hKuo6mOy2C05P0F1tdMmDCeuyidKnlrw/iTppHcr2A== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-compilation-targets" "^7.19.0" "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.19.0" "@babel/helper-replace-supers" "^7.18.9" "@babel/helper-split-export-declaration" "^7.18.6" globals "^11.1.0" @@ -1096,10 +1113,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.9" -"@babel/plugin-transform-destructuring@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.9.tgz#68906549c021cb231bee1db21d3b5b095f8ee292" - integrity sha512-p5VCYNddPLkZTq4XymQIaIfZNJwT9YsjkPOhkVEqt6QIpQFZVM9IltqqYpOEkJoN1DPznmxUDyZ5CTZs/ZCuHA== +"@babel/plugin-transform-destructuring@^7.18.13": + version "7.18.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz#9e03bc4a94475d62b7f4114938e6c5c33372cbf5" + integrity sha512-TodpQ29XekIsex2A+YJPj5ax2plkGa8YYY6mFjCohk/IG9IY42Rtuj1FuDeemfg2ipxIFLzPeA83SIBnlhSIow== dependencies: "@babel/helper-plugin-utils" "^7.18.9" @@ -1183,14 +1200,14 @@ "@babel/helper-simple-access" "^7.18.6" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-systemjs@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.9.tgz#545df284a7ac6a05125e3e405e536c5853099a06" - integrity sha512-zY/VSIbbqtoRoJKo2cDTewL364jSlZGvn0LKOf9ntbfxOvjfmyrdtEEOAdswOswhZEb8UH3jDkCKHd1sPgsS0A== +"@babel/plugin-transform-modules-systemjs@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.0.tgz#5f20b471284430f02d9c5059d9b9a16d4b085a1f" + integrity sha512-x9aiR0WXAWmOWsqcsnrzGR+ieaTMVyGyffPVA7F8cXAGt/UxefYv6uSHZLkAFChN5M5Iy1+wjE+xJuPt22H39A== dependencies: "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-module-transforms" "^7.18.9" - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-module-transforms" "^7.19.0" + "@babel/helper-plugin-utils" "^7.19.0" "@babel/helper-validator-identifier" "^7.18.6" babel-plugin-dynamic-import-node "^2.3.3" @@ -1202,13 +1219,13 @@ "@babel/helper-module-transforms" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-named-capturing-groups-regex@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.18.6.tgz#c89bfbc7cc6805d692f3a49bc5fc1b630007246d" - integrity sha512-UmEOGF8XgaIqD74bC8g7iV3RYj8lMf0Bw7NJzvnS9qQhM4mg+1WHKotUIdjxgD2RGrgFLZZPCFPFj3P/kVDYhg== +"@babel/plugin-transform-named-capturing-groups-regex@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.0.tgz#58c52422e4f91a381727faed7d513c89d7f41ada" + integrity sha512-HDSuqOQzkU//kfGdiHBt71/hkDTApw4U/cMVgKgX7PqfB3LOaK+2GtCEsBu1dL9CkswDm0Gwehht1dCr421ULQ== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-create-regexp-features-plugin" "^7.19.0" + "@babel/helper-plugin-utils" "^7.19.0" "@babel/plugin-transform-new-target@^7.18.6": version "7.18.6" @@ -1294,12 +1311,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-spread@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.18.9.tgz#6ea7a6297740f381c540ac56caf75b05b74fb664" - integrity sha512-39Q814wyoOPtIB/qGopNIL9xDChOE1pNU0ZY5dO0owhiVt/5kFm4li+/bBtwc7QotG0u5EPzqhZdjMtmqBqyQA== +"@babel/plugin-transform-spread@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz#dd60b4620c2fec806d60cfaae364ec2188d593b6" + integrity sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.19.0" "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" "@babel/plugin-transform-sticky-regex@^7.18.6": @@ -1338,18 +1355,18 @@ "@babel/helper-create-regexp-features-plugin" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" -"@babel/preset-env@^7.12.1", "@babel/preset-env@^7.14.7": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.18.10.tgz#83b8dfe70d7eea1aae5a10635ab0a5fe60dfc0f4" - integrity sha512-wVxs1yjFdW3Z/XkNfXKoblxoHgbtUF7/l3PvvP4m02Qz9TZ6uZGxRVYjSQeR87oQmHco9zWitW5J82DJ7sCjvA== +"@babel/preset-env@^7.12.1", "@babel/preset-env@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.19.0.tgz#fd18caf499a67d6411b9ded68dc70d01ed1e5da7" + integrity sha512-1YUju1TAFuzjIQqNM9WsF4U6VbD/8t3wEAlw3LFYuuEr+ywqLRcSXxFKz4DCEj+sN94l/XTDiUXYRrsvMpz9WQ== dependencies: - "@babel/compat-data" "^7.18.8" - "@babel/helper-compilation-targets" "^7.18.9" - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/compat-data" "^7.19.0" + "@babel/helper-compilation-targets" "^7.19.0" + "@babel/helper-plugin-utils" "^7.19.0" "@babel/helper-validator-option" "^7.18.6" "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.18.6" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.18.9" - "@babel/plugin-proposal-async-generator-functions" "^7.18.10" + "@babel/plugin-proposal-async-generator-functions" "^7.19.0" "@babel/plugin-proposal-class-properties" "^7.18.6" "@babel/plugin-proposal-class-static-block" "^7.18.6" "@babel/plugin-proposal-dynamic-import" "^7.18.6" @@ -1383,9 +1400,9 @@ "@babel/plugin-transform-async-to-generator" "^7.18.6" "@babel/plugin-transform-block-scoped-functions" "^7.18.6" "@babel/plugin-transform-block-scoping" "^7.18.9" - "@babel/plugin-transform-classes" "^7.18.9" + "@babel/plugin-transform-classes" "^7.19.0" "@babel/plugin-transform-computed-properties" "^7.18.9" - "@babel/plugin-transform-destructuring" "^7.18.9" + "@babel/plugin-transform-destructuring" "^7.18.13" "@babel/plugin-transform-dotall-regex" "^7.18.6" "@babel/plugin-transform-duplicate-keys" "^7.18.9" "@babel/plugin-transform-exponentiation-operator" "^7.18.6" @@ -1395,9 +1412,9 @@ "@babel/plugin-transform-member-expression-literals" "^7.18.6" "@babel/plugin-transform-modules-amd" "^7.18.6" "@babel/plugin-transform-modules-commonjs" "^7.18.6" - "@babel/plugin-transform-modules-systemjs" "^7.18.9" + "@babel/plugin-transform-modules-systemjs" "^7.19.0" "@babel/plugin-transform-modules-umd" "^7.18.6" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.18.6" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.19.0" "@babel/plugin-transform-new-target" "^7.18.6" "@babel/plugin-transform-object-super" "^7.18.6" "@babel/plugin-transform-parameters" "^7.18.8" @@ -1405,14 +1422,14 @@ "@babel/plugin-transform-regenerator" "^7.18.6" "@babel/plugin-transform-reserved-words" "^7.18.6" "@babel/plugin-transform-shorthand-properties" "^7.18.6" - "@babel/plugin-transform-spread" "^7.18.9" + "@babel/plugin-transform-spread" "^7.19.0" "@babel/plugin-transform-sticky-regex" "^7.18.6" "@babel/plugin-transform-template-literals" "^7.18.9" "@babel/plugin-transform-typeof-symbol" "^7.18.9" "@babel/plugin-transform-unicode-escapes" "^7.18.10" "@babel/plugin-transform-unicode-regex" "^7.18.6" "@babel/preset-modules" "^0.1.5" - "@babel/types" "^7.18.10" + "@babel/types" "^7.19.0" babel-plugin-polyfill-corejs2 "^0.3.2" babel-plugin-polyfill-corejs3 "^0.5.3" babel-plugin-polyfill-regenerator "^0.4.0" @@ -1483,26 +1500,26 @@ "@babel/parser" "^7.18.10" "@babel/types" "^7.18.10" -"@babel/traverse@^7.10.5", "@babel/traverse@^7.12.1", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.18.10", "@babel/traverse@^7.18.13", "@babel/traverse@^7.18.6", "@babel/traverse@^7.18.9": - version "7.18.13" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.13.tgz#5ab59ef51a997b3f10c4587d648b9696b6cb1a68" - integrity sha512-N6kt9X1jRMLPxxxPYWi7tgvJRH/rtoU+dbKAPDM44RFHiMH8igdsaSBgFeskhSl/kLWLDUvIh1RXCrTmg0/zvA== +"@babel/traverse@^7.10.5", "@babel/traverse@^7.12.1", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.18.10", "@babel/traverse@^7.18.6", "@babel/traverse@^7.18.9", "@babel/traverse@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.0.tgz#eb9c561c7360005c592cc645abafe0c3c4548eed" + integrity sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA== dependencies: "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.18.13" + "@babel/generator" "^7.19.0" "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" "@babel/helper-hoist-variables" "^7.18.6" "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.18.13" - "@babel/types" "^7.18.13" + "@babel/parser" "^7.19.0" + "@babel/types" "^7.19.0" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.12.1", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0", "@babel/types@^7.18.10", "@babel/types@^7.18.13", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.4.4": - version "7.18.13" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.13.tgz#30aeb9e514f4100f7c1cb6e5ba472b30e48f519a" - integrity sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ== +"@babel/types@^7.12.1", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0", "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.4.4": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.19.0.tgz#75f21d73d73dc0351f3368d28db73465f4814600" + integrity sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA== dependencies: "@babel/helper-string-parser" "^7.18.10" "@babel/helper-validator-identifier" "^7.18.6" @@ -1736,10 +1753,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.15.6.tgz#45be4184f00e505411bc265a05e709764114acd8" integrity sha512-hqmVU2mUjH6J2ZivHphJ/Pdse2ZD+uGCHK0uvsiLDk/JnSedEVj77CiVUnbMKuU4tih1TZZL8tG9DExQg/GZsw== -"@eslint/eslintrc@^1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.1.tgz#de0807bfeffc37b964a7d0400e0c348ce5a2543d" - integrity sha512-OhSY22oQQdw3zgPOOwdoj01l/Dzl1Z+xyUP33tkSN+aqyEhymJCcPHyXt+ylW8FSe0TfRC2VG+ROQOapD0aZSQ== +"@eslint/eslintrc@^1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.2.tgz#58b69582f3b7271d8fa67fe5251767a5b38ea356" + integrity sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ== dependencies: ajv "^6.12.4" debug "^4.3.2" @@ -2273,6 +2290,15 @@ resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== +"@types/jsdom@^20.0.0": + version "20.0.0" + resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-20.0.0.tgz#4414fb629465167f8b7b3804b9e067bdd99f1791" + integrity sha512-YfAchFs0yM1QPDrLm2VHe+WHGtqms3NXnXAMolrgrVP6fgBHHXy1ozAbo/dFtPNtZC/m66bPiCTWYmqp1F14gA== + dependencies: + "@types/node" "*" + "@types/tough-cookie" "*" + parse5 "^7.0.0" + "@types/json-buffer@~3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/json-buffer/-/json-buffer-3.0.0.tgz#85c1ff0f0948fc159810d4b5be35bf8c20875f64" @@ -2290,6 +2316,11 @@ dependencies: "@types/node" "*" +"@types/lodash@^4.14.184": + version "4.14.184" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.184.tgz#23f96cd2a21a28e106dc24d825d4aa966de7a9fe" + integrity sha512-RoZphVtHbxPZizt4IcILciSWiC6dcn+eZ8oX9IWEYfDMcocdd42f7NPI6fQj+6zI8y4E0L7gu2pcZKLGTRaV9Q== + "@types/mdast@^3.0.0": version "3.0.10" resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.10.tgz#4724244a82a4598884cbbe9bcfd73dff927ee8af" @@ -2401,6 +2432,11 @@ resolved "https://registry.yarnpkg.com/@types/stylis/-/stylis-4.0.2.tgz#311c62d68a23dfb01462d54b04549484a4c5cb2a" integrity sha512-wtckGuk1eXUlUz0Qb1eXHG37Z7HWT2GfMdqRf8F/ifddTwadSS9Jwsqi4qtXk7cP7MtoyGVIHPElFCLc6HItbg== +"@types/tough-cookie@*": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.2.tgz#6286b4c7228d58ab7866d19716f3696e03a09397" + integrity sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw== + "@types/trusted-types@*": version "2.0.2" resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.2.tgz#fc25ad9943bcac11cceb8168db4f275e0e72e756" @@ -2425,14 +2461,14 @@ dependencies: "@types/node" "*" -"@typescript-eslint/eslint-plugin@^5.36.1": - version "5.36.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.36.1.tgz#471f64dc53600025e470dad2ca4a9f2864139019" - integrity sha512-iC40UK8q1tMepSDwiLbTbMXKDxzNy+4TfPWgIL661Ym0sD42vRcQU93IsZIrmi+x292DBr60UI/gSwfdVYexCA== +"@typescript-eslint/eslint-plugin@^5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.37.0.tgz#5ccdd5d9004120f28fc6e717fb4b5c9bddcfbc04" + integrity sha512-Fde6W0IafXktz1UlnhGkrrmnnGpAo1kyX7dnyHHVrmwJOn72Oqm3eYtddrpOwwel2W8PAK9F3pIL5S+lfoM0og== dependencies: - "@typescript-eslint/scope-manager" "5.36.1" - "@typescript-eslint/type-utils" "5.36.1" - "@typescript-eslint/utils" "5.36.1" + "@typescript-eslint/scope-manager" "5.37.0" + "@typescript-eslint/type-utils" "5.37.0" + "@typescript-eslint/utils" "5.37.0" debug "^4.3.4" functional-red-black-tree "^1.0.1" ignore "^5.2.0" @@ -2440,130 +2476,84 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/parser@^5.36.1": - version "5.36.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.36.1.tgz#931c22c7bacefd17e29734628cdec8b2acdcf1ce" - integrity sha512-/IsgNGOkBi7CuDfUbwt1eOqUXF9WGVBW9dwEe1pi+L32XrTsZIgmDFIi2RxjzsvB/8i+MIf5JIoTEH8LOZ368A== +"@typescript-eslint/parser@^5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.37.0.tgz#c382077973f3a4ede7453fb14cadcad3970cbf3b" + integrity sha512-01VzI/ipYKuaG5PkE5+qyJ6m02fVALmMPY3Qq5BHflDx3y4VobbLdHQkSMg9VPRS4KdNt4oYTMaomFoHonBGAw== dependencies: - "@typescript-eslint/scope-manager" "5.36.1" - "@typescript-eslint/types" "5.36.1" - "@typescript-eslint/typescript-estree" "5.36.1" + "@typescript-eslint/scope-manager" "5.37.0" + "@typescript-eslint/types" "5.37.0" + "@typescript-eslint/typescript-estree" "5.37.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@5.10.1": - version "5.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.10.1.tgz#f0539c73804d2423506db2475352a4dec36cd809" - integrity sha512-Lyvi559Gvpn94k7+ElXNMEnXu/iundV5uFmCUNnftbFrUbAJ1WBoaGgkbOBm07jVZa682oaBU37ao/NGGX4ZDg== +"@typescript-eslint/scope-manager@5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.37.0.tgz#044980e4f1516a774a418dafe701a483a6c9f9ca" + integrity sha512-F67MqrmSXGd/eZnujjtkPgBQzgespu/iCZ+54Ok9X5tALb9L2v3G+QBSoWkXG0p3lcTJsL+iXz5eLUEdSiJU9Q== dependencies: - "@typescript-eslint/types" "5.10.1" - "@typescript-eslint/visitor-keys" "5.10.1" + "@typescript-eslint/types" "5.37.0" + "@typescript-eslint/visitor-keys" "5.37.0" -"@typescript-eslint/scope-manager@5.36.1": - version "5.36.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.36.1.tgz#23c49b7ddbcffbe09082e6694c2524950766513f" - integrity sha512-pGC2SH3/tXdu9IH3ItoqciD3f3RRGCh7hb9zPdN2Drsr341zgd6VbhP5OHQO/reUqihNltfPpMpTNihFMarP2w== +"@typescript-eslint/type-utils@5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.37.0.tgz#43ed2f567ada49d7e33a6e4b6f9babd060445fe5" + integrity sha512-BSx/O0Z0SXOF5tY0bNTBcDEKz2Ec20GVYvq/H/XNKiUorUFilH7NPbFUuiiyzWaSdN3PA8JV0OvYx0gH/5aFAQ== dependencies: - "@typescript-eslint/types" "5.36.1" - "@typescript-eslint/visitor-keys" "5.36.1" - -"@typescript-eslint/type-utils@5.36.1": - version "5.36.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.36.1.tgz#016fc2bff6679f54c0b2df848a493f0ca3d4f625" - integrity sha512-xfZhfmoQT6m3lmlqDvDzv9TiCYdw22cdj06xY0obSznBsT///GK5IEZQdGliXpAOaRL34o8phEvXzEo/VJx13Q== - dependencies: - "@typescript-eslint/typescript-estree" "5.36.1" - "@typescript-eslint/utils" "5.36.1" + "@typescript-eslint/typescript-estree" "5.37.0" + "@typescript-eslint/utils" "5.37.0" debug "^4.3.4" tsutils "^3.21.0" -"@typescript-eslint/types@5.10.1": - version "5.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.10.1.tgz#dca9bd4cb8c067fc85304a31f38ec4766ba2d1ea" - integrity sha512-ZvxQ2QMy49bIIBpTqFiOenucqUyjTQ0WNLhBM6X1fh1NNlYAC6Kxsx8bRTY3jdYsYg44a0Z/uEgQkohbR0H87Q== +"@typescript-eslint/types@5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.37.0.tgz#09e4870a5f3af7af3f84e08d792644a87d232261" + integrity sha512-3frIJiTa5+tCb2iqR/bf7XwU20lnU05r/sgPJnRpwvfZaqCJBrl8Q/mw9vr3NrNdB/XtVyMA0eppRMMBqdJ1bA== -"@typescript-eslint/types@5.36.1": - version "5.36.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.36.1.tgz#1cf0e28aed1cb3ee676917966eb23c2f8334ce2c" - integrity sha512-jd93ShpsIk1KgBTx9E+hCSEuLCUFwi9V/urhjOWnOaksGZFbTOxAT47OH2d4NLJnLhkVD+wDbB48BuaycZPLBg== - -"@typescript-eslint/typescript-estree@5.10.1": - version "5.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.10.1.tgz#b268e67be0553f8790ba3fe87113282977adda15" - integrity sha512-PwIGnH7jIueXv4opcwEbVGDATjGPO1dx9RkUl5LlHDSe+FXxPwFL5W/qYd5/NHr7f6lo/vvTrAzd0KlQtRusJQ== +"@typescript-eslint/typescript-estree@5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.37.0.tgz#956dcf5c98363bcb97bdd5463a0a86072ff79355" + integrity sha512-JkFoFIt/cx59iqEDSgIGnQpCTRv96MQnXCYvJi7QhBC24uyuzbD8wVbajMB1b9x4I0octYFJ3OwjAwNqk1AjDA== dependencies: - "@typescript-eslint/types" "5.10.1" - "@typescript-eslint/visitor-keys" "5.10.1" - debug "^4.3.2" - globby "^11.0.4" - is-glob "^4.0.3" - semver "^7.3.5" - tsutils "^3.21.0" - -"@typescript-eslint/typescript-estree@5.36.1": - version "5.36.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.36.1.tgz#b857f38d6200f7f3f4c65cd0a5afd5ae723f2adb" - integrity sha512-ih7V52zvHdiX6WcPjsOdmADhYMDN15SylWRZrT2OMy80wzKbc79n8wFW0xpWpU0x3VpBz/oDgTm2xwDAnFTl+g== - dependencies: - "@typescript-eslint/types" "5.36.1" - "@typescript-eslint/visitor-keys" "5.36.1" + "@typescript-eslint/types" "5.37.0" + "@typescript-eslint/visitor-keys" "5.37.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.36.1": - version "5.36.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.36.1.tgz#136d5208cc7a3314b11c646957f8f0b5c01e07ad" - integrity sha512-lNj4FtTiXm5c+u0pUehozaUWhh7UYKnwryku0nxJlYUEWetyG92uw2pr+2Iy4M/u0ONMKzfrx7AsGBTCzORmIg== +"@typescript-eslint/utils@5.37.0", "@typescript-eslint/utils@^5.10.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.37.0.tgz#7784cb8e91390c4f90ccaffd24a0cf9874df81b2" + integrity sha512-jUEJoQrWbZhmikbcWSMDuUSxEE7ID2W/QCV/uz10WtQqfOuKZUqFGjqLJ+qhDd17rjgp+QJPqTdPIBWwoob2NQ== dependencies: "@types/json-schema" "^7.0.9" - "@typescript-eslint/scope-manager" "5.36.1" - "@typescript-eslint/types" "5.36.1" - "@typescript-eslint/typescript-estree" "5.36.1" + "@typescript-eslint/scope-manager" "5.37.0" + "@typescript-eslint/types" "5.37.0" + "@typescript-eslint/typescript-estree" "5.37.0" eslint-scope "^5.1.1" eslint-utils "^3.0.0" -"@typescript-eslint/utils@^5.10.0": - version "5.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.10.1.tgz#fa682a33af47080ba2c4368ee0ad2128213a1196" - integrity sha512-RRmlITiUbLuTRtn/gcPRi4202niF+q7ylFLCKu4c+O/PcpRvZ/nAUwQ2G00bZgpWkhrNLNnvhZLbDn8Ml0qsQw== +"@typescript-eslint/visitor-keys@5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.37.0.tgz#7b72dd343295ea11e89b624995abc7103c554eee" + integrity sha512-Hp7rT4cENBPIzMwrlehLW/28EVCOcE9U1Z1BQTc8EA8v5qpr7GRGuG+U58V5tTY48zvUOA3KHvw3rA8tY9fbdA== dependencies: - "@types/json-schema" "^7.0.9" - "@typescript-eslint/scope-manager" "5.10.1" - "@typescript-eslint/types" "5.10.1" - "@typescript-eslint/typescript-estree" "5.10.1" - eslint-scope "^5.1.1" - eslint-utils "^3.0.0" - -"@typescript-eslint/visitor-keys@5.10.1": - version "5.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.10.1.tgz#29102de692f59d7d34ecc457ed59ab5fc558010b" - integrity sha512-NjQ0Xinhy9IL979tpoTRuLKxMc0zJC7QVSdeerXs2/QvOy2yRkzX5dRb10X5woNUdJgU8G3nYRDlI33sq1K4YQ== - dependencies: - "@typescript-eslint/types" "5.10.1" - eslint-visitor-keys "^3.0.0" - -"@typescript-eslint/visitor-keys@5.36.1": - version "5.36.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.36.1.tgz#7731175312d65738e501780f923896d200ad1615" - integrity sha512-ojB9aRyRFzVMN3b5joSYni6FAS10BBSCAfKJhjJAV08t/a95aM6tAhz+O1jF+EtgxktuSO3wJysp2R+Def/IWQ== - dependencies: - "@typescript-eslint/types" "5.36.1" + "@typescript-eslint/types" "5.37.0" eslint-visitor-keys "^3.3.0" -"@vitest/coverage-c8@^0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@vitest/coverage-c8/-/coverage-c8-0.23.1.tgz#6834f8ec5e35be56c03039276be83fd1580ab68c" - integrity sha512-si3vK1h3BHdoGfb5J2jXstthROHwDW+yqVNGO/NOPG8642+d1RO/jFFvF3OSSYFEsxxcDL0uywEVcXCjGuPYdA== +"@vitest/coverage-c8@^0.23.2": + version "0.23.2" + resolved "https://registry.yarnpkg.com/@vitest/coverage-c8/-/coverage-c8-0.23.2.tgz#48bf6ea81a7ce57abf539361d5a6762e87c36448" + integrity sha512-VWT6zGj9iXEZCimnRLAUhf3siYVGIG9VryyMoo7B8zMOd+bnAbH8/7PhqvmjedVwa9wh61nkxqgG7/3Y/mzofQ== dependencies: c8 "^7.12.0" - vitest "0.23.1" + vitest "0.23.2" -"@vitest/ui@^0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@vitest/ui/-/ui-0.23.1.tgz#de3e95b7cc01137767d64c4a8464f2d586009925" - integrity sha512-W1ygPK4aTyLTPsf6NX3gZFbH0X1ipNzlHhxTRnZ4/HpQXs/qKw5NDY45/U2yC66Fevj5kXHI1tdrNfN00NouFQ== +"@vitest/ui@^0.23.2": + version "0.23.2" + resolved "https://registry.yarnpkg.com/@vitest/ui/-/ui-0.23.2.tgz#0d4a3918edaca6d38f20c49467a03a51d4b26eff" + integrity sha512-dO1UxSwEm11OgumUVbEnF7wKwDPoBGjkrvATvvhkFaDw2iiQm8WewF0hmnUVHj6BSNoHUIJ3uXEzfF9T9W+2yg== dependencies: sirv "^2.0.2" @@ -3495,9 +3485,9 @@ camelcase@^5.0.0, camelcase@^5.3.1: integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== caniuse-lite@^1.0.30001359: - version "1.0.30001390" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001390.tgz" - integrity sha512-sS4CaUM+/+vqQUlCvCJ2WtDlV81aWtHhqeEVkLokVJJa3ViN4zDxAGfq9R8i1m90uGHxo99cy10Od+lvn3hf0g== + version "1.0.30001397" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001397.tgz" + integrity sha512-SW9N2TbCdLf0eiNDRrrQXx2sOkaakNZbCjgNpPyMJJbiOrU5QzMIrXOVMRM1myBXTD5iTkdrtU/EguCrBocHlA== caseless@~0.12.0: version "0.12.0" @@ -3913,13 +3903,13 @@ concat-stream@~1.5.0: readable-stream "~2.0.0" typedarray "~0.0.5" -concurrently@^7.0.0: - version "7.3.0" - resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-7.3.0.tgz#eb45cdbc8df43da195f619aba218a980cae49184" - integrity sha512-IiDwm+8DOcFEInca494A8V402tNTQlJaYq78RF2rijOrKEk/AOHTxhN4U1cp7GYKYX5Q6Ymh1dLTBlzIMN0ikA== +concurrently@^7.4.0: + version "7.4.0" + resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-7.4.0.tgz#bb0e344964bc172673577c420db21e963f2f7368" + integrity sha512-M6AfrueDt/GEna/Vg9BqQ+93yuvzkSKmoTixnwEJkH0LlcGrRC2eCmjeG1tLLHIYfpYJABokqSGyMcXjm96AFA== dependencies: chalk "^4.1.0" - date-fns "^2.16.1" + date-fns "^2.29.1" lodash "^4.17.21" rxjs "^7.0.0" shell-quote "^1.7.3" @@ -4178,7 +4168,7 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" -coveralls@^3.0.2: +coveralls@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.1.1.tgz#f5d4431d8b5ae69c5079c8f8ca00d64ac77cf081" integrity sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww== @@ -4594,10 +4584,10 @@ data-urls@^3.0.1, data-urls@^3.0.2: whatwg-mimetype "^3.0.0" whatwg-url "^11.0.0" -date-fns@^2.16.1: - version "2.27.0" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.27.0.tgz#e1ff3c3ddbbab8a2eaadbb6106be2929a5a2d92b" - integrity sha512-sj+J0Mo2p2X1e306MHq282WS4/A8Pz/95GIFcsPNMPMZVI3EUrAdSv90al1k+p74WGLCruMXk23bfEDZa71X9Q== +date-fns@^2.29.1: + version "2.29.3" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8" + integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA== dateformat@^3.0.0: version "3.0.3" @@ -4963,10 +4953,10 @@ domhandler@^5.0.1, domhandler@^5.0.2: dependencies: domelementtype "^2.3.0" -dompurify@2.3.10: - version "2.3.10" - resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.10.tgz#901f7390ffe16a91a5a556b94043314cd4850385" - integrity sha512-o7Fg/AgC7p/XpKjf/+RC3Ok6k4St5F7Q6q6+Nnm3p2zGWioAY6dh0CbbuwOhH2UcSzKsdniE/YnE2/92JcsA+g== +dompurify@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.4.0.tgz#c9c88390f024c2823332615c9e20a453cf3825dd" + integrity sha512-Be9tbQMZds4a3C6xTmz68NlMfeONA//4dOavl/1rNw50E+/QO0KVpbcU0PcaW0nsQxurXls9ZocqFxk8R2mWEA== domutils@^3.0.1: version "3.0.1" @@ -5463,10 +5453,10 @@ eslint-plugin-html@^7.1.0: dependencies: htmlparser2 "^8.0.1" -eslint-plugin-jest@^27.0.1: - version "27.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.0.1.tgz#3e67ee2051411540988c62075e8788702a1064da" - integrity sha512-LosUsrkwVSs/8Z/I8Hqn5vWgTEsHrfIquDEKOsV8/cl+gbFR4tiRCE1AimEotsHjSC0Rx1tYm6vPhw8C3ktmmg== +eslint-plugin-jest@^27.0.4: + version "27.0.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.0.4.tgz#ab9c7b3f48bfade4762c24c415a5d9bbc0174a61" + integrity sha512-BuvY78pHMpMJ6Cio7sKg6jrqEcnRYPUc4Nlihku4vKx3FjlmMINSX4vcYokZIe+8TKcyr1aI5Kq7vYwgJNdQSA== dependencies: "@typescript-eslint/utils" "^5.10.0" @@ -5526,17 +5516,17 @@ eslint-visitor-keys@^2.0.0, eslint-visitor-keys@^2.1.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== -eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0: +eslint-visitor-keys@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== -eslint@^8.23.0: - version "8.23.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.23.0.tgz#a184918d288820179c6041bb3ddcc99ce6eea040" - integrity sha512-pBG/XOn0MsJcKcTRLr27S5HpzQo4kLr+HjLQIyK4EiCsijDl/TB+h5uEuJU6bQ8Edvwz1XWOjpaP2qgnXGpTcA== +eslint@^8.23.1: + version "8.23.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.23.1.tgz#cfd7b3f7fdd07db8d16b4ac0516a29c8d8dca5dc" + integrity sha512-w7C1IXCc6fNqjpuYd0yPlcTKKmHlHHktRkzmBPZ+7cvNBQuiNjx0xaMTjAJGCafJhQkrFJooREv0CtrVzmHwqg== dependencies: - "@eslint/eslintrc" "^1.3.1" + "@eslint/eslintrc" "^1.3.2" "@humanwhocodes/config-array" "^0.10.4" "@humanwhocodes/gitignore-to-minimatch" "^1.0.2" "@humanwhocodes/module-importer" "^1.0.1" @@ -5555,7 +5545,6 @@ eslint@^8.23.0: fast-deep-equal "^3.1.3" file-entry-cache "^6.0.1" find-up "^5.0.0" - functional-red-black-tree "^1.0.1" glob-parent "^6.0.1" globals "^13.15.0" globby "^11.1.0" @@ -5564,6 +5553,7 @@ eslint@^8.23.0: import-fresh "^3.0.0" imurmurhash "^0.1.4" is-glob "^4.0.0" + js-sdsl "^4.1.4" js-yaml "^4.1.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" @@ -6429,7 +6419,7 @@ globals@^13.15.0: dependencies: type-fest "^0.20.2" -globby@^11.0.4, globby@^11.1.0: +globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== @@ -6511,7 +6501,7 @@ handlebars@^4.7.6: har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== har-validator@~5.1.3: version "5.1.5" @@ -6786,7 +6776,7 @@ http-proxy@^1.18.1: http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== dependencies: assert-plus "^1.0.0" jsprim "^1.2.2" @@ -7406,6 +7396,11 @@ js-base64@3.7.2: resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.2.tgz#816d11d81a8aff241603d19ce5761e13e41d7745" integrity sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ== +js-sdsl@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.1.4.tgz#78793c90f80e8430b7d8dc94515b6c77d98a26a6" + integrity sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw== + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -7653,7 +7648,7 @@ lazystream@^1.0.0: lcov-parse@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-1.0.0.tgz#eb0d46b54111ebc561acb4c408ef9363bdc8f7e0" - integrity sha1-6w1GtUER68VhrLTECO+TY73I9+A= + integrity sha512-aprLII/vPzuQvYZnDRU78Fns9I2Ag3gi4Ipga/hxnVMCZC8DnR2nI7XBqrPoywGfxqIx/DgarGvDJZAD3YBTgQ== lead@^1.0.0: version "1.0.0" @@ -9240,16 +9235,16 @@ prelude-ls@~1.1.2: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= -prettier-plugin-jsdoc@^0.3.30: - version "0.3.38" - resolved "https://registry.yarnpkg.com/prettier-plugin-jsdoc/-/prettier-plugin-jsdoc-0.3.38.tgz#b8adbe9efc1dc11f3cc5ff0b07e0233a0fdf533d" - integrity sha512-h81ZV/nFk5gr3fzWMWzWoz/M/8FneAZxscT7DVSy+5jMIuWYnBFZfSswVKYZyTaZ5r6+6k4hpFTDWhRp85C1tg== +prettier-plugin-jsdoc@^0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/prettier-plugin-jsdoc/-/prettier-plugin-jsdoc-0.4.2.tgz#c5668fc622ed10b87d988279476f96af96b058b7" + integrity sha512-w2jnAQm3z0GAG0bhzVJeehzDtrhGMSxJjit5ApCc2oxWfc7+jmLAkbtdOXaSpfwZz3IWkk+PiQPeRrLNpbM+Mw== dependencies: binary-searching "^2.0.5" comment-parser "^1.3.1" mdast-util-from-markdown "^1.2.0" -prettier@^2.3.2: +prettier@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== @@ -10086,7 +10081,7 @@ semver@7.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@7.3.7, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7: +semver@7.3.7, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.7: version "7.3.7" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== @@ -10476,7 +10471,7 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= -sshpk@^1.14.1, sshpk@^1.7.0: +sshpk@^1.14.1: version "1.16.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== @@ -10491,6 +10486,21 @@ sshpk@^1.14.1, sshpk@^1.7.0: safer-buffer "^2.0.2" tweetnacl "~0.14.0" +sshpk@^1.7.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + ssim.js@^3.1.1: version "3.5.0" resolved "https://registry.yarnpkg.com/ssim.js/-/ssim.js-3.5.0.tgz#d7276b9ee99b57a5ff0db34035f02f35197e62df" @@ -10717,10 +10727,10 @@ strip-literal@^0.4.0: dependencies: acorn "^8.7.1" -stylis@^4.0.10: - version "4.1.1" - resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.1.1.tgz#e46c6a9bbf7c58db1e65bb730be157311ae1fe12" - integrity sha512-lVrM/bNdhVX2OgBFNa2YJ9Lxj7kPzylieHd3TNjuGE0Re9JB7joL5VUKOVH1kdNNJTgGPpT8hmwIAPLaSyEVFQ== +stylis@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.1.2.tgz#870b3c1c2275f51b702bb3da9e94eedad87bba41" + integrity sha512-Nn2CCrG2ZaFziDxaZPN43CXqn+j7tcdjPFCkRBkFue8QYXC2HdEwnw5TCBo4yQZ2WxKYeSi0fdoOrtEqgDrXbA== subarg@^1.0.0: version "1.0.0" @@ -10880,7 +10890,7 @@ tiny-lr@^1.1.0: object-assign "^4.1.0" qs "^6.4.0" -tinybench@^2.1.3: +tinybench@^2.1.3, tinybench@^2.1.5: version "2.1.5" resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.1.5.tgz#6864341415ff0f912ed160cfd90b7f833ece674c" integrity sha512-ak+PZZEuH3mw6CCFOgf5S90YH0MARnZNhxjhjguAmoJimEMAJuNip/rJRd6/wyylHItomVpKTzZk9zrhTrQCoQ== @@ -10890,6 +10900,11 @@ tinypool@^0.2.4: resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-0.2.4.tgz#4d2598c4689d1a2ce267ddf3360a9c6b3925a20c" integrity sha512-Vs3rhkUH6Qq1t5bqtb816oT+HeJTXfwt2cbPH17sWHIYKTotQIFPk3tf2fgqRrVyMDVOc1EnPgzIxfIulXVzwQ== +tinypool@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-0.3.0.tgz#c405d8b743509fc28ea4ca358433190be654f819" + integrity sha512-NX5KeqHOBZU6Bc0xj9Vr5Szbb1j8tUHIeD18s41aDJaPeC5QTdEhK0SpdpUrZlj2nv5cctNcSjaKNanXlfcVEQ== + tinyspy@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-1.0.2.tgz#6da0b3918bfd56170fb3cd3a2b5ef832ee1dff0d" @@ -11148,10 +11163,10 @@ typedarray@^0.0.6, typedarray@~0.0.5: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@^4.6.4, typescript@^4.8.2: - version "4.8.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.2.tgz#e3b33d5ccfb5914e4eeab6699cf208adee3fd790" - integrity sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw== +typescript@^4.6.4, typescript@^4.8.3: + version "4.8.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.3.tgz#d59344522c4bc464a65a730ac695007fdb66dd88" + integrity sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig== uglify-js@^3.1.4: version "3.14.4" @@ -11605,7 +11620,24 @@ vinyl@^2.0.0, vinyl@^2.1.0: optionalDependencies: fsevents "~2.3.2" -vitest@0.23.1, vitest@^0.23.1: +vitest@0.23.2: + version "0.23.2" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-0.23.2.tgz#f978de0f2ada1b7c5ff8dc479ce75b976957ff19" + integrity sha512-kTBKp3ROPDkYC+x2zWt4znkDtnT08W1FQ6ngRFuqxpBGNuNVS+eWZKfffr8y2JGvEzZ9EzMAOcNaiqMj/FZqMw== + dependencies: + "@types/chai" "^4.3.3" + "@types/chai-subset" "^1.3.3" + "@types/node" "*" + chai "^4.3.6" + debug "^4.3.4" + local-pkg "^0.4.2" + strip-literal "^0.4.0" + tinybench "^2.1.5" + tinypool "^0.3.0" + tinyspy "^1.0.2" + vite "^2.9.12 || ^3.0.0-0" + +vitest@^0.23.1: version "0.23.1" resolved "https://registry.yarnpkg.com/vitest/-/vitest-0.23.1.tgz#da3f79a88a6570e4d8c1fe8cf5e2d997be2dc3bd" integrity sha512-kn9pG+h6VA3yj/xRvwgLKEd33rOlzMqJEg3tl5HSm3WUPlkY1Lr1FK8RN1uIqVKvFxmz6HGU3EQW+xW2kazRkQ== @@ -11763,10 +11795,10 @@ webpack-dev-middleware@^5.3.1: range-parser "^1.2.1" schema-utils "^4.0.0" -webpack-dev-server@^4.10.1: - version "4.10.1" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.10.1.tgz#124ac9ac261e75303d74d95ab6712b4aec3e12ed" - integrity sha512-FIzMq3jbBarz3ld9l7rbM7m6Rj1lOsgq/DyLGMX/fPEB1UBUPtf5iL/4eNfhx8YYJTRlzfv107UfWSWcBK5Odw== +webpack-dev-server@^4.11.0: + version "4.11.0" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.11.0.tgz#290ee594765cd8260adfe83b2d18115ea04484e7" + integrity sha512-L5S4Q2zT57SK7tazgzjMiSMBdsw+rGYIX27MgPgx7LDhWO0lViPrHKoLS7jo5In06PWYAhlYu3PbyoC6yAThbw== dependencies: "@types/bonjour" "^3.5.9" "@types/connect-history-api-fallback" "^1.3.5"