diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 8710d49aa..44b16532c 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,4 +1,4 @@ -blank_issues_enabled: false +blank_issues_enabled: true contact_links: - name: GitHub Discussions url: https://github.com/mermaid-js/mermaid/discussions diff --git a/CHANGELOG.md b/CHANGELOG.md index c5903cd91..7552efa3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,105 @@ -# Change Log +# Changelog -// TODO: Populate changelog +## [10.0.0](https://github.com/mermaid-js/mermaid/releases/tag/v10.0.0) + +### Mermaid is ESM only! + +We've dropped CJS support. So, you will have to update your import scripts as follows. + +```html + +``` + +You can keep using v9 by adding the `@9` in the CDN URL. + +```diff +- ++ +``` + +### mermaid.render is async and doesn't accept callbacks + +```js +// < v10 +mermaid.render('id', 'graph TD;\nA-->B', (svg, bindFunctions) => { + element.innerHTML = svg; + if (bindFunctions) { + bindFunctions(element); + } +}); + +// Shorter syntax +if (bindFunctions) { + bindFunctions(element); +} +// can be replaced with the `?.` shorthand +bindFunctions?.(element); + +// >= v10 with async/await +const { svg, bindFunctions } = await mermaid.render('id', 'graph TD;\nA-->B'); +element.innerHTML = svg; +bindFunctions?.(element); + +// >= v10 with promise.then +mermaid.render('id', 'graph TD;A-->B').then(({ svg, bindFunctions }) => { + element.innerHTML = svg; + bindFunctions?.(element); +}); +``` + +### mermaid.parse is async and ParseError is removed + +```js +// < v10 +mermaid.parse(text, parseError); + +//>= v10 +await mermaid.parse(text).catch(parseError); +// or +try { + await mermaid.parse(text); +} catch (err) { + parseError(err); +} +``` + +### Init deprecated and InitThrowsErrors removed + +The config passed to `init` was not being used eariler. +It will now be used. +The `init` function is deprecated and will be removed in the next major release. +init currently works as a wrapper to `initialize` and `run`. + +```js +// < v10 +mermaid.init(config, selector, cb); + +//>= v10 +mermaid.initialize(config); +mermaid.run({ + querySelector: selector, + postRenderCallback: cb, + suppressErrors: true, +}); +``` + +```js +// < v10 +mermaid.initThrowsErrors(config, selector, cb); + +//>= v10 +mermaid.initialize(config); +mermaid.run({ + querySelector: selector, + postRenderCallback: cb, + suppressErrors: false, +}); +``` + +// TODO: Populate changelog pre v10 - Config has a lot of changes - globalReset resets to `defaultConfig` instead of current config. Use `reset` instead. diff --git a/README.md b/README.md index f4cf8e105..d42e2f7e1 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Mermaid Generate diagrams from markdown-like text.
diff --git a/README.zh-CN.md b/README.zh-CN.md index 65cf38645..2653ac72b 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -8,7 +8,7 @@ Mermaid 通过解析类 Markdown 的文本语法来实现图表的创建和动态修改。
diff --git a/V10-BreakingChanges.md b/V10-BreakingChanges.md deleted file mode 100644 index 121fdd596..000000000 --- a/V10-BreakingChanges.md +++ /dev/null @@ -1,58 +0,0 @@ -# A collection of updates that change the behavior - -## Async - -`parse`, `render` are now async. - -## Lazy loading and asynchronisity - -- Invalid dates are rendered as syntax error instead of returning best guess or the current date - -## ParseError is removed - -```js -//< v10.0.0 -mermaid.parse(text, parseError); - -//>= v10.0.0 -await mermaid.parse(text).catch(parseError); -// or -try { - await mermaid.parse(text); -} catch (err) { - parseError(err); -} -``` - -## Init deprecated and InitThrowsErrors removed - -The config passed to `init` was not being used eariler. -It will now be used. -The `init` function is deprecated and will be removed in the next major release. -init currently works as a wrapper to `initialize` and `run`. - -```js -//< v10.0.0 -mermaid.init(config, selector, cb); - -//>= v10.0.0 -mermaid.initialize(config); -mermaid.run({ - querySelector: selector, - postRenderCallback: cb, - suppressErrors: true, -}); -``` - -```js -//< v10.0.0 -mermaid.initThrowsErrors(config, selector, cb); - -//>= v10.0.0 -mermaid.initialize(config); -mermaid.run({ - querySelector: selector, - postRenderCallback: cb, - suppressErrors: false, -}); -``` diff --git a/cSpell.json b/cSpell.json index 6f93af103..1d3eec1b2 100644 --- a/cSpell.json +++ b/cSpell.json @@ -27,6 +27,7 @@ "cuzon", "cytoscape", "dagre", + "deepdwn", "descr", "docsify", "docsy", diff --git a/cypress/integration/rendering/erDiagram.spec.js b/cypress/integration/rendering/erDiagram.spec.js index c72df49b6..df1fac0cd 100644 --- a/cypress/integration/rendering/erDiagram.spec.js +++ b/cypress/integration/rendering/erDiagram.spec.js @@ -188,7 +188,7 @@ describe('Entity Relationship Diagram', () => { erDiagram CLUSTER { varchar(99) name - string(255) description + string(255) description } `, { logLevel: 1 } diff --git a/cypress/integration/rendering/flowchart-v2.spec.js b/cypress/integration/rendering/flowchart-v2.spec.js index 30ae4f0d2..abdb22265 100644 --- a/cypress/integration/rendering/flowchart-v2.spec.js +++ b/cypress/integration/rendering/flowchart-v2.spec.js @@ -670,6 +670,17 @@ title: Simple flowchart --- flowchart TD A --> B +`, + { titleTopMargin: 0 } + ); + }); + it('3192: It should be possieble to render flowcharts with invisible edges', () => { + imgSnapshotTest( + `--- +title: Simple flowchart with invisible edges +--- +flowchart TD +A ~~~ B `, { titleTopMargin: 0 } ); diff --git a/cypress/integration/rendering/sequencediagram.spec.js b/cypress/integration/rendering/sequencediagram.spec.js index 1f063c13e..f8948240a 100644 --- a/cypress/integration/rendering/sequencediagram.spec.js +++ b/cypress/integration/rendering/sequencediagram.spec.js @@ -116,7 +116,11 @@ context('Sequence diagram', () => { loop Loopy Bob->>Alice: Pasten end `, - { wrap: true } + { + sequence: { + wrap: true, + }, + } ); }); context('font settings', () => { diff --git a/cypress/platform/flow2.html b/cypress/platform/flow2.html new file mode 100644 index 000000000..b23f00be6 --- /dev/null +++ b/cypress/platform/flow2.html @@ -0,0 +1,46 @@ + +
+ + + + ++ graph TB + subgraph One + a1-->a2-->a3 + end ++
+ graph TB + a_a --> b_b:::apa --> c_c:::apa + classDef apa fill:#f9f,stroke:#333,stroke-width:4px; + class a_a apa; ++
+ graph TB + a_a(Aftonbladet) --> b_b[gorilla]:::apa --> c_c{chimp}:::apa -->a_a + a_a --> c --> d_d --> c_c + classDef apa fill:#f9f,stroke:#333,stroke-width:4px; + class a_a apa; + click a_a "http://www.aftonbladet.se" "apa" ++ + + + diff --git a/cypress/platform/viewer.js b/cypress/platform/viewer.js index 07fe4d673..e3ea71da3 100644 --- a/cypress/platform/viewer.js +++ b/cypress/platform/viewer.js @@ -46,7 +46,7 @@ const contentLoaded = async function () { await mermaid2.registerExternalDiagrams([externalExample]); mermaid2.initialize(graphObj.mermaid); - await mermaid2.init(); + await mermaid2.run(); markRendered(); } }; diff --git a/demos/journey.html b/demos/journey.html index 40fa5d390..b0131ea3f 100644 --- a/demos/journey.html +++ b/demos/journey.html @@ -17,7 +17,7 @@
--- - title: My working day + title: My working day --- journey accTitle: Very simple journey demo diff --git a/docs/config/setup/interfaces/mermaidAPI.RenderResult.md b/docs/config/setup/interfaces/mermaidAPI.RenderResult.md index de4f763a0..ec59f8796 100644 --- a/docs/config/setup/interfaces/mermaidAPI.RenderResult.md +++ b/docs/config/setup/interfaces/mermaidAPI.RenderResult.md @@ -8,41 +8,6 @@ [mermaidAPI](../modules/mermaidAPI.md).RenderResult -Function that renders an svg with a graph from a chart definition. Usage example below. - -```javascript -mermaidAPI.initialize({ - startOnLoad: true, -}); -$(function () { - const graphDefinition = 'graph TB\na-->b'; - const cb = function (svgGraph) { - console.log(svgGraph); - }; - mermaidAPI.render('id1', graphDefinition, cb); -}); -``` - -**`Param`** - -The id for the SVG element (the element to be rendered) - -**`Param`** - -The text for the graph definition - -**`Param`** - -Callback which is called after rendering is finished with the svg code as in param. - -**`Param`** - -HTML element where the svg will be inserted. (Is usually element with the .mermaid class) -If no svgContainingElement is provided then the SVG element will be appended to the body. -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. - ## Properties ### bindFunctions @@ -53,6 +18,15 @@ element will be removed when rendering is completed. ▸ (`element`): `void` +Bind function to be called after the svg has been inserted into the DOM. +This is necessary for adding event listeners to the elements in the svg. + +```js +const { svg, bindFunctions } = mermaidAPI.render('id1', 'graph TD;A-->B'); +div.innerHTML = svg; +bindFunctions?.(div); // To call bindFunctions only if it's present. +``` + ##### Parameters | Name | Type | @@ -65,7 +39,7 @@ element will be removed when rendering is completed. #### Defined in -[mermaidAPI.ts:384](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L384) +[mermaidAPI.ts:91](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L91) --- @@ -73,6 +47,8 @@ element will be removed when rendering is completed. • **svg**: `string` +The svg code for the rendered graph. + #### Defined in -[mermaidAPI.ts:383](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L383) +[mermaidAPI.ts:81](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L81) diff --git a/docs/config/setup/modules/mermaidAPI.md b/docs/config/setup/modules/mermaidAPI.md index aa0885707..0406baa81 100644 --- a/docs/config/setup/modules/mermaidAPI.md +++ b/docs/config/setup/modules/mermaidAPI.md @@ -95,7 +95,7 @@ mermaid.initialize(config); #### Defined in -[mermaidAPI.ts:668](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L668) +[mermaidAPI.ts:680](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L680) ## Functions @@ -126,7 +126,7 @@ Return the last node appended #### Defined in -[mermaidAPI.ts:291](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L291) +[mermaidAPI.ts:308](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L308) --- @@ -152,7 +152,7 @@ the cleaned up svgCode #### Defined in -[mermaidAPI.ts:242](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L242) +[mermaidAPI.ts:259](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L259) --- @@ -178,7 +178,7 @@ the string with all the user styles #### Defined in -[mermaidAPI.ts:171](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L171) +[mermaidAPI.ts:188](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L188) --- @@ -201,7 +201,7 @@ the string with all the user styles #### Defined in -[mermaidAPI.ts:219](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L219) +[mermaidAPI.ts:236](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L236) --- @@ -228,7 +228,7 @@ with an enclosing block that has each of the cssClasses followed by !important; #### Defined in -[mermaidAPI.ts:155](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L155) +[mermaidAPI.ts:172](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L172) --- @@ -248,7 +248,7 @@ with an enclosing block that has each of the cssClasses followed by !important; #### Defined in -[mermaidAPI.ts:135](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L135) +[mermaidAPI.ts:152](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L152) --- @@ -268,7 +268,7 @@ with an enclosing block that has each of the cssClasses followed by !important; #### Defined in -[mermaidAPI.ts:106](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L106) +[mermaidAPI.ts:123](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L123) --- @@ -294,7 +294,7 @@ Put the svgCode into an iFrame. Return the iFrame code #### Defined in -[mermaidAPI.ts:270](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L270) +[mermaidAPI.ts:287](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L287) --- @@ -319,4 +319,4 @@ Remove any existing elements from the given document #### Defined in -[mermaidAPI.ts:341](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L341) +[mermaidAPI.ts:358](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L358) diff --git a/docs/config/usage.md b/docs/config/usage.md index 866dd6be7..190ef2197 100644 --- a/docs/config/usage.md +++ b/docs/config/usage.md @@ -20,21 +20,24 @@ Please note that you can switch versions through the dropdown box at the top rig For the majority of users, Using the [Live Editor](https://mermaid.live/) would be sufficient, however you may also opt to deploy mermaid as a dependency or using the [Mermaid API](./setup/README.md). -We have compiled some Video [Tutorials](./Tutorials.md) on how to use the mermaid Live Editor. +We have compiled some Video [Tutorials](./Tutorials.md) on how to use the Mermaid Live Editor. ### Installing and Hosting Mermaid on a Webpage **Using the npm package:** -1. You will need to install `node v16`, which would have npm. +Requirements: -2. Download `yarn` using npm. +- Node >= 16 -3. Enter the following command: `yarn add mermaid`. - -4. At this point, you can add mermaid as a dev dependency using this command: `yarn add --dev mermaid`. - -5. Alternatively, you can also deploy mermaid using the script tag in an HTML file with mermaid diagram descriptions as is shown in the example below. +```bash +# NPM +npm install mermaid +# Yarn +yarn add mermaid +# PNPM +pnpm add mermaid +``` **Hosting mermaid on a web page:** @@ -42,7 +45,9 @@ We have compiled some Video [Tutorials](./Tutorials.md) on how to use the mermai The easiest way to integrate mermaid on a web page requires two elements: -- A graph definition, inside `` tags labeled `class=mermaid`. Example: +- A graph definition, inside `` tags labeled `class=mermaid`. + +Example: ```html@@ -53,14 +58,13 @@ The easiest way to integrate mermaid on a web page requires two elements:``` -- Inclusion of the mermaid address in the html page body using a `script` tag as an ESM import, and the `mermaidAPI` call. +- The mermaid js script. Added using a `script` tag as an ESM import. Example: ```html ``` @@ -71,9 +75,6 @@ Example: ```html - - -graph LR @@ -83,7 +84,6 @@ Example:@@ -95,11 +95,12 @@ An id attribute is also added to mermaid tags without one. Mermaid can load multiple diagrams, in the same page. -> Try it out, save this code as HTML and load it using any browser.(Except Internet Explorer, please don't use Internet Explorer.) +> Try it out, save this code as HTML and load it using any browser. +> (Except Internet Explorer, please don't use Internet Explorer.) ## Enabling Click Event and Tags in Nodes -A `securityLevel` configuration has to first be cleared, `securityLevel` sets the level of trust for the parsed diagrams and limits click functionality. This was introduce in version 8.2 as a security improvement, aimed at preventing malicious use. +A `securityLevel` configuration has to first be cleared. `securityLevel` sets the level of trust for the parsed diagrams and limits click functionality. This was introduce in version 8.2 as a security improvement, aimed at preventing malicious use. **It is the site owner's responsibility to discriminate between trustworthy and untrustworthy user-bases and we encourage the use of discretion.** @@ -107,7 +108,7 @@ A `securityLevel` configuration has to first be cleared, `securityLevel` sets th | Parameter | Description | Type | Required | Values | | ------------- | --------------------------------- | ------ | -------- | ------------------------------------------ | -| securityLevel | Level of trust for parsed diagram | String | Required | 'sandbox', 'strict', 'loose', 'antiscript' | +| securityLevel | Level of trust for parsed diagram | String | Optional | 'sandbox', 'strict', 'loose', 'antiscript' | Values: @@ -122,26 +123,17 @@ Values: **If you are taking responsibility for the diagram source security you can set the `securityLevel` to a value of your choosing . This allows clicks and tags are allowed.** -**To change `securityLevel`, you have to call `mermaidAPI.initialize`:** +**To change `securityLevel`, you have to call `mermaid.initialize`:** ```javascript -mermaidAPI.initialize({ +mermaid.initialize({ securityLevel: 'loose', }); ``` ### Labels out of bounds -If you use dynamically loaded fonts that are loaded through CSS, such as Google fonts, mermaid should wait for the -whole page to load (dom + assets, particularly the fonts file). - -```javascript -$(document).load(function () { - mermaid.initialize(); -}); -``` - -or +If you use dynamically loaded fonts that are loaded through CSS, such as fonts, mermaid should wait for the whole page to load (dom + assets, particularly the fonts file). ```javascript $(document).ready(function () { @@ -154,12 +146,54 @@ Not doing so will most likely result in mermaid rendering graphs that have label If your page has other fonts in its body those might be used instead of the mermaid font. Specifying the font in your styling is a workaround for this. ```css -div.mermaid { +pre.mermaid { font-family: 'trebuchet ms', verdana, arial; } ``` -### Calling `mermaid.init` +### Using `mermaid.run` + +mermaid.run was added in v10 and is the preferred way of handling more complex integration. +By default, `mermaid.run` will be called when the document is ready, rendering all elements with `class="mermaid"`. + +You can customize that behavior by calling `await mermaid.run()`. + +`mermaid.initialize({startOnLoad: false})` will prevent `mermaid.run` from being called automatically after load. + +Render all elements with querySelector ".someOtherClass" + +```js +mermaid.initialize({ startOnLoad: false }); +await mermaid.run({ + querySelector: '.someOtherClass', +}); +``` + +Render all elements passed as an array + +```js +mermaid.initialize({ startOnLoad: false }); +await mermaid.run({ + nodes: [document.getElementById('someId'), document.getElementById('anotherId')], +}); +await mermaid.run({ + nodes: document.querySelectorAll('.yetAnotherClass'), +}); +``` + +Render all `.mermaid` elements while suppressing any error + +```js +mermaid.initialize({ startOnLoad: false }); +await mermaid.run({ + suppressErrors: true, +}); +``` + +### Calling `mermaid.init` - Deprecated + +> **Warning** +> mermaid.init is deprecated in v10 and will be removed in v11. Please use mermaid.run instead. By default, `mermaid.init` will be called when the document is ready, finding all elements with `class="mermaid"`. If you are adding content after mermaid is loaded, or otherwise need @@ -192,25 +226,24 @@ mermaid fully supports webpack. Here is a [working demo](https://github.com/merm ## API usage -The main idea of the API is to be able to call a render function with the graph definition as a string. The render function -will render the graph and call a callback with the resulting SVG code. With this approach it is up to the site creator to -fetch the graph definition from the site (perhaps from a textarea), render it and place the graph somewhere in the site. +The main idea of the API is to be able to call a render function with the graph definition as a string. The render function will render the graph and call a callback with the resulting SVG code. With this approach it is up to the site creator to fetch the graph definition from the site (perhaps from a textarea), render it and place the graph somewhere in the site. The example below show an outline of how this could be used. The example just logs the resulting SVG to the JavaScript console. ```html ``` @@ -223,17 +256,17 @@ The example code below is an extract of what mermaid does when using the API. Th bind events to an SVG when using the API for rendering. ```javascript -const insertSvg = function (svgCode, bindFunctions) { - element.innerHTML = svgCode; - if (typeof callback !== 'undefined') { - callback(id); +// Example of using the bindFunctions +const drawDiagram = async function () { + element = document.querySelector('#graphDiv'); + const graphDefinition = 'graph TB\na-->b'; + const { svg, bindFunctions } = await mermaid.render('graphDiv', graphDefinition); + element.innerHTML = svg; + // This can also be written as `bindFunctions?.(element);` using the `?` shorthand. + if (bindFunctions) { + bindFunctions(element); } - bindFunctions(element); }; - -const id = 'theGraph'; - -mermaidAPI.render(id, txt, insertSvg, element); ``` 1. The graph is generated using the render call. diff --git a/docs/ecosystem/integrations.md b/docs/ecosystem/integrations.md index 33b6b966e..3db4a17bc 100644 --- a/docs/ecosystem/integrations.md +++ b/docs/ecosystem/integrations.md @@ -20,6 +20,7 @@ They also serve as proof of concept, for the variety of things that can be built - [Gitea](https://gitea.io) (**Native support**) - [Azure Devops](https://docs.microsoft.com/en-us/azure/devops/project/wiki/wiki-markdown-guidance?view=azure-devops#add-mermaid-diagrams-to-a-wiki-page) (**Native support**) - [Tuleap](https://docs.tuleap.org/user-guide/writing-in-tuleap.html#graphs) (**Native support**) +- [Deepdwn](https://billiam.itch.io/deepdwn) (**Native support**) - [Joplin](https://joplinapp.org) (**Native support**) - [Swimm](https://swimm.io) (**Native support**) - [Notion](https://notion.so) (**Native support**) @@ -188,3 +189,6 @@ They also serve as proof of concept, for the variety of things that can be built - [mermaid-server: Generate diagrams using a HTTP request](https://github.com/TomWright/mermaid-server) - [ExDoc](https://github.com/elixir-lang/ex_doc) - [Rendering Mermaid graphs](https://github.com/elixir-lang/ex_doc#rendering-mermaid-graphs) +- [NiceGUI: Let any browser be the frontend of your Python code](https://nicegui.io) + - [ui.mermaid(...)](https://nicegui.io/reference#mermaid_diagrams) + - [ui.markdown(..., extras=\['mermaid'\])](https://nicegui.io/reference#markdown_element) diff --git a/docs/intro/n00b-gettingStarted.md b/docs/intro/n00b-gettingStarted.md index 87592ba27..f4fb69b90 100644 --- a/docs/intro/n00b-gettingStarted.md +++ b/docs/intro/n00b-gettingStarted.md @@ -103,7 +103,7 @@ When writing the .html file, we give two instructions inside the html code to th a. The mermaid code for the diagram we want to create. -b. The importing of mermaid library through the `mermaid.esm.js` or `mermaid.esm.min.mjs` and the `mermaid.initialize()` call, which dictates the appearance of diagrams and also starts the rendering process . +b. The importing of mermaid library through the `mermaid.esm.mjs` or `mermaid.esm.min.mjs` and the `mermaid.initialize()` call, which dictates the appearance of diagrams and also starts the rendering process . **a. The embedded mermaid diagram definition inside a ` `:** @@ -135,7 +135,7 @@ b. The importing of mermaid library through the `mermaid.esm.js` or `mermaid.esm ``` **Notes**: -Rendering in Mermaid is initialized by `mermaid.initialize()` call. You can place `mermaid.initialize()` inside `mermaid.esm.min.mjs` for brevity. However, doing the opposite lets you control when it starts looking for ``tags inside the web page with `mermaid.initialize()`. This is useful when you think that not all `` tags may have loaded on the execution of `mermaid.esm.min.mjs` file. +Rendering in Mermaid is initialized by `mermaid.initialize()` call. However, doing the opposite lets you control when it starts looking for `` tags inside the web page with `mermaid.initialize()`. This is useful when you think that not all `` tags may have loaded on the execution of `mermaid.esm.min.mjs` file. `startOnLoad` is one of the parameters that can be defined by `mermaid.initialize()` @@ -143,10 +143,6 @@ Rendering in Mermaid is initialized by `mermaid.initialize()` call. You can plac | ----------- | --------------------------------- | ------- | ----------- | | startOnLoad | Toggle for Rendering upon loading | Boolean | true, false | -### Adding external diagrams to mermaid - -Please refer to the [Mindmap](../syntax/mindmap.md?id=integrating-with-your-librarywebsite) section for more information. - ### Working Examples **Here is a full working example of the mermaidAPI being called through the CDN:** diff --git a/docs/syntax/flowchart.md b/docs/syntax/flowchart.md index fd0408c45..547847f54 100644 --- a/docs/syntax/flowchart.md +++ b/docs/syntax/flowchart.md @@ -391,6 +391,20 @@ flowchart LR A == text ==> B ``` +### An invisible link + +This can be a useful tool in some instances where you want to alter the default positioning of a node. + +```mermaid-example +flowchart LR + A ~~~ B +``` + +```mermaid +flowchart LR + A ~~~ B +``` + ### Chaining of links It is possible declare many links in the same line as per below: diff --git a/packages/mermaid/package.json b/packages/mermaid/package.json index c278821ab..0593814e1 100644 --- a/packages/mermaid/package.json +++ b/packages/mermaid/package.json @@ -1,14 +1,14 @@ { "name": "mermaid", - "version": "10.0.0-rc.4", + "version": "10.0.1-rc.1", "description": "Markdown-ish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.", "type": "module", "module": "./dist/mermaid.core.mjs", "types": "./dist/mermaid.d.ts", "exports": { ".": { - "import": "./dist/mermaid.core.mjs", - "types": "./dist/mermaid.d.ts" + "types": "./dist/mermaid.d.ts", + "import": "./dist/mermaid.core.mjs" }, "./*": "./*" }, diff --git a/packages/mermaid/src/Diagram.ts b/packages/mermaid/src/Diagram.ts index fc1f7e8f0..1e7539aeb 100644 --- a/packages/mermaid/src/Diagram.ts +++ b/packages/mermaid/src/Diagram.ts @@ -68,8 +68,8 @@ export class Diagram { } } -export const getDiagramFromText = async (txt: string): Promise=> { - const type = detectType(txt, configApi.getConfig()); +export const getDiagramFromText = async (text: string): Promise => { + const type = detectType(text, configApi.getConfig()); try { // Trying to find the diagram getDiagram(type); @@ -83,5 +83,5 @@ export const getDiagramFromText = async (txt: string): Promise => { const { id, diagram } = await loader(); registerDiagram(id, diagram); } - return new Diagram(txt); + return new Diagram(text); }; diff --git a/packages/mermaid/src/config.ts b/packages/mermaid/src/config.ts index 8750c8fa5..bc0066cec 100644 --- a/packages/mermaid/src/config.ts +++ b/packages/mermaid/src/config.ts @@ -243,6 +243,7 @@ const checkConfig = (config: MermaidConfig) => { if (!config) { return; } + // @ts-expect-error Properties were removed in v10. Warning should exist. if (config.lazyLoadedDiagrams || config.loadExternalDiagramsAtStartup) { issueWarning('LAZY_LOAD_DEPRECATED'); } diff --git a/packages/mermaid/src/config.type.ts b/packages/mermaid/src/config.type.ts index 474075824..c835ee440 100644 --- a/packages/mermaid/src/config.type.ts +++ b/packages/mermaid/src/config.type.ts @@ -3,10 +3,6 @@ import DOMPurify from 'dompurify'; export interface MermaidConfig { - /** @deprecated use mermaid.registerLazyDiagrams instead */ - lazyLoadedDiagrams?: string[]; - /** @deprecated use mermaid.registerLazyDiagrams instead */ - loadExternalDiagramsAtStartup?: boolean; theme?: string; themeVariables?: any; themeCSS?: string; diff --git a/packages/mermaid/src/dagre-wrapper/edges.js b/packages/mermaid/src/dagre-wrapper/edges.js index 71183eab5..f8c113694 100644 --- a/packages/mermaid/src/dagre-wrapper/edges.js +++ b/packages/mermaid/src/dagre-wrapper/edges.js @@ -453,6 +453,9 @@ export const insertEdge = function (elem, e, edge, clusterDb, diagramType, graph case 'thick': strokeClasses = 'edge-thickness-thick'; break; + case 'invisible': + strokeClasses = 'edge-thickness-thick'; + break; default: strokeClasses = ''; } diff --git a/packages/mermaid/src/diagram-api/detectType.ts b/packages/mermaid/src/diagram-api/detectType.ts index 3c9237e5b..6ffe5df85 100644 --- a/packages/mermaid/src/diagram-api/detectType.ts +++ b/packages/mermaid/src/diagram-api/detectType.ts @@ -7,6 +7,7 @@ import type { ExternalDiagramDefinition, } from './types'; import { frontMatterRegex } from './frontmatter'; +import { getDiagram, registerDiagram } from './diagramAPI'; import { UnknownDiagramError } from '../errors'; const directive = /%{2}{\s*(?:(\w+)\s*:|(\w+))\s*(?:(\w+)|((?:(?!}%{2}).|\r?\n)*))?\s*(?:}%{2})?/gi; @@ -54,6 +55,39 @@ export const registerLazyLoadedDiagrams = (...diagrams: ExternalDiagramDefinitio } }; +export const loadRegisteredDiagrams = async () => { + log.debug(`Loading registered diagrams`); + // Load all lazy loaded diagrams in parallel + const results = await Promise.allSettled( + Object.entries(detectors).map(async ([key, { detector, loader }]) => { + if (loader) { + try { + getDiagram(key); + } catch (error) { + try { + // Register diagram if it is not already registered + const { diagram, id } = await loader(); + registerDiagram(id, diagram, detector); + } catch (err) { + // Remove failed diagram from detectors + log.error(`Failed to load external diagram with key ${key}. Removing from detectors.`); + delete detectors[key]; + throw err; + } + } + } + }) + ); + const failed = results.filter((result) => result.status === 'rejected'); + if (failed.length > 0) { + log.error(`Failed to load ${failed.length} external diagrams`); + for (const res of failed) { + log.error(res); + } + throw new Error(`Failed to load ${failed.length} external diagrams`); + } +}; + export const addDetector = (key: string, detector: DiagramDetector, loader?: DiagramLoader) => { if (detectors[key]) { log.error(`Detector with key ${key} already exists`); diff --git a/packages/mermaid/src/diagram-api/diagram-orchestration.ts b/packages/mermaid/src/diagram-api/diagram-orchestration.ts index a68e99dd0..d06ce846a 100644 --- a/packages/mermaid/src/diagram-api/diagram-orchestration.ts +++ b/packages/mermaid/src/diagram-api/diagram-orchestration.ts @@ -1,104 +1,24 @@ -import { registerDiagram } from './diagramAPI'; -// @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 { setConfig } from '../config'; - -import errorRenderer from '../diagrams/error/errorRenderer'; -import errorStyles from '../diagrams/error/styles'; - +import c4 from '../diagrams/c4/c4Detector'; +import flowchart from '../diagrams/flowchart/flowDetector'; +import flowchartV2 from '../diagrams/flowchart/flowDetector-v2'; +import er from '../diagrams/er/erDetector'; +import git from '../diagrams/git/gitGraphDetector'; +import gantt from '../diagrams/gantt/ganttDetector'; +import info from '../diagrams/info/infoDetector'; +import pie from '../diagrams/pie/pieDetector'; +import requirement from '../diagrams/requirement/requirementDetector'; +import sequence from '../diagrams/sequence/sequenceDetector'; +import classDiagram from '../diagrams/class/classDetector'; +import classDiagramV2 from '../diagrams/class/classDetector-V2'; +import state from '../diagrams/state/stateDetector'; +import stateV2 from '../diagrams/state/stateDetector-V2'; +import journey from '../diagrams/user-journey/journeyDetector'; +import error from '../diagrams/error/errorDetector'; import flowchartElk from '../diagrams/flowchart/elk/detector'; +import timeline from '../diagrams/timeline/detector'; +import mindmap from '../diagrams/mindmap/detector'; import { registerLazyLoadedDiagrams } from './detectType'; - -// Lazy loaded diagrams -import timelineDetector from '../diagrams/timeline/detector'; -import mindmapDetector from '../diagrams/mindmap/detector'; +import { registerDiagram } from './diagramAPI'; let hasLoadedDiagrams = false; export const addDiagrams = () => { @@ -108,31 +28,6 @@ export const addDiagrams = () => { // This is added here to avoid race-conditions. // We could optimize the loading logic somehow. hasLoadedDiagrams = true; - registerLazyLoadedDiagrams(flowchartElk, timelineDetector, mindmapDetector); - - 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( '---', // --- diagram type may appear if YAML front-matter is not parsed correctly @@ -142,8 +37,8 @@ export const addDiagrams = () => { // Quite ok, clear needs to be there for --- to work as a regular diagram }, }, - styles: errorStyles, // should never be used - renderer: errorRenderer, // should never be used + styles: {}, // should never be used + renderer: {}, // should never be used parser: { parser: { yy: {} }, parse: () => { @@ -160,220 +55,25 @@ export const addDiagrams = () => { return text.toLowerCase().trimStart().startsWith('---'); } ); - - 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) => { - if (!cnf.flowchart) { - cnf.flowchart = {}; - } - // TODO, broken as of 2022-09-14 (13809b50251845475e6dca65cc395761be38fbd2) - cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - flowRenderer.setConf(cnf.flowchart); - flowDb.clear(); - flowDb.setGen('gen-1'); - }, - }, - flowDetector - ); - registerDiagram( - 'flowchart-v2', - { - parser: flowParser, - db: flowDb, - renderer: flowRendererV2, - styles: flowStyles, - init: (cnf) => { - if (!cnf.flowchart) { - cnf.flowchart = {}; - } - cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - // flowchart-v2 uses dagre-wrapper, which doesn't have access to flowchart cnf - setConfig({ flowchart: { arrowMarkerAbsolute: cnf.arrowMarkerAbsolute } }); - flowRendererV2.setConf(cnf.flowchart); - flowDb.clear(); - flowDb.setGen('gen-2'); - }, - }, - flowDetectorV2 - ); - registerDiagram( - 'gitGraph', - { parser: gitGraphParser, db: gitGraphDb, renderer: gitGraphRenderer, styles: gitGraphStyles }, - gitGraphDetector + registerLazyLoadedDiagrams( + error, + c4, + classDiagram, + classDiagramV2, + er, + gantt, + info, + pie, + requirement, + sequence, + flowchart, + flowchartV2, + flowchartElk, + mindmap, + timeline, + git, + state, + stateV2, + journey ); }; diff --git a/packages/mermaid/src/diagram-api/diagramAPI.spec.ts b/packages/mermaid/src/diagram-api/diagramAPI.spec.ts index ea546fbb6..9e04c861f 100644 --- a/packages/mermaid/src/diagram-api/diagramAPI.spec.ts +++ b/packages/mermaid/src/diagram-api/diagramAPI.spec.ts @@ -2,8 +2,12 @@ import { detectType } from './detectType'; import { getDiagram, registerDiagram } from './diagramAPI'; import { addDiagrams } from './diagram-orchestration'; import { DiagramDetector } from './types'; +import { getDiagramFromText } from '../Diagram'; addDiagrams(); +beforeAll(async () => { + await getDiagramFromText('sequenceDiagram'); +}); describe('DiagramAPI', () => { it('should return default diagrams', () => { diff --git a/packages/mermaid/src/diagram-api/diagramAPI.ts b/packages/mermaid/src/diagram-api/diagramAPI.ts index 936e43efd..c5841b96b 100644 --- a/packages/mermaid/src/diagram-api/diagramAPI.ts +++ b/packages/mermaid/src/diagram-api/diagramAPI.ts @@ -71,3 +71,9 @@ export const getDiagram = (name: string): DiagramDefinition => { } throw new Error(`Diagram ${name} not found.`); }; + +export class DiagramNotFoundError extends Error { + constructor(message: string) { + super(`Diagram ${message} not found.`); + } +} diff --git a/packages/mermaid/src/diagrams/c4/c4Detector.ts b/packages/mermaid/src/diagrams/c4/c4Detector.ts index 49ba95b8e..08b8bbf55 100644 --- a/packages/mermaid/src/diagrams/c4/c4Detector.ts +++ b/packages/mermaid/src/diagrams/c4/c4Detector.ts @@ -1,5 +1,20 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { ExternalDiagramDefinition } from '../../diagram-api/types'; -export const c4Detector: DiagramDetector = (txt) => { +const id = 'c4'; + +const detector = (txt: string) => { return txt.match(/^\s*C4Context|C4Container|C4Component|C4Dynamic|C4Deployment/) !== null; }; + +const loader = async () => { + const { diagram } = await import('./c4Diagram'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/c4/c4Diagram.ts b/packages/mermaid/src/diagrams/c4/c4Diagram.ts new file mode 100644 index 000000000..6f8f25db2 --- /dev/null +++ b/packages/mermaid/src/diagrams/c4/c4Diagram.ts @@ -0,0 +1,17 @@ +// @ts-ignore: TODO Fix ts errors +import c4Parser from './parser/c4Diagram'; +import c4Db from './c4Db'; +import c4Renderer from './c4Renderer'; +import c4Styles from './styles'; +import { MermaidConfig } from '../../config.type'; +import { DiagramDefinition } from '../../diagram-api/types'; + +export const diagram: DiagramDefinition = { + parser: c4Parser, + db: c4Db, + renderer: c4Renderer, + styles: c4Styles, + init: (cnf: MermaidConfig) => { + c4Renderer.setConf(cnf.c4); + }, +}; diff --git a/packages/mermaid/src/diagrams/class/classDetector-V2.ts b/packages/mermaid/src/diagrams/class/classDetector-V2.ts index 7100f6c66..1d4255719 100644 --- a/packages/mermaid/src/diagrams/class/classDetector-V2.ts +++ b/packages/mermaid/src/diagrams/class/classDetector-V2.ts @@ -1,6 +1,8 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types'; -export const classDetectorV2: DiagramDetector = (txt, config) => { +const id = 'classDiagram'; + +const detector: DiagramDetector = (txt, config) => { // If we have configured 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 && @@ -11,3 +13,16 @@ export const classDetectorV2: DiagramDetector = (txt, config) => { // 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; }; + +const loader = async () => { + const { diagram } = await import('./classDiagram-v2'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/class/classDetector.ts b/packages/mermaid/src/diagrams/class/classDetector.ts index c3833ed28..ef8ea61e7 100644 --- a/packages/mermaid/src/diagrams/class/classDetector.ts +++ b/packages/mermaid/src/diagrams/class/classDetector.ts @@ -1,6 +1,8 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types'; -export const classDetector: DiagramDetector = (txt, config) => { +const id = 'class'; + +const detector: DiagramDetector = (txt, config) => { // If we have configured to use dagre-wrapper then we should never return true in this function if (config?.class?.defaultRenderer === 'dagre-wrapper') { return false; @@ -8,3 +10,16 @@ export const classDetector: DiagramDetector = (txt, config) => { // 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; }; + +const loader = async () => { + const { diagram } = await import('./classDiagram'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/class/classDiagram-v2.ts b/packages/mermaid/src/diagrams/class/classDiagram-v2.ts new file mode 100644 index 000000000..2f0bbf371 --- /dev/null +++ b/packages/mermaid/src/diagrams/class/classDiagram-v2.ts @@ -0,0 +1,20 @@ +import { DiagramDefinition } from '../../diagram-api/types'; +// @ts-ignore: TODO Fix ts errors +import parser from './parser/classDiagram'; +import db from './classDb'; +import styles from './styles'; +import renderer from './classRenderer-v2'; + +export const diagram: DiagramDefinition = { + parser, + db, + renderer, + styles, + init: (cnf) => { + if (!cnf.class) { + cnf.class = {}; + } + cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + db.clear(); + }, +}; diff --git a/packages/mermaid/src/diagrams/class/classDiagram.ts b/packages/mermaid/src/diagrams/class/classDiagram.ts new file mode 100644 index 000000000..250d04176 --- /dev/null +++ b/packages/mermaid/src/diagrams/class/classDiagram.ts @@ -0,0 +1,20 @@ +import { DiagramDefinition } from '../../diagram-api/types'; +// @ts-ignore: TODO Fix ts errors +import parser from './parser/classDiagram'; +import db from './classDb'; +import styles from './styles'; +import renderer from './classRenderer'; + +export const diagram: DiagramDefinition = { + parser, + db, + renderer, + styles, + init: (cnf) => { + if (!cnf.class) { + cnf.class = {}; + } + cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + db.clear(); + }, +}; diff --git a/packages/mermaid/src/diagrams/er/erDetector.ts b/packages/mermaid/src/diagrams/er/erDetector.ts index 5a87a949e..f73baa434 100644 --- a/packages/mermaid/src/diagrams/er/erDetector.ts +++ b/packages/mermaid/src/diagrams/er/erDetector.ts @@ -1,5 +1,20 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types'; -export const erDetector: DiagramDetector = (txt) => { +const id = 'er'; + +const detector: DiagramDetector = (txt) => { return txt.match(/^\s*erDiagram/) !== null; }; + +const loader = async () => { + const { diagram } = await import('./erDiagram'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/er/erDiagram.ts b/packages/mermaid/src/diagrams/er/erDiagram.ts new file mode 100644 index 000000000..a5b0da9c1 --- /dev/null +++ b/packages/mermaid/src/diagrams/er/erDiagram.ts @@ -0,0 +1,12 @@ +// @ts-ignore: TODO Fix ts errors +import erParser from './parser/erDiagram'; +import erDb from './erDb'; +import erRenderer from './erRenderer'; +import erStyles from './styles'; + +export const diagram = { + parser: erParser, + db: erDb, + renderer: erRenderer, + styles: erStyles, +}; diff --git a/packages/mermaid/src/diagrams/er/parser/erDiagram.jison b/packages/mermaid/src/diagrams/er/parser/erDiagram.jison index 1e3972a3b..6aaca81d6 100644 --- a/packages/mermaid/src/diagrams/er/parser/erDiagram.jison +++ b/packages/mermaid/src/diagrams/er/parser/erDiagram.jison @@ -81,7 +81,7 @@ start document : /* empty */ { $$ = [] } - | document line {$1.push($2);$$ = $1} + | document line {$1.push($2);$$ = $1} ; line diff --git a/packages/mermaid/src/diagrams/error/errorDetector.ts b/packages/mermaid/src/diagrams/error/errorDetector.ts new file mode 100644 index 000000000..2bdcd7028 --- /dev/null +++ b/packages/mermaid/src/diagrams/error/errorDetector.ts @@ -0,0 +1,20 @@ +import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types'; + +const id = 'error'; + +const detector: DiagramDetector = (text) => { + return text.toLowerCase().trim() === 'error'; +}; + +const loader = async () => { + const { diagram } = await import('./errorDiagram'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/error/errorDiagram.ts b/packages/mermaid/src/diagrams/error/errorDiagram.ts new file mode 100644 index 000000000..d081e1028 --- /dev/null +++ b/packages/mermaid/src/diagrams/error/errorDiagram.ts @@ -0,0 +1,21 @@ +import { DiagramDefinition } from '../../diagram-api/types'; +import styles from './styles'; +import renderer from './errorRenderer'; +export const diagram: DiagramDefinition = { + db: { + clear: () => { + // Quite ok, clear needs to be there for error to work as a regular diagram + }, + }, + styles, + renderer, + parser: { + parser: { yy: {} }, + parse: () => { + // no op + }, + }, + init: () => { + // no op + }, +}; diff --git a/packages/mermaid/src/diagrams/flowchart/flowDb.js b/packages/mermaid/src/diagrams/flowchart/flowDb.js index 2e6b840b5..31196ba96 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowDb.js +++ b/packages/mermaid/src/diagrams/flowchart/flowDb.js @@ -677,6 +677,10 @@ const destructEndLink = (_str) => { stroke = 'thick'; } + if (line[0] === '~') { + stroke = 'invisible'; + } + let dots = countChar('.', line); if (dots) { diff --git a/packages/mermaid/src/diagrams/flowchart/flowDetector-v2.ts b/packages/mermaid/src/diagrams/flowchart/flowDetector-v2.ts index 3916325de..6162cc828 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowDetector-v2.ts +++ b/packages/mermaid/src/diagrams/flowchart/flowDetector-v2.ts @@ -1,6 +1,9 @@ import type { DiagramDetector } from '../../diagram-api/types'; +import type { ExternalDiagramDefinition } from '../../diagram-api/types'; -export const flowDetectorV2: DiagramDetector = (txt, config) => { +const id = 'flowchart-v2'; + +const detector: DiagramDetector = (txt, config) => { if (config?.flowchart?.defaultRenderer === 'dagre-d3') { return false; } @@ -14,3 +17,16 @@ export const flowDetectorV2: DiagramDetector = (txt, config) => { } return txt.match(/^\s*flowchart/) !== null; }; + +const loader = async () => { + const { diagram } = await import('./flowDiagram-v2'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/flowchart/flowDetector.ts b/packages/mermaid/src/diagrams/flowchart/flowDetector.ts index d46b7d8f5..9457ff469 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowDetector.ts +++ b/packages/mermaid/src/diagrams/flowchart/flowDetector.ts @@ -1,6 +1,8 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types'; -export const flowDetector: DiagramDetector = (txt, config) => { +const id = 'flowchart'; + +const detector: DiagramDetector = (txt, config) => { // If we have conferred to only use new flow charts this function should always return false // as in not signalling true for a legacy flowchart if (config?.flowchart?.defaultRenderer === 'dagre-wrapper') { @@ -11,3 +13,16 @@ export const flowDetector: DiagramDetector = (txt, config) => { } return txt.match(/^\s*graph/) !== null; }; + +const loader = async () => { + const { diagram } = await import('./flowDiagram'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/flowchart/flowDiagram-v2.ts b/packages/mermaid/src/diagrams/flowchart/flowDiagram-v2.ts new file mode 100644 index 000000000..8cd49de65 --- /dev/null +++ b/packages/mermaid/src/diagrams/flowchart/flowDiagram-v2.ts @@ -0,0 +1,25 @@ +// @ts-ignore: TODO Fix ts errors +import flowParser from './parser/flow'; +import flowDb from './flowDb'; +import flowRendererV2 from './flowRenderer-v2'; +import flowStyles from './styles'; +import { MermaidConfig } from '../../config.type'; +import { setConfig } from '../../config'; + +export const diagram = { + parser: flowParser, + db: flowDb, + renderer: flowRendererV2, + styles: flowStyles, + init: (cnf: MermaidConfig) => { + if (!cnf.flowchart) { + cnf.flowchart = {}; + } + cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + // flowchart-v2 uses dagre-wrapper, which doesn't have access to flowchart cnf + setConfig({ flowchart: { arrowMarkerAbsolute: cnf.arrowMarkerAbsolute } }); + flowRendererV2.setConf(cnf.flowchart); + flowDb.clear(); + flowDb.setGen('gen-2'); + }, +}; diff --git a/packages/mermaid/src/diagrams/flowchart/flowDiagram.ts b/packages/mermaid/src/diagrams/flowchart/flowDiagram.ts new file mode 100644 index 000000000..d68a7c01d --- /dev/null +++ b/packages/mermaid/src/diagrams/flowchart/flowDiagram.ts @@ -0,0 +1,24 @@ +// @ts-ignore: TODO Fix ts errors +import flowParser from './parser/flow'; +import flowDb from './flowDb'; +import flowRenderer from './flowRenderer'; +import flowRendererV2 from './flowRenderer-v2'; +import flowStyles from './styles'; +import { MermaidConfig } from '../../config.type'; + +export const diagram = { + parser: flowParser, + db: flowDb, + renderer: flowRendererV2, + styles: flowStyles, + init: (cnf: MermaidConfig) => { + if (!cnf.flowchart) { + cnf.flowchart = {}; + } + // TODO, broken as of 2022-09-14 (13809b50251845475e6dca65cc395761be38fbd2) + cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + flowRenderer.setConf(cnf.flowchart); + flowDb.clear(); + flowDb.setGen('gen-1'); + }, +}; diff --git a/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js b/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js index 03bda7611..2d3e21a44 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js +++ b/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js @@ -280,6 +280,11 @@ export const addEdges = function (edges, g, diagObj) { edgeData.pattern = 'solid'; edgeData.style = 'stroke-width: 3.5px;fill:none;'; break; + case 'invisible': + edgeData.thickness = 'invisible'; + edgeData.pattern = 'solid'; + edgeData.style = 'stroke-width: 0;fill:none;'; + break; } if (edge.style !== undefined) { const styles = getStylesFromArray(edge.style); diff --git a/packages/mermaid/src/diagrams/flowchart/flowRenderer.addEdges.spec.js b/packages/mermaid/src/diagrams/flowchart/flowRenderer.addEdges.spec.js index 01b6163cb..7744053f0 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowRenderer.addEdges.spec.js +++ b/packages/mermaid/src/diagrams/flowchart/flowRenderer.addEdges.spec.js @@ -1,21 +1,24 @@ import flowDb from './flowDb'; -import flowParser from './parser/flow'; +import { parser } from './parser/flow'; import flowRenderer from './flowRenderer'; -import { Diagram } from '../../Diagram'; import { addDiagrams } from '../../diagram-api/diagram-orchestration'; + +const diag = { + db: flowDb, +}; addDiagrams(); describe('when using mermaid and ', function () { describe('when calling addEdges ', function () { beforeEach(function () { - flowParser.parser.yy = flowDb; + 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(); + it('should handle edges with text', () => { + parser.parse('graph TD;A-->|text ex|B;'); + flowDb.getVertices(); + const edges = flowDb.getEdges(); const mockG = { setEdge: function (start, end, options) { @@ -29,10 +32,10 @@ describe('when using mermaid and ', function () { 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(); + it('should handle edges without text', async function () { + parser.parse('graph TD;A-->B;'); + flowDb.getVertices(); + const edges = flowDb.getEdges(); const mockG = { setEdge: function (start, end, options) { @@ -45,10 +48,10 @@ describe('when using mermaid and ', function () { 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(); + it('should handle open-ended edges', () => { + parser.parse('graph TD;A---B;'); + flowDb.getVertices(); + const edges = flowDb.getEdges(); const mockG = { setEdge: function (start, end, options) { @@ -61,10 +64,10 @@ describe('when using mermaid and ', function () { 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(); + it('should handle edges with styles defined', () => { + parser.parse('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;'); + flowDb.getVertices(); + const edges = flowDb.getEdges(); const mockG = { setEdge: function (start, end, options) { @@ -77,10 +80,10 @@ describe('when using mermaid and ', function () { 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(); + it('should handle edges with interpolation defined', () => { + parser.parse('graph TD;A---B; linkStyle 0 interpolate basis'); + flowDb.getVertices(); + const edges = flowDb.getEdges(); const mockG = { setEdge: function (start, end, options) { @@ -93,12 +96,10 @@ describe('when using mermaid and ', function () { 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(); + it('should handle edges with text and styles defined', () => { + parser.parse('graph TD;A---|the text|B; linkStyle 0 stroke:val1,stroke-width:val2;'); + flowDb.getVertices(); + const edges = flowDb.getEdges(); const mockG = { setEdge: function (start, end, options) { @@ -113,10 +114,10 @@ describe('when using mermaid and ', function () { 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(); + it('should set fill to "none" by default when handling edges', () => { + parser.parse('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;'); + flowDb.getVertices(); + const edges = flowDb.getEdges(); const mockG = { setEdge: function (start, end, options) { @@ -130,12 +131,10 @@ describe('when using mermaid and ', function () { 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(); + it('should not set fill to none if fill is set in linkStyle', () => { + parser.parse('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2,fill:blue;'); + flowDb.getVertices(); + const edges = flowDb.getEdges(); const mockG = { setEdge: function (start, end, options) { expect(start).toContain('flowchart-A-'); diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow.jison b/packages/mermaid/src/diagrams/flowchart/parser/flow.jison index 05473b4a0..e2dad5881 100644 --- a/packages/mermaid/src/diagrams/flowchart/parser/flow.jison +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow.jison @@ -121,6 +121,7 @@ that id. \s*[xo<]?\-\-+[-xo>]\s* return 'LINK'; \s*[xo<]?\=\=+[=xo>]\s* return 'LINK'; \s*[xo<]?\-?\.+\-[xo>]?\s* return 'LINK'; +\s*\~\~[\~]+\s* return 'LINK'; \s*[xo<]?\-\-\s* return 'START_LINK'; \s*[xo<]?\=\=\s* return 'START_LINK'; \s*[xo<]?\-\.\s* return 'START_LINK'; diff --git a/packages/mermaid/src/diagrams/gantt/ganttDetector.ts b/packages/mermaid/src/diagrams/gantt/ganttDetector.ts index 5de167010..3fe2bbe7e 100644 --- a/packages/mermaid/src/diagrams/gantt/ganttDetector.ts +++ b/packages/mermaid/src/diagrams/gantt/ganttDetector.ts @@ -1,5 +1,20 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types'; -export const ganttDetector: DiagramDetector = (txt) => { +const id = 'gantt'; + +const detector: DiagramDetector = (txt) => { return txt.match(/^\s*gantt/) !== null; }; + +const loader = async () => { + const { diagram } = await import('./ganttDiagram'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/gantt/ganttDiagram.ts b/packages/mermaid/src/diagrams/gantt/ganttDiagram.ts new file mode 100644 index 000000000..b1341052d --- /dev/null +++ b/packages/mermaid/src/diagrams/gantt/ganttDiagram.ts @@ -0,0 +1,13 @@ +// @ts-ignore: TODO Fix ts errors +import ganttParser from './parser/gantt'; +import ganttDb from './ganttDb'; +import ganttRenderer from './ganttRenderer'; +import ganttStyles from './styles'; +import { DiagramDefinition } from '../../diagram-api/types'; + +export const diagram: DiagramDefinition = { + parser: ganttParser, + db: ganttDb, + renderer: ganttRenderer, + styles: ganttStyles, +}; diff --git a/packages/mermaid/src/diagrams/git/gitGraphDetector.ts b/packages/mermaid/src/diagrams/git/gitGraphDetector.ts index f890501a5..46d09c6e5 100644 --- a/packages/mermaid/src/diagrams/git/gitGraphDetector.ts +++ b/packages/mermaid/src/diagrams/git/gitGraphDetector.ts @@ -1,5 +1,21 @@ import type { DiagramDetector } from '../../diagram-api/types'; +import type { ExternalDiagramDefinition } from '../../diagram-api/types'; -export const gitGraphDetector: DiagramDetector = (txt) => { +const id = 'gitGraph'; + +const detector: DiagramDetector = (txt) => { return txt.match(/^\s*gitGraph/) !== null; }; + +const loader = async () => { + const { diagram } = await import('./gitGraphDiagram'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/git/gitGraphDiagram.ts b/packages/mermaid/src/diagrams/git/gitGraphDiagram.ts new file mode 100644 index 000000000..9ef3506a0 --- /dev/null +++ b/packages/mermaid/src/diagrams/git/gitGraphDiagram.ts @@ -0,0 +1,13 @@ +// @ts-ignore: TODO Fix ts errors +import gitGraphParser from './parser/gitGraph'; +import gitGraphDb from './gitGraphAst'; +import gitGraphRenderer from './gitGraphRenderer'; +import gitGraphStyles from './styles'; +import { DiagramDefinition } from '../../diagram-api/types'; + +export const diagram: DiagramDefinition = { + parser: gitGraphParser, + db: gitGraphDb, + renderer: gitGraphRenderer, + styles: gitGraphStyles, +}; diff --git a/packages/mermaid/src/diagrams/info/infoDetector.ts b/packages/mermaid/src/diagrams/info/infoDetector.ts index 8bccb578f..a022e3ccb 100644 --- a/packages/mermaid/src/diagrams/info/infoDetector.ts +++ b/packages/mermaid/src/diagrams/info/infoDetector.ts @@ -1,5 +1,20 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types'; -export const infoDetector: DiagramDetector = (txt) => { +const id = 'info'; + +const detector: DiagramDetector = (txt) => { return txt.match(/^\s*info/) !== null; }; + +const loader = async () => { + const { diagram } = await import('./infoDiagram'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/info/infoDiagram.ts b/packages/mermaid/src/diagrams/info/infoDiagram.ts new file mode 100644 index 000000000..a8100a79f --- /dev/null +++ b/packages/mermaid/src/diagrams/info/infoDiagram.ts @@ -0,0 +1,13 @@ +import { DiagramDefinition } from '../../diagram-api/types'; +// @ts-ignore: TODO Fix ts errors +import parser from './parser/info'; +import db from './infoDb'; +import styles from './styles'; +import renderer from './infoRenderer'; + +export const diagram: DiagramDefinition = { + parser, + db, + renderer, + styles, +}; diff --git a/packages/mermaid/src/diagrams/pie/pieDetector.ts b/packages/mermaid/src/diagrams/pie/pieDetector.ts index e267c710a..dd1224db9 100644 --- a/packages/mermaid/src/diagrams/pie/pieDetector.ts +++ b/packages/mermaid/src/diagrams/pie/pieDetector.ts @@ -1,6 +1,20 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types'; -export const pieDetector: DiagramDetector = (txt) => { - const logOutput = txt.match(/^\s*pie/) !== null || txt.match(/^\s*bar/) !== null; - return logOutput; +const id = 'pie'; + +const detector: DiagramDetector = (txt) => { + return txt.match(/^\s*pie/) !== null; }; + +const loader = async () => { + const { diagram } = await import('./pieDiagram'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/pie/pieDiagram.ts b/packages/mermaid/src/diagrams/pie/pieDiagram.ts new file mode 100644 index 000000000..3a586f668 --- /dev/null +++ b/packages/mermaid/src/diagrams/pie/pieDiagram.ts @@ -0,0 +1,13 @@ +import { DiagramDefinition } from '../../diagram-api/types'; +// @ts-ignore: TODO Fix ts errors +import parser from './parser/pie'; +import db from './pieDb'; +import styles from './styles'; +import renderer from './pieRenderer'; + +export const diagram: DiagramDefinition = { + parser, + db, + renderer, + styles, +}; diff --git a/packages/mermaid/src/diagrams/requirement/requirementDetector.ts b/packages/mermaid/src/diagrams/requirement/requirementDetector.ts index 164da6c1a..1102fde0c 100644 --- a/packages/mermaid/src/diagrams/requirement/requirementDetector.ts +++ b/packages/mermaid/src/diagrams/requirement/requirementDetector.ts @@ -1,5 +1,20 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types'; -export const requirementDetector: DiagramDetector = (txt) => { +const id = 'requirement'; + +const detector: DiagramDetector = (txt) => { return txt.match(/^\s*requirement(Diagram)?/) !== null; }; + +const loader = async () => { + const { diagram } = await import('./requirementDiagram'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/requirement/requirementDiagram.ts b/packages/mermaid/src/diagrams/requirement/requirementDiagram.ts new file mode 100644 index 000000000..37f6177b6 --- /dev/null +++ b/packages/mermaid/src/diagrams/requirement/requirementDiagram.ts @@ -0,0 +1,13 @@ +import { DiagramDefinition } from '../../diagram-api/types'; +// @ts-ignore: TODO Fix ts errors +import parser from './parser/requirementDiagram'; +import db from './requirementDb'; +import styles from './styles'; +import renderer from './requirementRenderer'; + +export const diagram: DiagramDefinition = { + parser, + db, + renderer, + styles, +}; diff --git a/packages/mermaid/src/diagrams/sequence/sequenceDetector.ts b/packages/mermaid/src/diagrams/sequence/sequenceDetector.ts index 52640b134..c436e65d4 100644 --- a/packages/mermaid/src/diagrams/sequence/sequenceDetector.ts +++ b/packages/mermaid/src/diagrams/sequence/sequenceDetector.ts @@ -1,5 +1,20 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types'; -export const sequenceDetector: DiagramDetector = (txt) => { +const id = 'sequence'; + +const detector: DiagramDetector = (txt) => { return txt.match(/^\s*sequenceDiagram/) !== null; }; + +const loader = async () => { + const { diagram } = await import('./sequenceDiagram'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js b/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js index 72daca932..08f6abee1 100644 --- a/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js +++ b/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js @@ -2,9 +2,14 @@ import { vi } from 'vitest'; import * as configApi from '../../config'; import mermaidAPI from '../../mermaidAPI'; -import { Diagram } from '../../Diagram'; +import { Diagram, getDiagramFromText } from '../../Diagram'; import { addDiagrams } from '../../diagram-api/diagram-orchestration'; +beforeAll(async () => { + // Is required to load the sequence diagram + await getDiagramFromText('sequenceDiagram'); +}); + /** * Sequence diagrams require their own very special version of a mocked d3 module * diagrams/sequence/svgDraw uses statements like this with d3 nodes: (note the [0][0]) @@ -183,7 +188,7 @@ Alice->Bob:Hello Bob, how are you? Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`; - await mermaidAPI.parse(str, diagram); + await mermaidAPI.parse(str); const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); actors.Bob.description = 'Bob'; diff --git a/packages/mermaid/src/diagrams/sequence/sequenceDiagram.ts b/packages/mermaid/src/diagrams/sequence/sequenceDiagram.ts new file mode 100644 index 000000000..fdec7f86d --- /dev/null +++ b/packages/mermaid/src/diagrams/sequence/sequenceDiagram.ts @@ -0,0 +1,13 @@ +import { DiagramDefinition } from '../../diagram-api/types'; +// @ts-ignore: TODO Fix ts errors +import parser from './parser/sequenceDiagram'; +import db from './sequenceDb'; +import styles from './styles'; +import renderer from './sequenceRenderer'; + +export const diagram: DiagramDefinition = { + parser, + db, + renderer, + styles, +}; diff --git a/packages/mermaid/src/diagrams/state/parser/state-parser.spec.js b/packages/mermaid/src/diagrams/state/parser/state-parser.spec.js index 5ec5642e1..f8ea694a6 100644 --- a/packages/mermaid/src/diagrams/state/parser/state-parser.spec.js +++ b/packages/mermaid/src/diagrams/state/parser/state-parser.spec.js @@ -117,7 +117,7 @@ describe('state parser can parse...', () => { state "Big State 1" as bigState1 { state "inner state 1" as inner1 inner2: inner state 2 - inner1 --> inner2 + inner1 --> inner2 }`; stateDiagram.parser.parse(diagramText); stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2()); diff --git a/packages/mermaid/src/diagrams/state/stateDetector-V2.ts b/packages/mermaid/src/diagrams/state/stateDetector-V2.ts index 9e59c4a04..5fa617a76 100644 --- a/packages/mermaid/src/diagrams/state/stateDetector-V2.ts +++ b/packages/mermaid/src/diagrams/state/stateDetector-V2.ts @@ -1,11 +1,29 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types'; -export const stateDetectorV2: DiagramDetector = (text, config) => { +const id = 'stateDiagram'; + +const detector: DiagramDetector = (text, config) => { if (text.match(/^\s*stateDiagram-v2/) !== null) { return true; } if (text.match(/^\s*stateDiagram/) && config?.state?.defaultRenderer === 'dagre-wrapper') { return true; } + if (text.match(/^\s*stateDiagram/) && config?.state?.defaultRenderer === 'dagre-wrapper') { + return true; + } return false; }; + +const loader = async () => { + const { diagram } = await import('./stateDiagram-v2'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/state/stateDetector.ts b/packages/mermaid/src/diagrams/state/stateDetector.ts index 85338c6df..ee6b3ac2c 100644 --- a/packages/mermaid/src/diagrams/state/stateDetector.ts +++ b/packages/mermaid/src/diagrams/state/stateDetector.ts @@ -1,6 +1,8 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types'; -export const stateDetector: DiagramDetector = (txt, config) => { +const id = 'state'; + +const detector: DiagramDetector = (txt, config) => { // If we have confirmed 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') { @@ -8,3 +10,16 @@ export const stateDetector: DiagramDetector = (txt, config) => { } return txt.match(/^\s*stateDiagram/) !== null; }; + +const loader = async () => { + const { diagram } = await import('./stateDiagram'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/state/stateDiagram-v2.ts b/packages/mermaid/src/diagrams/state/stateDiagram-v2.ts new file mode 100644 index 000000000..f7ee4f052 --- /dev/null +++ b/packages/mermaid/src/diagrams/state/stateDiagram-v2.ts @@ -0,0 +1,20 @@ +import { DiagramDefinition } from '../../diagram-api/types'; +// @ts-ignore: TODO Fix ts errors +import parser from './parser/stateDiagram'; +import db from './stateDb'; +import styles from './styles'; +import renderer from './stateRenderer-v2'; + +export const diagram: DiagramDefinition = { + parser, + db, + renderer, + styles, + init: (cnf) => { + if (!cnf.state) { + cnf.state = {}; + } + cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + db.clear(); + }, +}; diff --git a/packages/mermaid/src/diagrams/state/stateDiagram.ts b/packages/mermaid/src/diagrams/state/stateDiagram.ts new file mode 100644 index 000000000..570d599de --- /dev/null +++ b/packages/mermaid/src/diagrams/state/stateDiagram.ts @@ -0,0 +1,20 @@ +import { DiagramDefinition } from '../../diagram-api/types'; +// @ts-ignore: TODO Fix ts errors +import parser from './parser/stateDiagram'; +import db from './stateDb'; +import styles from './styles'; +import renderer from './stateRenderer'; + +export const diagram: DiagramDefinition = { + parser, + db, + renderer, + styles, + init: (cnf) => { + if (!cnf.state) { + cnf.state = {}; + } + cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + db.clear(); + }, +}; diff --git a/packages/mermaid/src/diagrams/user-journey/journeyDetector.ts b/packages/mermaid/src/diagrams/user-journey/journeyDetector.ts index 535e7be9d..90b2fd6e1 100644 --- a/packages/mermaid/src/diagrams/user-journey/journeyDetector.ts +++ b/packages/mermaid/src/diagrams/user-journey/journeyDetector.ts @@ -1,5 +1,20 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types'; -export const journeyDetector: DiagramDetector = (txt) => { +const id = 'journey'; + +const detector: DiagramDetector = (txt) => { return txt.match(/^\s*journey/) !== null; }; + +const loader = async () => { + const { diagram } = await import('./journeyDiagram'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/user-journey/journeyDiagram.ts b/packages/mermaid/src/diagrams/user-journey/journeyDiagram.ts new file mode 100644 index 000000000..c3a2a3c6b --- /dev/null +++ b/packages/mermaid/src/diagrams/user-journey/journeyDiagram.ts @@ -0,0 +1,17 @@ +import { DiagramDefinition } from '../../diagram-api/types'; +// @ts-ignore: TODO Fix ts errors +import parser from './parser/journey'; +import db from './journeyDb'; +import styles from './styles'; +import renderer from './journeyRenderer'; + +export const diagram: DiagramDefinition = { + parser, + db, + renderer, + styles, + init: (cnf) => { + renderer.setConf(cnf.journey); + db.clear(); + }, +}; diff --git a/packages/mermaid/src/docs/.vitepress/theme/Mermaid.vue b/packages/mermaid/src/docs/.vitepress/theme/Mermaid.vue index 85c13393c..5012d3067 100644 --- a/packages/mermaid/src/docs/.vitepress/theme/Mermaid.vue +++ b/packages/mermaid/src/docs/.vitepress/theme/Mermaid.vue @@ -17,7 +17,7 @@ const props = defineProps({ }, }); -const svg = ref(null); +const svg = ref(''); let mut = null; onMounted(async () => { diff --git a/packages/mermaid/src/docs/.vitepress/theme/mermaid.ts b/packages/mermaid/src/docs/.vitepress/theme/mermaid.ts index c5b57f886..4752a1c01 100644 --- a/packages/mermaid/src/docs/.vitepress/theme/mermaid.ts +++ b/packages/mermaid/src/docs/.vitepress/theme/mermaid.ts @@ -2,6 +2,6 @@ import mermaid, { type MermaidConfig } from 'mermaid'; export const render = async (id: string, code: string, config: MermaidConfig): Promise => { mermaid.initialize(config); - const svg = await mermaid.render(id, code); + const { svg } = await mermaid.render(id, code); return svg; }; diff --git a/packages/mermaid/src/docs/config/usage.md b/packages/mermaid/src/docs/config/usage.md index dd989069f..c74023952 100644 --- a/packages/mermaid/src/docs/config/usage.md +++ b/packages/mermaid/src/docs/config/usage.md @@ -14,21 +14,24 @@ Please note that you can switch versions through the dropdown box at the top rig For the majority of users, Using the [Live Editor](https://mermaid.live/) would be sufficient, however you may also opt to deploy mermaid as a dependency or using the [Mermaid API](./setup/README.md). -We have compiled some Video [Tutorials](./Tutorials.md) on how to use the mermaid Live Editor. +We have compiled some Video [Tutorials](./Tutorials.md) on how to use the Mermaid Live Editor. ### Installing and Hosting Mermaid on a Webpage **Using the npm package:** -1. You will need to install `node v16`, which would have npm. +Requirements: -2. Download `yarn` using npm. +- Node >= 16 -3. Enter the following command: `yarn add mermaid`. - -4. At this point, you can add mermaid as a dev dependency using this command: `yarn add --dev mermaid`. - -5. Alternatively, you can also deploy mermaid using the script tag in an HTML file with mermaid diagram descriptions as is shown in the example below. +```bash +# NPM +npm install mermaid +# Yarn +yarn add mermaid +# PNPM +pnpm add mermaid +``` **Hosting mermaid on a web page:** @@ -36,7 +39,9 @@ We have compiled some Video [Tutorials](./Tutorials.md) on how to use the mermai The easiest way to integrate mermaid on a web page requires two elements: -- A graph definition, inside ` ` tags labeled `class=mermaid`. Example: +- A graph definition, inside `` tags labeled `class=mermaid`. + +Example: ```html@@ -47,14 +52,13 @@ The easiest way to integrate mermaid on a web page requires two elements:``` -- Inclusion of the mermaid address in the html page body using a `script` tag as an ESM import, and the `mermaidAPI` call. +- The mermaid js script. Added using a `script` tag as an ESM import. Example: ```html ``` @@ -65,9 +69,6 @@ Example: ```html - - -graph LR @@ -77,7 +78,6 @@ Example:@@ -89,11 +89,12 @@ An id attribute is also added to mermaid tags without one. Mermaid can load multiple diagrams, in the same page. -> Try it out, save this code as HTML and load it using any browser.(Except Internet Explorer, please don't use Internet Explorer.) +> Try it out, save this code as HTML and load it using any browser. +> (Except Internet Explorer, please don't use Internet Explorer.) ## Enabling Click Event and Tags in Nodes -A `securityLevel` configuration has to first be cleared, `securityLevel` sets the level of trust for the parsed diagrams and limits click functionality. This was introduce in version 8.2 as a security improvement, aimed at preventing malicious use. +A `securityLevel` configuration has to first be cleared. `securityLevel` sets the level of trust for the parsed diagrams and limits click functionality. This was introduce in version 8.2 as a security improvement, aimed at preventing malicious use. **It is the site owner's responsibility to discriminate between trustworthy and untrustworthy user-bases and we encourage the use of discretion.** @@ -101,7 +102,7 @@ A `securityLevel` configuration has to first be cleared, `securityLevel` sets th | Parameter | Description | Type | Required | Values | | ------------- | --------------------------------- | ------ | -------- | ------------------------------------------ | -| securityLevel | Level of trust for parsed diagram | String | Required | 'sandbox', 'strict', 'loose', 'antiscript' | +| securityLevel | Level of trust for parsed diagram | String | Optional | 'sandbox', 'strict', 'loose', 'antiscript' | Values: @@ -117,26 +118,17 @@ This changes the default behaviour of mermaid so that after upgrade to 8.2, unle **If you are taking responsibility for the diagram source security you can set the `securityLevel` to a value of your choosing . This allows clicks and tags are allowed.** -**To change `securityLevel`, you have to call `mermaidAPI.initialize`:** +**To change `securityLevel`, you have to call `mermaid.initialize`:** ```javascript -mermaidAPI.initialize({ +mermaid.initialize({ securityLevel: 'loose', }); ``` ### Labels out of bounds -If you use dynamically loaded fonts that are loaded through CSS, such as Google fonts, mermaid should wait for the -whole page to load (dom + assets, particularly the fonts file). - -```javascript -$(document).load(function () { - mermaid.initialize(); -}); -``` - -or +If you use dynamically loaded fonts that are loaded through CSS, such as fonts, mermaid should wait for the whole page to load (dom + assets, particularly the fonts file). ```javascript $(document).ready(function () { @@ -149,12 +141,55 @@ Not doing so will most likely result in mermaid rendering graphs that have label If your page has other fonts in its body those might be used instead of the mermaid font. Specifying the font in your styling is a workaround for this. ```css -div.mermaid { +pre.mermaid { font-family: 'trebuchet ms', verdana, arial; } ``` -### Calling `mermaid.init` +### Using `mermaid.run` + +mermaid.run was added in v10 and is the preferred way of handling more complex integration. +By default, `mermaid.run` will be called when the document is ready, rendering all elements with `class="mermaid"`. + +You can customize that behavior by calling `await mermaid.run()`. + +`mermaid.initialize({startOnLoad: false})` will prevent `mermaid.run` from being called automatically after load. + +Render all elements with querySelector ".someOtherClass" + +```js +mermaid.initialize({ startOnLoad: false }); +await mermaid.run({ + querySelector: '.someOtherClass', +}); +``` + +Render all elements passed as an array + +```js +mermaid.initialize({ startOnLoad: false }); +await mermaid.run({ + nodes: [document.getElementById('someId'), document.getElementById('anotherId')], +}); +await mermaid.run({ + nodes: document.querySelectorAll('.yetAnotherClass'), +}); +``` + +Render all `.mermaid` elements while suppressing any error + +```js +mermaid.initialize({ startOnLoad: false }); +await mermaid.run({ + suppressErrors: true, +}); +``` + +### Calling `mermaid.init` - Deprecated + +```warning +mermaid.init is deprecated in v10 and will be removed in v11. Please use mermaid.run instead. +``` By default, `mermaid.init` will be called when the document is ready, finding all elements with `class="mermaid"`. If you are adding content after mermaid is loaded, or otherwise need @@ -188,25 +223,24 @@ mermaid fully supports webpack. Here is a [working demo](https://github.com/merm ## API usage -The main idea of the API is to be able to call a render function with the graph definition as a string. The render function -will render the graph and call a callback with the resulting SVG code. With this approach it is up to the site creator to -fetch the graph definition from the site (perhaps from a textarea), render it and place the graph somewhere in the site. +The main idea of the API is to be able to call a render function with the graph definition as a string. The render function will render the graph and call a callback with the resulting SVG code. With this approach it is up to the site creator to fetch the graph definition from the site (perhaps from a textarea), render it and place the graph somewhere in the site. The example below show an outline of how this could be used. The example just logs the resulting SVG to the JavaScript console. ```html ``` @@ -219,17 +253,17 @@ The example code below is an extract of what mermaid does when using the API. Th bind events to an SVG when using the API for rendering. ```javascript -const insertSvg = function (svgCode, bindFunctions) { - element.innerHTML = svgCode; - if (typeof callback !== 'undefined') { - callback(id); +// Example of using the bindFunctions +const drawDiagram = async function () { + element = document.querySelector('#graphDiv'); + const graphDefinition = 'graph TB\na-->b'; + const { svg, bindFunctions } = await mermaid.render('graphDiv', graphDefinition); + element.innerHTML = svg; + // This can also be written as `bindFunctions?.(element);` using the `?` shorthand. + if (bindFunctions) { + bindFunctions(element); } - bindFunctions(element); }; - -const id = 'theGraph'; - -mermaidAPI.render(id, txt, insertSvg, element); ``` 1. The graph is generated using the render call. diff --git a/packages/mermaid/src/docs/ecosystem/integrations.md b/packages/mermaid/src/docs/ecosystem/integrations.md index cf4ccc9f8..727580664 100644 --- a/packages/mermaid/src/docs/ecosystem/integrations.md +++ b/packages/mermaid/src/docs/ecosystem/integrations.md @@ -14,6 +14,7 @@ They also serve as proof of concept, for the variety of things that can be built - [Gitea](https://gitea.io) (**Native support**) - [Azure Devops](https://docs.microsoft.com/en-us/azure/devops/project/wiki/wiki-markdown-guidance?view=azure-devops#add-mermaid-diagrams-to-a-wiki-page) (**Native support**) - [Tuleap](https://docs.tuleap.org/user-guide/writing-in-tuleap.html#graphs) (**Native support**) +- [Deepdwn](https://billiam.itch.io/deepdwn) (**Native support**) - [Joplin](https://joplinapp.org) (**Native support**) - [Swimm](https://swimm.io) (**Native support**) - [Notion](https://notion.so) (**Native support**) @@ -182,3 +183,6 @@ They also serve as proof of concept, for the variety of things that can be built - [mermaid-server: Generate diagrams using a HTTP request](https://github.com/TomWright/mermaid-server) - [ExDoc](https://github.com/elixir-lang/ex_doc) - [Rendering Mermaid graphs](https://github.com/elixir-lang/ex_doc#rendering-mermaid-graphs) +- [NiceGUI: Let any browser be the frontend of your Python code](https://nicegui.io) + - [ui.mermaid(...)](https://nicegui.io/reference#mermaid_diagrams) + - [ui.markdown(..., extras=['mermaid'])](https://nicegui.io/reference#markdown_element) diff --git a/packages/mermaid/src/docs/intro/n00b-gettingStarted.md b/packages/mermaid/src/docs/intro/n00b-gettingStarted.md index cfc16e707..fcb3f31ee 100644 --- a/packages/mermaid/src/docs/intro/n00b-gettingStarted.md +++ b/packages/mermaid/src/docs/intro/n00b-gettingStarted.md @@ -86,7 +86,7 @@ When writing the .html file, we give two instructions inside the html code to th a. The mermaid code for the diagram we want to create. -b. The importing of mermaid library through the `mermaid.esm.js` or `mermaid.esm.min.mjs` and the `mermaid.initialize()` call, which dictates the appearance of diagrams and also starts the rendering process . +b. The importing of mermaid library through the `mermaid.esm.mjs` or `mermaid.esm.min.mjs` and the `mermaid.initialize()` call, which dictates the appearance of diagrams and also starts the rendering process . **a. The embedded mermaid diagram definition inside a ` `:** @@ -118,7 +118,7 @@ b. The importing of mermaid library through the `mermaid.esm.js` or `mermaid.esm ``` **Notes**: -Rendering in Mermaid is initialized by `mermaid.initialize()` call. You can place `mermaid.initialize()` inside `mermaid.esm.min.mjs` for brevity. However, doing the opposite lets you control when it starts looking for ``tags inside the web page with `mermaid.initialize()`. This is useful when you think that not all `` tags may have loaded on the execution of `mermaid.esm.min.mjs` file. +Rendering in Mermaid is initialized by `mermaid.initialize()` call. However, doing the opposite lets you control when it starts looking for `` tags inside the web page with `mermaid.initialize()`. This is useful when you think that not all `` tags may have loaded on the execution of `mermaid.esm.min.mjs` file. `startOnLoad` is one of the parameters that can be defined by `mermaid.initialize()` @@ -126,10 +126,6 @@ Rendering in Mermaid is initialized by `mermaid.initialize()` call. You can plac | ----------- | --------------------------------- | ------- | ----------- | | startOnLoad | Toggle for Rendering upon loading | Boolean | true, false | -### Adding external diagrams to mermaid - -Please refer to the [Mindmap](../syntax/mindmap.md?id=integrating-with-your-librarywebsite) section for more information. - ### Working Examples **Here is a full working example of the mermaidAPI being called through the CDN:** diff --git a/packages/mermaid/src/docs/syntax/flowchart.md b/packages/mermaid/src/docs/syntax/flowchart.md index 5896e0518..6997ca088 100644 --- a/packages/mermaid/src/docs/syntax/flowchart.md +++ b/packages/mermaid/src/docs/syntax/flowchart.md @@ -245,6 +245,15 @@ flowchart LR A == text ==> B ``` +### An invisible link + +This can be a useful tool in some instances where you want to alter the default positioning of a node. + +```mermaid-example +flowchart LR + A ~~~ B +``` + ### Chaining of links It is possible declare many links in the same line as per below: diff --git a/packages/mermaid/src/mermaid.spec.ts b/packages/mermaid/src/mermaid.spec.ts index 75cafcdf3..58d39c348 100644 --- a/packages/mermaid/src/mermaid.spec.ts +++ b/packages/mermaid/src/mermaid.spec.ts @@ -1,6 +1,11 @@ import mermaid from './mermaid'; import { mermaidAPI } from './mermaidAPI'; import './diagram-api/diagram-orchestration'; +import { addDiagrams } from './diagram-api/diagram-orchestration'; + +beforeAll(async () => { + addDiagrams(); +}); const spyOn = vi.spyOn; vi.mock('./mermaidAPI'); @@ -66,9 +71,9 @@ describe('when using mermaid and ', () => { mermaid.registerExternalDiagrams( [ { - id: 'dummy', - detector: (text) => /dummy/.test(text), - loader: () => Promise.reject('error'), + id: 'dummyError', + detector: (text) => /dummyError/.test(text), + loader: () => Promise.reject('dummyError'), }, ], { lazyLoad: false } diff --git a/packages/mermaid/src/mermaid.ts b/packages/mermaid/src/mermaid.ts index 29d25c016..0b6807b3c 100644 --- a/packages/mermaid/src/mermaid.ts +++ b/packages/mermaid/src/mermaid.ts @@ -7,11 +7,10 @@ import { MermaidConfig } from './config.type'; import { log } from './logger'; import utils from './utils'; import { mermaidAPI, ParseOptions, RenderResult } from './mermaidAPI'; -import { registerLazyLoadedDiagrams } from './diagram-api/detectType'; +import { registerLazyLoadedDiagrams, loadRegisteredDiagrams } from './diagram-api/detectType'; import type { ParseErrorFunction } from './Diagram'; import { isDetailedError } from './utils'; import type { DetailedError } from './utils'; -import { registerDiagram } from './diagram-api/diagramAPI'; import { ExternalDiagramDefinition } from './diagram-api/types'; export type { @@ -23,19 +22,22 @@ export type { ParseOptions, }; -/** - * The options used when running mermaid. - * - * @param querySelector - The query selector to use when finding elements to render. Default: .mermaid - * @param nodes - The nodes to render. If this is set, querySelector will be ignored. - * @param postRenderCallback - A callback to call after each diagram is rendered. - * @param suppressErrors - If true, errors will be logged to the console, but not thrown. Default: false - */ export interface RunOptions { - // Default: .mermaid + /** + * The query selector to use when finding elements to render. Default: `".mermaid"`. + */ querySelector?: string; + /** + * The nodes to render. If this is set, `querySelector` will be ignored. + */ nodes?: ArrayLike; + /** + * A callback to call after each diagram is rendered. + */ postRenderCallback?: (id: string) => unknown; + /** + * If `true`, errors will be logged to the console, but not thrown. Default: `false` + */ suppressErrors?: boolean; } @@ -64,30 +66,6 @@ const handleError = (error: unknown, errors: DetailedError[], parseError?: Parse } }; -/** - * This is an internal function and should not be made public, as it will likely change. - * @internal - * @param diagrams - Array of {@link ExternalDiagramDefinition}. - */ -const loadExternalDiagrams = async (...diagrams: ExternalDiagramDefinition[]) => { - log.debug(`Loading ${diagrams.length} external diagrams`); - // Load all lazy loaded diagrams in parallel - const results = await Promise.allSettled( - diagrams.map(async ({ id, detector, loader }) => { - const { diagram } = await loader(); - registerDiagram(id, diagram, detector); - }) - ); - const failed = results.filter((result) => result.status === 'rejected'); - if (failed.length > 0) { - log.error(`Failed to load ${failed.length} external diagrams`); - for (const res of failed) { - log.error(res); - } - throw new Error(`Failed to load ${failed.length} external diagrams`); - } -}; - /** * ## run * @@ -251,7 +229,7 @@ const init = async function ( /** * Used to register external diagram types. * @param diagrams - Array of {@link ExternalDiagramDefinition}. - * @param opts - If opts.lazyLoad is true, the diagram will be loaded on demand. + * @param opts - If opts.lazyLoad is false, the diagrams will be loaded immediately. */ const registerExternalDiagrams = async ( diagrams: ExternalDiagramDefinition[], @@ -261,10 +239,9 @@ const registerExternalDiagrams = async ( lazyLoad?: boolean; } = {} ) => { - if (lazyLoad) { - registerLazyLoadedDiagrams(...diagrams); - } else { - await loadExternalDiagrams(...diagrams); + registerLazyLoadedDiagrams(...diagrams); + if (lazyLoad === false) { + await loadRegisteredDiagrams(); } }; diff --git a/packages/mermaid/src/mermaidAPI.ts b/packages/mermaid/src/mermaidAPI.ts index 999db5088..64e0bbce2 100644 --- a/packages/mermaid/src/mermaidAPI.ts +++ b/packages/mermaid/src/mermaidAPI.ts @@ -74,6 +74,23 @@ export interface ParseOptions { // @ts-ignore Could replicate the type definition in d3. This also makes it possible to use the untyped info from the js diagram files. export type D3Element = any; +export interface RenderResult { + /** + * The svg code for the rendered graph. + */ + svg: string; + /** + * Bind function to be called after the svg has been inserted into the DOM. + * This is necessary for adding event listeners to the elements in the svg. + * ```js + * const { svg, bindFunctions } = mermaidAPI.render('id1', 'graph TD;A-->B'); + * div.innerHTML = svg; + * bindFunctions?.(div); // To call bindFunctions only if it's present. + * ``` + */ + bindFunctions?: (element: Element) => void; +} + /** * Parse the text and validate the syntax. * @param text - The mermaid diagram definition. @@ -379,11 +396,6 @@ export const removeExistingElements = ( * @returns Returns the rendered element as a string containing the SVG definition. */ -export interface RenderResult { - svg: string; - bindFunctions?: (element: Element) => void; -} - const render = async function ( id: string, text: string, diff --git a/packages/mermaid/src/styles.ts b/packages/mermaid/src/styles.ts index 055f63be5..588c26cb1 100644 --- a/packages/mermaid/src/styles.ts +++ b/packages/mermaid/src/styles.ts @@ -1,39 +1,7 @@ -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'; -import info from './diagrams/info/styles'; -import pie from './diagrams/pie/styles'; -import requirement from './diagrams/requirement/styles'; -import sequence from './diagrams/sequence/styles'; -import stateDiagram from './diagrams/state/styles'; -import journey from './diagrams/user-journey/styles'; -import c4 from './diagrams/c4/styles'; -import { FlowChartStyleOptions } from './diagrams/flowchart/styles'; +import type { FlowChartStyleOptions } from './diagrams/flowchart/styles'; import { log } from './logger'; -// TODO @knut: Inject from registerDiagram. -const themes: Record = { - flowchart, - 'flowchart-v2': flowchart, - sequence, - gantt, - classDiagram, - 'classDiagram-v2': classDiagram, - class: classDiagram, - stateDiagram, - state: stateDiagram, - // gitGraph, - info, - pie, - er, - error, - journey, - requirement, - c4, -}; +const themes: Record = {}; const getStyles = ( type: string, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 67a902273..ed3323d34 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1166,7 +1166,6 @@ packages: /@braintree/sanitize-url/6.0.0: resolution: {integrity: sha512-mgmE7XBYY/21erpzhexk4Cj1cyTQ9LzvnTxtzM17BJ7ERMNE6W72mQRo0I1Ud8eFJ+RVVIcBNhLFZ3GX4XFz5w==} - dev: false /@colors/colors/1.5.0: resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} @@ -2983,6 +2982,10 @@ packages: resolution: {integrity: sha512-zmEmF5OIM3rb7SbLCFYoQhO4dGt2FRM9AMkxvA3LaADOF1n8in/zGJlWji9fmafLoNyz+FoL6FE0SLtGIArD7w==} dev: true + /@types/lodash/4.14.189: + resolution: {integrity: sha512-kb9/98N6X8gyME9Cf7YaqIMvYGnBSWqEci6tiettE6iJWH1XdJz/PO8LB0GtLCG7x8dU3KWhZT+lA1a35127tA==} + dev: true + /@types/markdown-it/12.2.3: resolution: {integrity: sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==} dependencies: @@ -5424,12 +5427,10 @@ packages: engines: {node: '>=12'} dependencies: internmap: 2.0.3 - dev: false /d3-axis/3.0.0: resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==} engines: {node: '>=12'} - dev: false /d3-brush/3.0.0: resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==} @@ -5440,38 +5441,32 @@ packages: d3-interpolate: 3.0.1 d3-selection: 3.0.0 d3-transition: 3.0.1_d3-selection@3.0.0 - dev: false /d3-chord/3.0.1: resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==} engines: {node: '>=12'} dependencies: d3-path: 3.0.1 - dev: false /d3-color/3.1.0: resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} engines: {node: '>=12'} - dev: false /d3-contour/4.0.0: resolution: {integrity: sha512-7aQo0QHUTu/Ko3cP9YK9yUTxtoDEiDGwnBHyLxG5M4vqlBkO/uixMRele3nfsfj6UXOcuReVpVXzAboGraYIJw==} engines: {node: '>=12'} dependencies: d3-array: 3.2.0 - dev: false /d3-delaunay/6.0.2: resolution: {integrity: sha512-IMLNldruDQScrcfT+MWnazhHbDJhcRJyOEBAJfwQnHle1RPh6WDuLvxNArUju2VSMSUuKlY5BGHRJ2cYyoFLQQ==} engines: {node: '>=12'} dependencies: delaunator: 5.0.0 - dev: false /d3-dispatch/3.0.1: resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==} engines: {node: '>=12'} - dev: false /d3-drag/3.0.0: resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==} @@ -5479,7 +5474,6 @@ packages: dependencies: d3-dispatch: 3.0.1 d3-selection: 3.0.0 - dev: false /d3-dsv/3.0.1: resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==} @@ -5489,19 +5483,16 @@ packages: commander: 7.2.0 iconv-lite: 0.6.3 rw: 1.3.3 - dev: false /d3-ease/3.0.1: resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} engines: {node: '>=12'} - dev: false /d3-fetch/3.0.1: resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==} engines: {node: '>=12'} dependencies: d3-dsv: 3.0.1 - dev: false /d3-force/3.0.0: resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==} @@ -5510,51 +5501,42 @@ packages: d3-dispatch: 3.0.1 d3-quadtree: 3.0.1 d3-timer: 3.0.1 - dev: false /d3-format/3.1.0: resolution: {integrity: sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==} engines: {node: '>=12'} - dev: false /d3-geo/3.0.1: resolution: {integrity: sha512-Wt23xBych5tSy9IYAM1FR2rWIBFWa52B/oF/GYe5zbdHrg08FU8+BuI6X4PvTwPDdqdAdq04fuWJpELtsaEjeA==} engines: {node: '>=12'} dependencies: d3-array: 3.2.0 - dev: false /d3-hierarchy/3.1.2: resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==} engines: {node: '>=12'} - dev: false /d3-interpolate/3.0.1: resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} engines: {node: '>=12'} dependencies: d3-color: 3.1.0 - dev: false /d3-path/3.0.1: resolution: {integrity: sha512-gq6gZom9AFZby0YLduxT1qmrp4xpBA1YZr19OI717WIdKE2OM5ETq5qrHLb301IgxhLwcuxvGZVLeeWc/k1I6w==} engines: {node: '>=12'} - dev: false /d3-polygon/3.0.1: resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==} engines: {node: '>=12'} - dev: false /d3-quadtree/3.0.1: resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==} engines: {node: '>=12'} - dev: false /d3-random/3.0.1: resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==} engines: {node: '>=12'} - dev: false /d3-scale-chromatic/3.0.0: resolution: {integrity: sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==} @@ -5562,7 +5544,6 @@ packages: dependencies: d3-color: 3.1.0 d3-interpolate: 3.0.1 - dev: false /d3-scale/4.0.2: resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==} @@ -5573,38 +5554,32 @@ packages: d3-interpolate: 3.0.1 d3-time: 3.0.0 d3-time-format: 4.1.0 - dev: false /d3-selection/3.0.0: resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==} engines: {node: '>=12'} - dev: false /d3-shape/3.1.0: resolution: {integrity: sha512-tGDh1Muf8kWjEDT/LswZJ8WF85yDZLvVJpYU9Nq+8+yW1Z5enxrmXOhTArlkaElU+CTn0OTVNli+/i+HP45QEQ==} engines: {node: '>=12'} dependencies: d3-path: 3.0.1 - dev: false /d3-time-format/4.1.0: resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==} engines: {node: '>=12'} dependencies: d3-time: 3.0.0 - dev: false /d3-time/3.0.0: resolution: {integrity: sha512-zmV3lRnlaLI08y9IMRXSDshQb5Nj77smnfpnd2LrBa/2K281Jijactokeak14QacHs/kKq0AQ121nidNYlarbQ==} engines: {node: '>=12'} dependencies: d3-array: 3.2.0 - dev: false /d3-timer/3.0.1: resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} engines: {node: '>=12'} - dev: false /d3-transition/3.0.1_d3-selection@3.0.0: resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==} @@ -5618,7 +5593,6 @@ packages: d3-interpolate: 3.0.1 d3-selection: 3.0.0 d3-timer: 3.0.1 - dev: false /d3-zoom/3.0.0: resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} @@ -5629,7 +5603,6 @@ packages: d3-interpolate: 3.0.1 d3-selection: 3.0.0 d3-transition: 3.0.1_d3-selection@3.0.0 - dev: false /d3/7.8.2: resolution: {integrity: sha512-WXty7qOGSHb7HR7CfOzwN1Gw04MUOzN8qh9ZUsvwycIMb4DYMpY9xczZ6jUorGtO6bR9BPMPaueIKwiDxu9uiQ==} @@ -5665,7 +5638,6 @@ packages: d3-timer: 3.0.1 d3-transition: 3.0.1_d3-selection@3.0.0 d3-zoom: 3.0.0 - dev: false /dagre-d3-es/7.0.8: resolution: {integrity: sha512-eykdoYQ4FwCJinEYS0gPL2f2w+BPbSLvnQSJ3Ye1vAoPjdkq6xIMKBv+UkICd3qZE26wBKIn3p+6n0QC7R1LyA==} @@ -5859,7 +5831,6 @@ packages: resolution: {integrity: sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==} dependencies: robust-predicates: 3.0.1 - dev: false /delayed-stream/1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} @@ -7496,7 +7467,6 @@ packages: /internmap/2.0.3: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} engines: {node: '>=12'} - dev: false /interpret/2.2.0: resolution: {integrity: sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==} @@ -8453,7 +8423,6 @@ packages: /khroma/2.0.0: resolution: {integrity: sha512-2J8rDNlQWbtiNYThZRvmMv5yt44ZakX+Tz5ZIp/mN1pt4snn+m030Va5Z4v8xA0cQFDXBwO/8i42xL4QPsVk3g==} - dev: false /kind-of/6.0.3: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} @@ -9327,7 +9296,6 @@ packages: /moment-mini/2.29.4: resolution: {integrity: sha512-uhXpYwHFeiTbY9KSgPPRoo1nt8OxNVdMVoTBYHfSEKeRkIkwGpO+gERmhuhBtzfaeOyTkykSrm2+noJBgqt3Hg==} - dev: false /mri/1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} @@ -9430,7 +9398,6 @@ packages: /non-layered-tidy-tree-layout/2.0.2: resolution: {integrity: sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==} - dev: false /normalize-package-data/2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} @@ -10439,7 +10406,6 @@ packages: /robust-predicates/3.0.1: resolution: {integrity: sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==} - dev: false /rollup/3.15.0: resolution: {integrity: sha512-F9hrCAhnp5/zx/7HYmftvsNBkMfLfk/dXUh73hPSM2E3CRgap65orDNJbLetoiUFwSAk6iHPLvBrZ5iHYvzqsg==} @@ -10457,7 +10423,6 @@ packages: /rw/1.3.3: resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} - dev: false /rxjs/7.5.6: resolution: {integrity: sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==} @@ -11086,7 +11051,6 @@ packages: /stylis/4.1.2: resolution: {integrity: sha512-Nn2CCrG2ZaFziDxaZPN43CXqn+j7tcdjPFCkRBkFue8QYXC2HdEwnw5TCBo4yQZ2WxKYeSi0fdoOrtEqgDrXbA==} - dev: false /supports-color/2.0.0: resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} @@ -11655,7 +11619,6 @@ packages: /uuid/9.0.0: resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} hasBin: true - dev: false /uvu/0.5.6: resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==}