merged with master

This commit is contained in:
devcer 2022-10-17 09:27:42 +05:30
commit aad53f9e61
100 changed files with 3125 additions and 3888 deletions

View File

@ -61,24 +61,25 @@
},
"overrides": [
{
"files": "./**/*.html",
"rules": {
"no-undef": "off",
"jsdoc/require-jsdoc": "off"
}
},
{
"files": ["./cypress/**", "./demos/**"],
"files": ["cypress/**", "demos/**"],
"rules": {
"no-console": "off"
}
},
{
"files": ["./**/*.spec.{ts,js}", "./cypress/**", "./demos/**", "./**/docs/**"],
"files": ["*.spec.{ts,js}", "cypress/**", "demos/**", "**/docs/**"],
"rules": {
"jsdoc/require-jsdoc": "off",
"@typescript-eslint/no-unused-vars": "off"
}
},
{
"files": ["*.html", "*.md", "**/*.md/*"],
"rules": {
"no-var": "error",
"no-undef": "off",
"@typescript-eslint/no-unused-vars": "off"
}
}
]
}

View File

@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x]
node-version: [18.x]
steps:
- uses: actions/checkout@v3

View File

@ -16,9 +16,9 @@ jobs:
name: 'Docs: Spellcheck'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
name: Check out the code
- uses: actions/setup-node@v1
- uses: actions/setup-node@v3
name: Setup node
with:
node-version: '16'

View File

@ -23,7 +23,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x]
node-version: [18.x]
steps:
- if: ${{ ! env.USE_APPLI }}
name: Warn if not using Applitools

View File

@ -11,7 +11,7 @@ jobs:
strategy:
fail-fast: false
matrix:
node-version: [16.x]
node-version: [18.x]
containers: [1, 2, 3, 4]
steps:
- uses: actions/checkout@v3

View File

@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x]
node-version: [18.x]
steps:
- uses: actions/checkout@v3

View File

@ -13,7 +13,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 16.x
node-version: 18.x
- name: Install Yarn
run: npm i yarn --global

View File

@ -14,7 +14,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 16.x
node-version: 18.x
- name: Install Yarn
run: npm i yarn --global

View File

@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x]
node-version: [18.x]
steps:
- uses: actions/checkout@v3

1
.npmrc Normal file
View File

@ -0,0 +1 @@
auto-install-peers=true

View File

@ -6,12 +6,23 @@ So you want to help? That's great!
Here are a few things to know to get you started on the right path.
Below link will help you making a copy of the repository in your local system.
https://docs.github.com/en/get-started/quickstart/fork-a-repo
## Requirements
- [volta](https://volta.sh/) to manage node versions.
- [Node.js](https://nodejs.org/en/). `volta install node`
- [pnpm](https://pnpm.io/) package manager. `volta install pnpm`
## Development Installation
```bash
git clone git@github.com:mermaid-js/mermaid.git
cd mermaid
pnpm install
# npx is required for first install as volta support for pnpm is not added yet.
npx pnpm install
pnpm test
```
@ -39,16 +50,16 @@ Less strict here, it is OK to commit directly in the `develop` branch if you are
The documentation is written in **Markdown**. For more information about Markdown [see the GitHub Markdown help page](https://help.github.com/en/github/writing-on-github/basic-writing-and-formatting-syntax).
### Documentation source files are in /src/docs
### Documentation source files are in [`/packages/mermaid/src/docs`](packages/mermaid/src/docs)
The source files for the project documentation are located in the `/src/docs` directory. This is where you should make changes.
The files under `/src/docs` are processed to generate the published documentation, and the resulting files are put into the `/docs` directory.
The source files for the project documentation are located in the [`/packages/mermaid/src/docs`](packages/mermaid/src/docs) directory. This is where you should make changes.
The files under `/packages/mermaid/src/docs` are processed to generate the published documentation, and the resulting files are put into the `/docs` directory.
```mermaid
flowchart LR
classDef default fill:#fff,color:black,stroke:black
source["files in /src/docs\n(changes should be done here)"] -- automatic processing\nto generate the final documentation--> published["files in /docs\ndisplayed on the official documentation site"]
source["files in /packages/mermaid/src/docs\n(changes should be done here)"] -- automatic processing\nto generate the final documentation--> published["files in /docs\ndisplayed on the official documentation site"]
```
@ -137,7 +148,7 @@ it('should render forks and joins', () => {
Finally, if it is not in the documentation, no one will know about it and then **no one will use it**. Wouldn't that be sad? With all the effort that was put into the feature?
The source files for documentation are in `/src/docs` and are written in markdown. Just pick the right section and start typing. See the [Committing Documentation](#committing-documentation) section for more about how the documentation is generated.
The source files for documentation are in `/packages/mermaid/src/docs` and are written in markdown. Just pick the right section and start typing. See the [Committing Documentation](#committing-documentation) section for more about how the documentation is generated.
#### Adding to or changing the documentation organization

View File

@ -1,6 +1,8 @@
# mermaid [![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE)
# mermaid
# Whoa, whats going on here?
[![Build CI Status](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml/badge.svg)](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml) [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid) [![NPM](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid) [![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [![Twitter Follow](https://img.shields.io/twitter/follow/mermaidjs_?style=social)](https://twitter.com/mermaidjs_)
# Whoa, what's going on here?
We are transforming the Mermaid repository to a so called mono-repo. This is a part of the effort to decouple the diagrams from the core of mermaid. This will:

View File

@ -1,4 +1,6 @@
# mermaid [![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE)
# mermaid
[![Build CI Status](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml/badge.svg)](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml) [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid) [![NPM](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid) [![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [![Twitter Follow](https://img.shields.io/twitter/follow/mermaidjs_?style=social)](https://twitter.com/mermaidjs_)
[English](./README.md) | 简体中文

View File

@ -1,3 +1 @@
import { vi } from 'vitest';
// export const render = vi.fn();
// DO NOT delete this file. It is used by vitest to mock the dagre-d3 module.

View File

@ -52,7 +52,8 @@
"Ashish",
"bbox",
"techn",
"cytoscape"
"cytoscape",
"ts-nocheck"
],
"patterns": [
{

View File

@ -0,0 +1,14 @@
<html>
<body>
<pre class="mermaid">
none
hello world
</pre>
<script src="./mermaid.js"></script>
<script>
mermaid.initialize({
logLevel: 1,
});
</script>
</body>
</html>

View File

@ -93,7 +93,7 @@
throw new Error('XSS Succeeded');
}
var diagram = 'classDiagram\n';
let diagram = 'classDiagram\n';
diagram += 'class Square~<img/src';
diagram += "='1'/onerror=xssAttack()>~{\n";
diagram += 'id A\n';

View File

@ -93,7 +93,7 @@
throw new Error('XSS Succeeded');
}
var diagram = 'stateDiagram-v2\n';
let diagram = 'stateDiagram-v2\n';
diagram += 's2 : This is a state description<img/src';
diagram += "='1'/onerror=xssAttack()>";

View File

@ -93,7 +93,7 @@
throw new Error('XSS Succeeded');
}
var diagram = 'stateDiagram-v2\n';
let diagram = 'stateDiagram-v2\n';
diagram += 's2 : A<img/src';
diagram += "='1'/onerror=xssAttack()>";

View File

@ -93,7 +93,7 @@
throw new Error('XSS Succeeded');
}
var diagram = 'stateDiagram-v2\n';
let diagram = 'stateDiagram-v2\n';
diagram += 'if_state --> False: if n < 0<img/src';
diagram += "='1'/onerror=xssAttack()>";

View File

@ -93,7 +93,7 @@
throw new Error('XSS Succeeded');
}
var diagram = 'classDiagram\n';
let diagram = 'classDiagram\n';
diagram += 'classA <-- classB : <ifr';
diagram += "ame/srcdoc='<scr";
diagram += 'ipt>parent.xssAttack(`XSS`)</';

View File

@ -93,7 +93,7 @@
throw new Error('XSS Succeeded');
}
var diagram = `sequenceDiagram
let diagram = `sequenceDiagram
participant John
links John: {"XSS": "javas`;
diagram += `cript:alert('AudioParam')"}`;

View File

@ -93,7 +93,7 @@
throw new Error('XSS Succeeded');
}
var diagram = `sequenceDiagram
let diagram = `sequenceDiagram
participant Alice
links Alice: { "Click me!" : "javasjavascript:cript:alert('goose')" }`;

View File

@ -93,7 +93,7 @@
throw new Error('XSS Succeeded');
}
var diagram = `sequenceDiagram
let diagram = `sequenceDiagram
participant Alice
link Alice: Click Me!@javasjavascript:cript:alert("goose")`;

View File

@ -93,7 +93,7 @@
throw new Error('XSS Succeeded');
}
var diagram = `classDiagram
let diagram = `classDiagram
Class "<img/src='x'/onerror=xssAttack(1)>" <--> "<img/src='x'/onerror=xssAttack(2)>" C2: Cool label`;
// // var diagram = "stateDiagram-v2\n";

View File

@ -93,7 +93,7 @@
throw new Error('XSS Succeeded');
}
var diagram = `classDiagram
let diagram = `classDiagram
class Shape{
<<<img/src='1'/`;

View File

@ -54,9 +54,9 @@
startOnLoad: true,
useMaxWidth: true,
});
var cnt = 0;
var a;
var handler = setInterval(() => {
let cnt = 0;
let a;
const handler = setInterval(() => {
cnt++;
a = {};
if (typeof a.polluted !== 'undefined') {

View File

@ -96,7 +96,7 @@
// var diagram = ` graph TD
// A --> B["&lt;a href='javasc`;
// diagram += `ript#colon;xssAttack()'&gt;AAA&lt;/a&gt;"]`;
var diagram = ` graph TD
let diagram = ` graph TD
A --> B["<a href='javasc`;
diagram += `ript#colon;xssAttack()'>AAA</a>"]`;
// diagram += '//via.placeholder.com/64\' width=64 />"]';

View File

@ -96,7 +96,7 @@
// var diagram = ` graph TD
// A --> B["&lt;a href='javascript`;
// diagram += `ript#colon;xssAttack()'&gt;AAA&lt;/a&gt;"]`;
var diagram = ` graph TD
let diagram = ` graph TD
A --> B["<a href='javasc`;
diagram += `ript#9;t#colon;xssAttack()'>AAA</a>"]`;
// diagram += '//via.placeholder.com/64\' width=64 />"]';

View File

@ -42,9 +42,9 @@
startOnLoad: true,
useMaxWidth: true,
});
var cnt = 0;
var a;
var handler = setInterval(() => {
let cnt = 0;
let a;
const handler = setInterval(() => {
cnt++;
a = {};
if (typeof a.polluted !== 'undefined') {

View File

@ -85,7 +85,7 @@
alert('It worked');
}
var diagram = '%%{init: {"flowchart": {"htmlLabels": "true"}} }%%\n';
let diagram = '%%{init: {"flowchart": {"htmlLabels": "true"}} }%%\n';
diagram += 'flowchart\n';
diagram += 'A["<ifra';
diagram += "me srcdoc='<scrip";

View File

@ -92,7 +92,7 @@
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeeded');
}
var diagram = 'graph LR\n';
let diagram = 'graph LR\n';
diagram += 'B-->D("<img onerror=location=`java';
// diagram += "script\u003aalert\u0028document.domain\u0029\` src=x>\"\);\n";
diagram += 'script\x3a;xssAttack\u0028\u0029` src=x>");\n';

View File

@ -92,7 +92,7 @@
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeeded');
}
var diagram = 'graph LR\n';
let diagram = 'graph LR\n';
diagram += 'A(<img/src/onerror=xssAttack`1`>)';
// diagram += "script\u003aalert\u0028document.domain\u0029\` src=x>\"\);\n";
console.log(diagram);

View File

@ -92,7 +92,7 @@
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeeded');
}
var diagram = 'graph LR\n';
let diagram = 'graph LR\n';
diagram += " B(<a href='<";
diagram += 'script></';
diagram += "script>Javascript:xssAttack`1`'>Click)";

View File

@ -93,7 +93,7 @@
throw new Error('XSS Succeeded');
}
var diagram = 'stateDiagram-v2\n';
let diagram = 'stateDiagram-v2\n';
diagram += "<img/src='1'/onerror=xssAttack()> --> B";
// diagram += "script\u003aalert\u0028document.domain\u0029\` src=x>\"\);\n";
console.log(diagram);

View File

@ -93,7 +93,7 @@
throw new Error('XSS Succeeded');
}
var diagram = 'stateDiagram-v2\n';
let diagram = 'stateDiagram-v2\n';
diagram += "<img/src='1'/onerror=xssAttack()> --> B";
// diagram += "script\u003aalert\u0028document.domain\u0029\` src=x>\"\);\n";
console.log(diagram);

View File

@ -277,7 +277,7 @@
<script>
function testClick(nodeId) {
console.log('clicked', nodeId);
var originalBgColor = document.querySelector('body').style.backgroundColor;
let originalBgColor = document.querySelector('body').style.backgroundColor;
document.querySelector('body').style.backgroundColor = 'yellow';
setTimeout(function () {
document.querySelector('body').style.backgroundColor = originalBgColor;

View File

@ -46,7 +46,7 @@
<script>
function testClick(nodeId) {
console.log('clicked', nodeId);
var originalBgColor = document.querySelector('body').style.backgroundColor;
let originalBgColor = document.querySelector('body').style.backgroundColor;
document.querySelector('body').style.backgroundColor = 'yellow';
setTimeout(function () {
document.querySelector('body').style.backgroundColor = originalBgColor;

View File

@ -1513,7 +1513,7 @@
<script>
function testClick(nodeId) {
console.log('clicked', nodeId);
var originalBgColor = document.querySelector('body').style.backgroundColor;
let originalBgColor = document.querySelector('body').style.backgroundColor;
document.querySelector('body').style.backgroundColor = 'yellow';
setTimeout(function () {
document.querySelector('body').style.backgroundColor = originalBgColor;

View File

@ -174,7 +174,7 @@
}
function testClick(nodeId) {
console.log('clicked', nodeId);
var originalBgColor = document.querySelector('body').style.backgroundColor;
let originalBgColor = document.querySelector('body').style.backgroundColor;
document.querySelector('body').style.backgroundColor = 'yellow';
setTimeout(function () {
document.querySelector('body').style.backgroundColor = originalBgColor;

View File

@ -10,7 +10,7 @@ It is a JavaScript based diagramming and charting tool that renders Markdown-ins
<img src="img/header.png" alt="" />
[![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE)
[![Build CI Status](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml/badge.svg)](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml) [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid) [![NPM](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid) [![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [![Twitter Follow](https://img.shields.io/twitter/follow/mermaidjs_?style=social)](https://twitter.com/mermaidjs_)
<!-- Mermaid book banner -->
@ -271,16 +271,16 @@ To Deploy Mermaid:
### [Mermaid API](./Setup.md):
**To deploy mermaid without a bundler, one can insert a `script` tag with an absolute address and a `mermaidAPI` call into the HTML like so:**
**To deploy mermaid without a bundler, one can insert a `script` tag with an absolute address and a `mermaid.initialize` call into the HTML like so:**
```html
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
<script>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@9/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
```
**Doing so will command the mermaid parser to look for the `<div>` tags with `class="mermaid"`. From these tags mermaid will try to read the diagram/chart definitions and render them into SVG charts.**
**Doing so will command the mermaid parser to look for the `<div>` or `<pre>` tags with `class="mermaid"`. From these tags mermaid will try to read the diagram/chart definitions and render them into SVG charts.**
**Examples can be found at** [Other examples](/examples)

View File

@ -1561,7 +1561,7 @@ Returns **void**
```html
<script>
var config = {
const config = {
theme: 'default',
logLevel: 'fatal',
securityLevel: 'strict',

View File

@ -589,7 +589,7 @@ click Shape2 call callbackFunction() "This is a tooltip for a callback"
```html
<script>
var callbackFunction = function () {
const callbackFunction = function () {
alert('A callback was triggered');
};
</script>
@ -653,10 +653,10 @@ Beginner's tip—a full example using interactive links in an HTML page:
</pre>
<script>
var callback = function () {
const callback = function () {
alert('A callback was triggered');
};
var config = {
const config = {
startOnLoad: true,
securityLevel: 'loose',
};

View File

@ -649,7 +649,7 @@ A node can have click events bound that lead to either a JavaScript callback or
```html
<script>
var callback = function (nodeId) {
const callback = function (nodeId) {
alert('A callback was triggered on ' + nodeId);
};
</script>
@ -727,10 +727,10 @@ Beginner's tip—here's a full example of using interactive links in HTML:
</pre>
<script>
var callback = function () {
const callback = function () {
alert('A callback was triggered');
};
var config = {
const config = {
startOnLoad: true,
flowchart: {
useMaxWidth: true,

View File

@ -315,13 +315,13 @@ flowchart LR
### Dotted link
```mermaid-example
flowchart LR;
A-.->B;
flowchart LR
A-.->B
```
```mermaid
flowchart LR;
A-.->B;
flowchart LR
A-.->B
```
### Dotted link with text
@ -695,7 +695,7 @@ Examples of tooltip usage below:
```html
<script>
var callback = function () {
const callback = function () {
alert('A callback was triggered');
};
</script>
@ -771,10 +771,10 @@ Beginner's tip—a full example using interactive links in a html context:
</pre>
<script>
var callback = function () {
const callback = function () {
alert('A callback was triggered');
};
var config = {
const config = {
startOnLoad: true,
flowchart: { useMaxWidth: true, htmlLabels: true, curve: 'cardinal' },
securityLevel: 'loose',
@ -866,13 +866,13 @@ A shorter form of adding a class is to attach the classname to the node using th
```mermaid-example
flowchart LR
A:::someclass --> B
classDef someclass fill:#f96;
classDef someclass fill:#f96
```
```mermaid
flowchart LR
A:::someclass --> B
classDef someclass fill:#f96;
classDef someclass fill:#f96
```
### Css classes
@ -895,14 +895,14 @@ below:
**Example definition**
```mermaid-example
flowchart LR;
flowchart LR
A-->B[AAA<span>BBB</span>]
B-->D
class A cssClass
```
```mermaid
flowchart LR;
flowchart LR
A-->B[AAA<span>BBB</span>]
B-->D
class A cssClass
@ -924,7 +924,7 @@ The icons are accessed via the syntax fa:#icon class name#.
flowchart TD
B["fab:fa-twitter for peace"]
B-->C[fa:fa-ban forbidden]
B-->D(fa:fa-spinner);
B-->D(fa:fa-spinner)
B-->E(A fa:fa-camera-retro perhaps?)
```
@ -932,7 +932,7 @@ flowchart TD
flowchart TD
B["fab:fa-twitter for peace"]
B-->C[fa:fa-ban forbidden]
B-->D(fa:fa-spinner);
B-->D(fa:fa-spinner)
B-->E(A fa:fa-camera-retro perhaps?)
```

View File

@ -391,13 +391,13 @@ Beginner's tip—a full example using interactive links in an html context:
</pre>
<script>
var printArguments = function (arg1, arg2, arg3) {
const printArguments = function (arg1, arg2, arg3) {
alert('printArguments called with arguments: ' + arg1 + ', ' + arg2 + ', ' + arg3);
};
var printTask = function (taskId) {
const printTask = function (taskId) {
alert('taskId: ' + taskId);
};
var config = {
const config = {
startOnLoad: true,
securityLevel: 'loose',
};

View File

@ -21,21 +21,34 @@
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css"
/>
<script src="//cdn.jsdelivr.net/npm/mermaid@9.1.7/dist/mermaid.min.js"></script>
<!-- <script src="http://localhost:9000/mermaid.js"></script> -->
<script
defer=""
data-domain="mermaid-js.github.io"
src="https://plausible.io/js/plausible.js"
></script>
<script>
var require = {
paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.29.1/min/vs' },
const require = {
paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.0/min/vs' },
};
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.29.1/min/vs/loader.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.29.1/min/vs/editor/editor.main.nls.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.29.1/min/vs/editor/editor.main.js"></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.0/min/vs/loader.min.js"
integrity="sha512-6bIYsGqvLpAiEBXPdRQeFf5cueeBECtAKJjIHer3BhBZNTV3WLcLA8Tm3pDfxUwTMIS+kAZwTUvJ1IrMdX8C5w=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.0/min/vs/editor/editor.main.nls.min.js"
integrity="sha512-CCv+DKWw+yZhxf4Z+ExT6HC5G+3S45TeMTYcJyYbdrv4BpK2vyALJ4FoVR/KGWDIPu7w4tNCOC9MJQIkYPR5FA=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.0/min/vs/editor/editor.main.min.js"
integrity="sha512-iVHvVf6TQEoF5oQrocjP88wstImQHQZCxGsa5nKYOs6gXWzsV7QZHyk80HrXhrEWRJ1ADoIV6Uji3UUXtCmBMg=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
<script>
exports = {};
</script>
@ -50,17 +63,22 @@
<body>
<div id="app"></div>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@9/dist/mermaid.esm.min.mjs';
window.mermaid = mermaid;
</script>
<script>
var initEditor = exports.default;
var parser = new DOMParser();
var currentCodeExample = 0;
var colorize = [];
let initEditor = exports.default;
let parser = new DOMParser();
let currentCodeExample = 0;
let colorize = [];
let num = 0;
function colorizeEverything(html) {
initEditor(monaco);
return new Promise((resolve, reject) => {
monaco.editor.setTheme('mermaid');
var parsed = parser.parseFromString(html, 'text/html').body;
const parsed = parser.parseFromString(html, 'text/html').body;
Promise.all(
[...parsed.querySelectorAll('pre[id*="code"]')].map((codeBlock) =>
monaco.editor.colorize(codeBlock.innerText, 'mermaid')
@ -99,6 +117,7 @@
colorize.push(currentCodeExample);
return '<pre id="code' + currentCodeExample + '">' + escapeHTML(code) + '</pre>';
} else if (lang === 'mermaid') {
// TODO: This will need to be updated when render is async.
return (
'<pre class="mermaid">' + mermaid.render('mermaid-svg-' + num++, code) + '</pre>'
);
@ -117,7 +136,7 @@
function (hook, vm) {
hook.beforeEach(function (html) {
url = 'https://github.com/mermaid-js/mermaid/blob/develop/src/docs/' + vm.route.file;
var editHtml = '[:memo: Edit this Page](' + url + ')\n';
const editHtml = '[:memo: Edit this Page](' + url + ')\n';
return editHtml + html;
});
@ -136,7 +155,6 @@
],
};
var num = 0;
const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
const conf = {

View File

@ -75,23 +75,13 @@ The API works by pulling rendering instructions from the source `mermaid.js` in
### Requirements for the Mermaid API.
When writing the .html file, we give three instructions inside the html code to the web browser:
When writing the .html file, we give two instructions inside the html code to the web browser:
a. A reference for fetching the online mermaid renderer, through the `mermaid.js` or `mermaid.min.js`.
a. The mermaid code for the diagram we want to create.
b. 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 .
c. The `mermaid.initialize()` call, which dictates the appearance of diagrams and also starts the rendering process .
**a. A reference to the external CDN in a `<script src>` tag, or a reference to mermaid.js as a separate file.:**
```html
<body>
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
</body>
```
**b. The embedded mermaid diagram definition inside a `<pre class="mermaid">`:**
**a. The embedded mermaid diagram definition inside a `<pre class="mermaid">`:**
```html
<body>
@ -107,13 +97,14 @@ c. The `mermaid.initialize()` call, which dictates the appearance of diagrams an
**Notes**: Every Mermaid chart/graph/diagram definition, should have separate `<pre>` tags.
**c. The `mermaid.initialize()` call.**
**b. The import of mermaid and the `mermaid.initialize()` call.**
`mermaid.initialize()` call takes all the definitions contained in all the `<pre class="mermaid">` tags that it finds in the html body and renders them into diagrams. Example:
```html
<body>
<script>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@9/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
</body>
@ -135,11 +126,6 @@ Rendering in Mermaid is initialized by `mermaid.initialize()` call. You can plac
```html
<html>
<body>
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
<script>
mermaid.initialize({ startOnLoad: true });
</script>
Here is one mermaid diagram:
<pre class="mermaid">
graph TD
@ -156,6 +142,11 @@ Rendering in Mermaid is initialized by `mermaid.initialize()` call. You can plac
B -->|tcp_456| C[Server1]
B -->|tcp_456| D[Server2]
</pre>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@9/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
</body>
</html>
```
@ -181,8 +172,8 @@ In this example mermaid.js is referenced in `src` as a separate JavaScript file,
B --> C[Server1]
B --> D[Server2]
</pre>
<script src="The\Path\In\Your\Package\mermaid.js"></script>
<script>
<script type="module">
import mermaid from 'The/Path/In/Your/Package/mermaid.esm.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
</body>
@ -206,4 +197,4 @@ In this example mermaid.js is referenced in `src` as a separate JavaScript file,
**Comments from Knut Sveidqvist, creator of mermaid:**
- In early versions of mermaid, the `<script src>` tag was invoked in the `<head>` part of the web page. Nowadays we can place it in the `<body>` as seen above. Older parts of the documentation frequently reflects the previous way which still works.
- In early versions of mermaid, the `<script>` tag was invoked in the `<head>` part of the web page. Nowadays we can place it in the `<body>` as seen above. Older parts of the documentation frequently reflects the previous way which still works.

View File

@ -39,23 +39,9 @@ We have compiled some Video [Tutorials](./Tutorials.md) on how to use the mermai
> Note:This topic explored in greater depth in the [User Guide for Beginners](./n00b-gettingStarted.md)
The easiest way to integrate mermaid on a web page requires three elements:
The easiest way to integrate mermaid on a web page requires two elements:
1. Inclusion of the mermaid address in the html page using a `script` tag, in the `src` section.Example:
```html
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
```
2. The `mermaidAPI` call, in a separate `script` tag. Example:
```html
<script>
mermaid.initialize({ startOnLoad: true });
</script>
```
3. A graph definition, inside `<div>` tags labeled `class=mermaid`. Example:
- A graph definition, inside `<pre>` tags labeled `class=mermaid`. Example:
```html
<pre class="mermaid">
@ -66,8 +52,18 @@ The easiest way to integrate mermaid on a web page requires three elements:
</pre>
```
**Following these directions, mermaid starts at page load and (when the page has loaded) it will
locate the graph definitions inside the `div` tags with `class="mermaid"` and return diagrams in SVG form, following given definitions.**
- Inclusion of the mermaid address in the html page body using a `script` tag as an ESM import, and the `mermaidAPI` call.
Example:
```html
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@9/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
```
**Following these directions, mermaid starts at page load and (when the page has loaded) it will locate the graph definitions inside the `pre` tags with `class="mermaid"` and return diagrams in SVG form, following given definitions.**
## Simple full example:
@ -84,8 +80,8 @@ locate the graph definitions inside the `div` tags with `class="mermaid"` and re
B-->C[fa:fa-ban forbidden]
B-->D(fa:fa-spinner);
</pre>
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
<script>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@9/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
</body>
@ -204,18 +200,17 @@ fetch the graph definition from the site (perhaps from a textarea), render it an
The example below show an outline of how this could be used. The example just logs the resulting SVG to the JavaScript console.
```html
<script src="mermaid.js"></script>
<script>
<script type="module">
import mermaid from './mermaid.mjs';
mermaid.mermaidAPI.initialize({ startOnLoad: false });
$(function () {
$(async function () {
// Example of using the API var
element = document.querySelector('#graphDiv');
var insertSvg = function (svgCode, bindFunctions) {
const insertSvg = function (svgCode, bindFunctions) {
element.innerHTML = svgCode;
};
var graphDefinition = 'graph TB\na-->b';
var graph = mermaid.mermaidAPI.render('graphDiv', graphDefinition, insertSvg);
const graphDefinition = 'graph TB\na-->b';
const graph = await mermaid.mermaidAPI.render('graphDiv', graphDefinition, insertSvg);
});
</script>
```
@ -339,7 +334,7 @@ on what kind of integration you use.
```html
<script src="../dist/mermaid.js"></script>
<script>
var config = { startOnLoad: true, flowchart: { useMaxWidth: false, htmlLabels: true } };
let config = { startOnLoad: true, flowchart: { useMaxWidth: false, htmlLabels: true } };
mermaid.initialize(config);
</script>
```

View File

@ -7,7 +7,7 @@
"module": "dist/mermaid.core.mjs",
"types": "dist/mermaid.d.ts",
"type": "module",
"packageManager": "pnpm@7.13.2",
"packageManager": "pnpm@7.13.5",
"exports": {
".": {
"require": "./dist/mermaid.min.js",
@ -30,7 +30,7 @@
"build:types": "concurrently \"tsc -p ./packages/mermaid/tsconfig.json --emitDeclarationOnly\" \"tsc -p ./packages/mermaid-mindmap/tsconfig.json --emitDeclarationOnly\"",
"build:watch": "pnpm build:vite --watch",
"build": "pnpm run -r clean && concurrently \"pnpm build:vite\" \"pnpm build:types\"",
"dev": "concurrently \"pnpm build:vite --watch\" \"ts-node-esm .vite/server\"",
"dev": "concurrently \"pnpm build:vite --watch\" \"ts-node-esm .vite/server.ts\"",
"docs:build": "ts-node-esm --transpileOnly packages/mermaid/src/docs.mts",
"docs:verify": "pnpm docs:build --verify",
"todo-postbuild": "documentation build src/mermaidAPI.ts src/config.ts src/defaultConfig.ts --shallow -f md --markdown-toc false > src/docs/Setup.md && prettier --write src/docs/Setup.md",
@ -47,7 +47,8 @@
"e2e": "start-server-and-test dev http://localhost:9000/ cypress",
"ci": "vitest run",
"test": "pnpm lint && vitest run",
"test:watch": "vitest --coverage --watch",
"test:watch": "vitest --watch",
"test:coverage": "vitest --coverage",
"prepublishOnly": "pnpm build && pnpm test",
"prepare": "concurrently \"husky install\" \"pnpm build\"",
"pre-commit": "lint-staged"
@ -69,81 +70,82 @@
]
},
"dependencies": {
"@braintree/sanitize-url": "^6.0.0",
"@types/node": "^18.8.1",
"@types/uuid": "^8.3.4",
"d3": "^7.0.0",
"dagre": "^0.8.5",
"dagre-d3": "^0.6.4",
"@braintree/sanitize-url": "6.0.0",
"@types/node": "18.11.0",
"@types/uuid": "8.3.4",
"d3": "7.6.1",
"dagre": "0.8.5",
"dagre-d3": "0.6.4",
"dompurify": "2.4.0",
"fast-clone": "^1.5.13",
"graphlib": "^2.1.8",
"khroma": "^2.0.0",
"lodash": "^4.17.21",
"moment-mini": "^2.24.0",
"non-layered-tidy-tree-layout": "^2.0.2",
"rollup": "^2.79.1",
"stylis": "^4.1.2",
"uuid": "^9.0.0"
"fast-clone": "1.5.13",
"graphlib": "2.1.8",
"khroma": "2.0.0",
"lodash": "4.17.21",
"moment-mini": "2.29.4",
"non-layered-tidy-tree-layout": "2.0.2",
"rollup": "2.79.1",
"stylis": "4.1.2",
"uuid": "9.0.0"
},
"devDependencies": {
"@applitools/eyes-cypress": "^3.27.1",
"@commitlint/cli": "^17.1.2",
"@commitlint/config-conventional": "^17.1.0",
"@applitools/eyes-cypress": "3.27.2",
"@commitlint/cli": "17.1.2",
"@commitlint/config-conventional": "17.1.0",
"@cspell/eslint-plugin": "^6.12.0",
"@types/d3": "^7.4.0",
"@types/dompurify": "^2.3.4",
"@types/eslint": "^8.4.6",
"@types/express": "^4.17.14",
"@types/jsdom": "^20.0.0",
"@types/lodash": "^4.14.186",
"@types/prettier": "^2.7.1",
"@types/stylis": "^4.0.2",
"@typescript-eslint/eslint-plugin": "^5.39.0",
"@typescript-eslint/parser": "^5.39.0",
"@vitest/coverage-c8": "^0.23.4",
"@vitest/ui": "^0.23.4",
"concurrently": "^7.4.0",
"coveralls": "^3.1.1",
"cypress": "^10.0.0",
"cypress-image-snapshot": "^4.0.1",
"documentation": "13.2.0",
"esbuild": "^0.15.10",
"eslint": "^8.24.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-cypress": "^2.12.1",
"eslint-plugin-html": "^7.1.0",
"eslint-plugin-jest": "^27.1.0",
"eslint-plugin-jsdoc": "^39.3.6",
"eslint-plugin-json": "^3.1.0",
"eslint-plugin-markdown": "^3.0.0",
"express": "^4.18.1",
"globby": "^13.1.2",
"husky": "^8.0.1",
"identity-obj-proxy": "^3.0.0",
"jest": "29.x",
"jison": "^0.4.18",
"jsdom": "^20.0.1",
"lint-staged": "^13.0.3",
"markdown-it": "^13.0.1",
"path-browserify": "^1.0.1",
"pnpm": "^7.13.2",
"prettier": "^2.7.1",
"prettier-plugin-jsdoc": "^0.4.2",
"remark": "^14.0.2",
"rimraf": "^3.0.2",
"start-server-and-test": "^1.14.0",
"ts-node": "^10.9.1",
"typescript": "^4.8.4",
"unist-util-flatmap": "^1.0.0",
"vite": "^3.1.4",
"vitepress": "^1.0.0-alpha.19",
"vitepress-plugin-mermaid": "^2.0.8",
"vitepress-plugin-search": "^1.0.4-alpha.11",
"vitest": "^0.23.4"
"@types/d3": "7.4.0",
"@types/dompurify": "2.3.4",
"@types/eslint": "8.4.6",
"@types/express": "4.17.14",
"@types/jsdom": "20.0.0",
"@types/lodash": "4.14.186",
"@types/mdast": "3.0.10",
"@types/prettier": "2.7.1",
"@types/stylis": "4.0.2",
"@typescript-eslint/eslint-plugin": "5.40.0",
"@typescript-eslint/parser": "5.40.0",
"@vitest/coverage-c8": "0.24.3",
"@vitest/ui": "0.24.3",
"concurrently": "7.4.0",
"coveralls": "3.1.1",
"cypress": "10.10.0",
"cypress-image-snapshot": "4.0.1",
"documentation": "13.2.5",
"esbuild": "0.15.11",
"eslint": "8.25.0",
"eslint-config-prettier": "8.5.0",
"eslint-plugin-cypress": "2.12.1",
"eslint-plugin-html": "7.1.0",
"eslint-plugin-jest": "27.1.2",
"eslint-plugin-jsdoc": "39.3.6",
"eslint-plugin-json": "3.1.0",
"eslint-plugin-markdown": "3.0.0",
"express": "4.18.2",
"globby": "13.1.2",
"husky": "8.0.1",
"identity-obj-proxy": "3.0.0",
"jest": "29.2.0",
"jison": "0.4.18",
"jsdom": "20.0.1",
"lint-staged": "13.0.3",
"markdown-it": "13.0.1",
"path-browserify": "1.0.1",
"pnpm": "7.13.5",
"prettier": "2.7.1",
"prettier-plugin-jsdoc": "0.4.2",
"remark": "14.0.2",
"rimraf": "3.0.2",
"start-server-and-test": "1.14.0",
"ts-node": "10.9.1",
"typescript": "4.8.4",
"unist-util-flatmap": "1.0.0",
"vite": "3.1.8",
"vitepress": "1.0.0-alpha.21",
"vitepress-plugin-mermaid": "2.0.8",
"vitepress-plugin-search": "1.0.4-alpha.11",
"vitest": "0.24.3"
},
"resolutions": {
"d3": "^7.0.0"
"d3": "7.6.1"
},
"files": [
"dist"
@ -151,5 +153,8 @@
"sideEffects": [
"**/*.css",
"**/*.scss"
]
],
"volta": {
"node": "18.5.0"
}
}

View File

@ -50,8 +50,8 @@
},
"dependencies": {},
"devDependencies": {
"concurrently": "^7.4.0",
"rimraf": "^3.0.2"
"concurrently": "7.4.0",
"rimraf": "3.0.2"
},
"resolutions": {
"d3": "^7.0.0"

View File

@ -57,8 +57,8 @@
"non-layered-tidy-tree-layout": "^2.0.2"
},
"devDependencies": {
"concurrently": "^7.4.0",
"rimraf": "^3.0.2"
"concurrently": "7.4.0",
"rimraf": "3.0.2"
},
"resolutions": {
"d3": "^7.0.0"

View File

@ -75,51 +75,51 @@
"stylis": "^4.1.2"
},
"devDependencies": {
"@applitools/eyes-cypress": "^3.25.7",
"@commitlint/cli": "^17.1.2",
"@commitlint/config-conventional": "^17.0.0",
"@types/d3": "^7.4.0",
"@types/dompurify": "^2.3.4",
"@types/eslint": "^8.4.6",
"@types/express": "^4.17.13",
"@types/jsdom": "^20.0.0",
"@types/lodash": "^4.14.185",
"@types/prettier": "^2.7.0",
"@types/stylis": "^4.0.2",
"@typescript-eslint/eslint-plugin": "^5.37.0",
"@typescript-eslint/parser": "^5.37.0",
"concurrently": "^7.4.0",
"coveralls": "^3.1.1",
"cypress": "^10.0.0",
"cypress-image-snapshot": "^4.0.1",
"documentation": "13.2.0",
"esbuild": "^0.15.8",
"eslint": "^8.23.1",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-cypress": "^2.12.1",
"eslint-plugin-html": "^7.1.0",
"eslint-plugin-jest": "^27.0.4",
"eslint-plugin-jsdoc": "^39.3.6",
"eslint-plugin-json": "^3.1.0",
"eslint-plugin-markdown": "^3.0.0",
"express": "^4.18.1",
"globby": "^13.1.2",
"husky": "^8.0.0",
"identity-obj-proxy": "^3.0.0",
"jison": "^0.4.18",
"@applitools/eyes-cypress": "3.27.2",
"@commitlint/cli": "17.1.2",
"@commitlint/config-conventional": "17.1.0",
"@types/d3": "7.4.0",
"@types/dompurify": "2.3.4",
"@types/eslint": "8.4.6",
"@types/express": "4.17.14",
"@types/jsdom": "20.0.0",
"@types/lodash": "4.14.186",
"@types/prettier": "2.7.1",
"@types/stylis": "4.0.2",
"@typescript-eslint/eslint-plugin": "5.40.0",
"@typescript-eslint/parser": "5.40.0",
"concurrently": "7.4.0",
"coveralls": "3.1.1",
"cypress": "10.10.0",
"cypress-image-snapshot": "4.0.1",
"documentation": "13.2.5",
"esbuild": "0.15.11",
"eslint": "8.25.0",
"eslint-config-prettier": "8.5.0",
"eslint-plugin-cypress": "2.12.1",
"eslint-plugin-html": "7.1.0",
"eslint-plugin-jest": "27.1.2",
"eslint-plugin-jsdoc": "39.3.6",
"eslint-plugin-json": "3.1.0",
"eslint-plugin-markdown": "3.0.0",
"express": "4.18.2",
"globby": "13.1.2",
"husky": "8.0.1",
"identity-obj-proxy": "3.0.0",
"jison": "0.4.18",
"js-base64": "3.7.2",
"jsdom": "^20.0.0",
"lint-staged": "^13.0.0",
"moment": "^2.23.0",
"path-browserify": "^1.0.1",
"prettier": "^2.7.1",
"prettier-plugin-jsdoc": "^0.4.2",
"remark": "^14.0.2",
"rimraf": "^3.0.2",
"start-server-and-test": "^1.12.6",
"ts-node": "^10.9.1",
"typescript": "^4.8.3",
"unist-util-flatmap": "^1.0.0"
"jsdom": "20.0.1",
"lint-staged": "13.0.3",
"moment": "2.29.4",
"path-browserify": "1.0.1",
"prettier": "2.7.1",
"prettier-plugin-jsdoc": "0.4.2",
"remark": "14.0.2",
"rimraf": "3.0.2",
"start-server-and-test": "1.14.0",
"ts-node": "10.9.1",
"typescript": "4.8.4",
"unist-util-flatmap": "1.0.0"
},
"resolutions": {
"d3": "^7.0.0"

View File

@ -2,17 +2,26 @@ import * as configApi from './config';
import { log } from './logger';
import { getDiagram, registerDiagram } from './diagram-api/diagramAPI';
import { detectType, getDiagramLoader } from './diagram-api/detectType';
import { isDetailedError } from './utils';
import { isDetailedError, type DetailedError } from './utils';
export type ParseErrorFunction = (err: string | DetailedError, hash?: any) => void;
export class Diagram {
type = 'graph';
parser;
renderer;
db;
// eslint-disable-next-line @typescript-eslint/ban-types
constructor(public txt: string, parseError?: Function) {
private detectTypeFailed = false;
constructor(public txt: string, parseError?: ParseErrorFunction) {
const cnf = configApi.getConfig();
this.txt = txt;
try {
this.type = detectType(txt, cnf);
} catch (e) {
this.handleError(e, parseError);
this.type = 'error';
this.detectTypeFailed = true;
}
const diagram = getDiagram(this.type);
log.debug('Type ' + this.type);
// Setup diagram
@ -30,31 +39,39 @@ export class Diagram {
this.parse(this.txt, parseError);
}
// eslint-disable-next-line @typescript-eslint/ban-types
parse(text: string, parseError?: Function): boolean {
parse(text: string, parseError?: ParseErrorFunction): boolean {
if (this.detectTypeFailed) {
return false;
}
try {
text = text + '\n';
this.db.clear();
this.parser.parse(text);
return true;
} catch (error) {
this.handleError(error, parseError);
}
return false;
}
handleError(error: unknown, parseError?: ParseErrorFunction) {
// Is this the correct way to access mermiad's parseError()
// method ? (or global.mermaid.parseError()) ?
if (parseError) {
if (isDetailedError(error)) {
// handle case where error string and hash were
// wrapped in object like`const error = { str, hash };`
parseError(error.str, error.hash);
} else {
// assume it is just error string and pass it on
parseError(error);
}
} else {
if (parseError === undefined) {
// No mermaid.parseError() handler defined, so re-throw it
throw error;
}
if (isDetailedError(error)) {
// Handle case where error string and hash were
// wrapped in object like`const error = { str, hash };`
parseError(error.str, error.hash);
return;
}
return false;
// Otherwise, assume it is just an error string and pass it on
parseError(error as string);
}
getParser() {
@ -66,10 +83,10 @@ export class Diagram {
}
}
export default Diagram;
// eslint-disable-next-line @typescript-eslint/ban-types
export const getDiagramFromText = async (txt: string, parseError?: Function) => {
export const getDiagramFromText = async (
txt: string,
parseError?: ParseErrorFunction
): Promise<Diagram> => {
const type = detectType(txt, configApi.getConfig());
try {
// Trying to find the diagram
@ -80,23 +97,13 @@ export const getDiagramFromText = async (txt: string, parseError?: Function) =>
throw new Error(`Diagram ${type} not found.`);
}
// Diagram not available, loading it
// const path = getPathForDiagram(type);
const { diagram } = await loader(); // eslint-disable-line @typescript-eslint/no-explicit-any
registerDiagram(
type,
{
db: diagram.db,
renderer: diagram.renderer,
parser: diagram.parser,
styles: diagram.styles,
},
diagram.injectUtils
);
// await loadDiagram('./packages/mermaid-mindmap/dist/mermaid-mindmap.js');
// await loadDiagram(path + 'mermaid-' + type + '.js');
const { diagram } = await loader();
registerDiagram(type, diagram, undefined, diagram.injectUtils);
// new diagram will try getDiagram again and if fails then it is a valid throw
}
// If either of the above worked, we have the diagram
// logic and can continue
return new Diagram(txt, parseError);
};
export default Diagram;

View File

@ -6,22 +6,17 @@
import * as configApi from '../config';
import { vi } from 'vitest';
import { addDiagrams } from '../diagram-api/diagram-orchestration';
import Diagram from '../Diagram';
import Diagram, { type ParseErrorFunction } from '../Diagram';
// Normally, we could just do the following to get the original `parse()`
// implementation, however, requireActual returns a promise and it's not documented how to use withing mock file.
let hasLoadedDiagrams = false;
/**
* @param text
* @param parseError
*/
// eslint-disable-next-line @typescript-eslint/ban-types
function parse(text: string, parseError?: Function): boolean {
if (!hasLoadedDiagrams) {
function parse(text: string, parseError?: ParseErrorFunction): boolean {
addDiagrams();
hasLoadedDiagrams = true;
}
const diagram = new Diagram(text, parseError);
return diagram.parse(text, parseError);
}

View File

@ -3,7 +3,7 @@
import DOMPurify from 'dompurify';
export interface MermaidConfig {
lazyLoadedDiagrams?: any;
lazyLoadedDiagrams?: string[];
theme?: string;
themeVariables?: any;
themeCSS?: string;

View File

@ -1,8 +1,7 @@
import { MermaidConfig } from '../config.type';
import { log } from '../logger';
import { DetectorRecord, DiagramDetector, DiagramLoader } from './types';
export type DiagramDetector = (text: string, config?: MermaidConfig) => boolean;
export type DiagramLoader = (() => any) | null;
export type DetectorRecord = { detector: DiagramDetector; loader: DiagramLoader };
const directive =
/[%]{2}[{]\s*(?:(?:(\w+)\s*:|(\w+))\s*(?:(?:(\w+))|((?:(?![}][%]{2}).|\r?\n)*))?\s*)(?:[}][%]{2})?/gi;
const anyComment = /\s*%%.*\n/gm;
@ -34,26 +33,22 @@ const detectors: Record<string, DetectorRecord> = {};
*/
export const detectType = function (text: string, config?: MermaidConfig): string {
text = text.replace(directive, '').replace(anyComment, '\n');
// console.log(detectors);
for (const [key, { detector }] of Object.entries(detectors)) {
const diagram = detector(text, config);
if (diagram) {
return key;
}
}
// TODO: #3391
// throw new Error(`No diagram type detected for text: ${text}`);
return 'flowchart';
throw new Error(`No diagram type detected for text: ${text}`);
};
export const addDetector = (
key: string,
detector: DiagramDetector,
loader: DiagramLoader | null
) => {
export const addDetector = (key: string, detector: DiagramDetector, loader?: DiagramLoader) => {
if (detectors[key]) {
throw new Error(`Detector with key ${key} already exists`);
}
detectors[key] = { detector, loader };
log.debug(`Detector with key ${key} added${loader ? ' with loader' : ''}`);
};
export const getDiagramLoader = (key: string) => detectors[key].loader;

View File

@ -1,16 +1,4 @@
import {
registerDiagram,
registerDetector,
DiagramDefinition,
DiagramDetector,
} from './diagramAPI';
// // @ts-ignore: TODO Fix ts errors
// import mindmapParser from '../diagrams/mindmap/parser/mindmap';
// import * as mindmapDb from '../diagrams/mindmap/mindmapDb';
// import { mindmapDetector } from '../diagrams/mindmap/mindmapDetector';
// import mindmapRenderer from '../diagrams/mindmap/mindmapRenderer';
// import mindmapStyles from '../diagrams/mindmap/styles';
import { registerDiagram } from './diagramAPI';
// @ts-ignore: TODO Fix ts errors
import gitGraphParser from '../diagrams/git/parser/gitGraph';
@ -106,17 +94,15 @@ import { setConfig } from '../config';
import errorRenderer from '../diagrams/error/errorRenderer';
import errorStyles from '../diagrams/error/styles';
const registerDiagramAndDetector = (
id: string,
diagram: DiagramDefinition,
detector: DiagramDetector
) => {
registerDiagram(id, diagram);
registerDetector(id, detector);
};
let hasLoadedDiagrams = false;
export const addDiagrams = () => {
registerDiagramAndDetector(
if (hasLoadedDiagrams) {
return;
}
// This is added here to avoid race-conditions.
// We could optimize the loading logic somehow.
hasLoadedDiagrams = true;
registerDiagram(
'error',
// Special diagram with error messages but setup as a regular diagram
{
@ -140,7 +126,7 @@ export const addDiagrams = () => {
(text) => text.toLowerCase().trim() === 'error'
);
registerDiagramAndDetector(
registerDiagram(
'c4',
{
parser: c4Parser,
@ -153,7 +139,7 @@ export const addDiagrams = () => {
},
c4Detector
);
registerDiagramAndDetector(
registerDiagram(
'class',
{
parser: classParser,
@ -170,7 +156,7 @@ export const addDiagrams = () => {
},
classDetector
);
registerDiagramAndDetector(
registerDiagram(
'classDiagram',
{
parser: classParser,
@ -187,7 +173,7 @@ export const addDiagrams = () => {
},
classDetectorV2
);
registerDiagramAndDetector(
registerDiagram(
'er',
{
parser: erParser,
@ -197,7 +183,7 @@ export const addDiagrams = () => {
},
erDetector
);
registerDiagramAndDetector(
registerDiagram(
'gantt',
{
parser: ganttParser,
@ -207,7 +193,7 @@ export const addDiagrams = () => {
},
ganttDetector
);
registerDiagramAndDetector(
registerDiagram(
'info',
{
parser: infoParser,
@ -217,7 +203,7 @@ export const addDiagrams = () => {
},
infoDetector
);
registerDiagramAndDetector(
registerDiagram(
'pie',
{
parser: pieParser,
@ -227,7 +213,7 @@ export const addDiagrams = () => {
},
pieDetector
);
registerDiagramAndDetector(
registerDiagram(
'requirement',
{
parser: requirementParser,
@ -237,7 +223,7 @@ export const addDiagrams = () => {
},
requirementDetector
);
registerDiagramAndDetector(
registerDiagram(
'sequence',
{
parser: sequenceParser,
@ -260,7 +246,7 @@ export const addDiagrams = () => {
},
sequenceDetector
);
registerDiagramAndDetector(
registerDiagram(
'state',
{
parser: stateParser,
@ -277,7 +263,7 @@ export const addDiagrams = () => {
},
stateDetector
);
registerDiagramAndDetector(
registerDiagram(
'stateDiagram',
{
parser: stateParser,
@ -294,7 +280,7 @@ export const addDiagrams = () => {
},
stateDetectorV2
);
registerDiagramAndDetector(
registerDiagram(
'journey',
{
parser: journeyParser,
@ -309,7 +295,7 @@ export const addDiagrams = () => {
journeyDetector
);
registerDiagramAndDetector(
registerDiagram(
'flowchart',
{
parser: flowParser,
@ -329,7 +315,7 @@ export const addDiagrams = () => {
},
flowDetector
);
registerDiagramAndDetector(
registerDiagram(
'flowchart-v2',
{
parser: flowParser,
@ -350,14 +336,9 @@ export const addDiagrams = () => {
},
flowDetectorV2
);
registerDiagramAndDetector(
registerDiagram(
'gitGraph',
{ parser: gitGraphParser, db: gitGraphDb, renderer: gitGraphRenderer, styles: gitGraphStyles },
gitGraphDetector
);
// registerDiagram(
// 'mindmap',
// { parser: mindmapParser, db: mindmapDb, renderer: mindmapRenderer, styles: mindmapStyles },
// mindmapDetector
// );
};

View File

@ -1,6 +1,7 @@
import { detectType, DiagramDetector } from './detectType';
import { getDiagram, registerDiagram, registerDetector } from './diagramAPI';
import { detectType } from './detectType';
import { getDiagram, registerDiagram } from './diagramAPI';
import { addDiagrams } from './diagram-orchestration';
import { DiagramDetector } from './types';
addDiagrams();
@ -15,17 +16,22 @@ describe('DiagramAPI', () => {
it('should handle diagram registrations', () => {
expect(() => getDiagram('loki')).toThrow();
expect(() => detectType('loki diagram')).not.toThrow(); // TODO: #3391
expect(() => detectType('loki diagram')).toThrow(
'No diagram type detected for text: loki diagram'
);
const detector: DiagramDetector = (str: string) => {
return str.match('loki') !== null;
};
registerDetector('loki', detector);
registerDiagram('loki', {
registerDiagram(
'loki',
{
db: {},
parser: {},
renderer: {},
styles: {},
});
},
detector
);
expect(getDiagram('loki')).not.toBeNull();
expect(detectType('loki diagram')).toBe('loki');
});

View File

@ -1,10 +1,10 @@
import { addDetector, DiagramDetector as _DiagramDetector } from './detectType';
import { addDetector } from './detectType';
import { log as _log, setLogLevel as _setLogLevel } from '../logger';
import { getConfig as _getConfig } from '../config';
import { sanitizeText as _sanitizeText } from '../diagrams/common/common';
import { MermaidConfig } from '../config.type';
import { setupGraphViewbox as _setupGraphViewbox } from '../setupGraphViewbox';
import { addStylesForDiagram } from '../styles';
import { DiagramDefinition, DiagramDetector } from './types';
/*
Packaging and exposing resources for external diagrams so that they can import
@ -13,41 +13,19 @@ import { addStylesForDiagram } from '../styles';
*/
export const log = _log;
export const setLogLevel = _setLogLevel;
export type DiagramDetector = _DiagramDetector;
export const getConfig = _getConfig;
export const sanitizeText = (text: string) => _sanitizeText(text, getConfig());
export const setupGraphViewbox = _setupGraphViewbox;
export interface InjectUtils {
_log: any;
_setLogLevel: any;
_getConfig: any;
_sanitizeText: any;
_setupGraphViewbox: any;
}
export interface DiagramDefinition {
db: any;
renderer: any;
parser: any;
styles: any;
init?: (config: MermaidConfig) => void;
injectUtils?: (utils: InjectUtils) => void;
}
const diagrams: Record<string, DiagramDefinition> = {};
const connectCallbacks: Record<string, any> = {}; // TODO fix, eslint-disable-line @typescript-eslint/no-explicit-any
export interface Detectors {
[key: string]: DiagramDetector;
}
export const registerDetector = (id: string, detector: DiagramDetector) => {
addDetector(id, detector, null);
};
export const registerDiagram = (
id: string,
diagram: DiagramDefinition,
detector?: DiagramDetector,
callback?: (
_log: any,
_setLogLevel: any,
@ -57,9 +35,12 @@ export const registerDiagram = (
) => void
) => {
if (diagrams[id]) {
log.warn(`Diagram ${id} already registered.`);
throw new Error(`Diagram ${id} already registered.`);
}
diagrams[id] = diagram;
if (detector) {
addDetector(id, detector);
}
addStylesForDiagram(id, diagram.styles);
if (typeof callback !== 'undefined') {
callback(log, setLogLevel, getConfig, sanitizeText, setupGraphViewbox);
@ -72,19 +53,3 @@ export const getDiagram = (name: string): DiagramDefinition => {
}
throw new Error(`Diagram ${name} not found.`);
};
/**
*
* @param sScriptSrc
*/
export const loadDiagram = (sScriptSrc: string) =>
new Promise((resolve) => {
const oHead = document.getElementsByTagName('HEAD')[0];
const oScript = document.createElement('script');
oScript.type = 'text/javascript';
oScript.src = sScriptSrc;
oHead.appendChild(oScript);
oScript.onload = () => {
resolve(true);
};
});

View File

@ -1,227 +0,0 @@
export const lineBreakRegex = /<br\s*\/?>/gi;
/**
* Caches results of functions based on input
*
* @param {Function} fn Function to run
* @param {Function} resolver Function that resolves to an ID given arguments the `fn` takes
* @returns {Function} An optimized caching function
*/
const memoize = (fn, resolver) => {
let cache = {};
return (...args) => {
let n = resolver ? resolver.apply(this, args) : args[0];
if (n in cache) {
return cache[n];
} else {
let result = fn(...args);
cache[n] = result;
return result;
}
};
};
/**
* This calculates the width of the given text, font size and family.
*
* @param {any} text - The text to calculate the width of
* @param {any} config - The config for fontSize, fontFamily, and fontWeight all impacting the resulting size
* @returns {any} - The width for the given text
*/
export const calculateTextWidth = function (text, config) {
config = Object.assign({ fontSize: 12, fontWeight: 400, fontFamily: 'Arial' }, config);
return calculateTextDimensions(text, config).width;
};
export const getTextObj = function () {
return {
x: 0,
y: 0,
fill: undefined,
anchor: 'start',
style: '#666',
width: 100,
height: 100,
textMargin: 0,
rx: 0,
ry: 0,
valign: undefined,
};
};
/**
* Adds text to an element
*
* @param {SVGElement} elem Element to add text to
* @param {{
* text: string;
* x: number;
* y: number;
* anchor: 'start' | 'middle' | 'end';
* fontFamily: string;
* fontSize: string | number;
* fontWeight: string | number;
* fill: string;
* class: string | undefined;
* textMargin: number;
* }} textData
* @returns {SVGTextElement} Text element with given styling and content
*/
export const drawSimpleText = function (elem, textData) {
// Remove and ignore br:s
const nText = textData.text.replace(lineBreakRegex, ' ');
const textElem = elem.append('text');
textElem.attr('x', textData.x);
textElem.attr('y', textData.y);
textElem.style('text-anchor', textData.anchor);
textElem.style('font-family', textData.fontFamily);
textElem.style('font-size', textData.fontSize);
textElem.style('font-weight', textData.fontWeight);
textElem.attr('fill', textData.fill);
if (typeof textData.class !== 'undefined') {
textElem.attr('class', textData.class);
}
const span = textElem.append('tspan');
span.attr('x', textData.x + textData.textMargin * 2);
span.attr('fill', textData.fill);
span.text(nText);
return textElem;
};
/**
* This calculates the dimensions of the given text, font size, font family, font weight, and margins.
*
* @param {any} text - The text to calculate the width of
* @param {any} config - The config for fontSize, fontFamily, fontWeight, and margin all impacting
* the resulting size
* @returns - The width for the given text
*/
export const calculateTextDimensions = memoize(
function (text, config) {
config = Object.assign({ fontSize: 12, fontWeight: 400, fontFamily: 'Arial' }, config);
const { fontSize, fontFamily, fontWeight } = config;
if (!text) {
return { width: 0, height: 0 };
}
// We can't really know if the user supplied font family will render on the user agent;
// thus, we'll take the max width between the user supplied font family, and a default
// of sans-serif.
const fontFamilies = ['sans-serif', fontFamily];
const lines = text.split(common.lineBreakRegex);
let dims = [];
const body = select('body');
// We don't want to leak DOM elements - if a removal operation isn't available
// for any reason, do not continue.
if (!body.remove) {
return { width: 0, height: 0, lineHeight: 0 };
}
const g = body.append('svg');
for (let fontFamily of fontFamilies) {
let cheight = 0;
let dim = { width: 0, height: 0, lineHeight: 0 };
for (let line of lines) {
const textObj = getTextObj();
textObj.text = line;
const textElem = drawSimpleText(g, textObj)
.style('font-size', fontSize)
.style('font-weight', fontWeight)
.style('font-family', fontFamily);
let bBox = (textElem._groups || textElem)[0][0].getBBox();
dim.width = Math.round(Math.max(dim.width, bBox.width));
cheight = Math.round(bBox.height);
dim.height += cheight;
dim.lineHeight = Math.round(Math.max(dim.lineHeight, cheight));
}
dims.push(dim);
}
g.remove();
let index =
isNaN(dims[1].height) ||
isNaN(dims[1].width) ||
isNaN(dims[1].lineHeight) ||
(dims[0].height > dims[1].height &&
dims[0].width > dims[1].width &&
dims[0].lineHeight > dims[1].lineHeight)
? 0
: 1;
return dims[index];
},
(text, config) => `${text}-${config.fontSize}-${config.fontWeight}-${config.fontFamily}`
);
const breakString = memoize(
(word, maxWidth, hyphenCharacter = '-', config) => {
config = Object.assign(
{ fontSize: 12, fontWeight: 400, fontFamily: 'Arial', margin: 0 },
config
);
const characters = word.split('');
const lines = [];
let currentLine = '';
characters.forEach((character, index) => {
const nextLine = `${currentLine}${character}`;
const lineWidth = calculateTextWidth(nextLine, config);
if (lineWidth >= maxWidth) {
const currentCharacter = index + 1;
const isLastLine = characters.length === currentCharacter;
const hyphenatedNextLine = `${nextLine}${hyphenCharacter}`;
lines.push(isLastLine ? nextLine : hyphenatedNextLine);
currentLine = '';
} else {
currentLine = nextLine;
}
});
return { hyphenatedStrings: lines, remainingWord: currentLine };
},
(word, maxWidth, hyphenCharacter = '-', config) =>
`${word}-${maxWidth}-${hyphenCharacter}-${config.fontSize}-${config.fontWeight}-${config.fontFamily}`
);
export const wrapLabel = memoize(
(label, maxWidth, config) => {
if (!label) {
return label;
}
config = Object.assign(
{ fontSize: 12, fontWeight: 400, fontFamily: 'Arial', joinWith: '<br/>' },
config
);
if (lineBreakRegex.test(label)) {
return label;
}
const words = label.split(' ');
const completedLines = [];
let nextLine = '';
words.forEach((word, index) => {
const wordLength = calculateTextWidth(`${word} `, config);
const nextLineLength = calculateTextWidth(nextLine, config);
if (wordLength > maxWidth) {
const { hyphenatedStrings, remainingWord } = breakString(word, maxWidth, '-', config);
completedLines.push(nextLine, ...hyphenatedStrings);
nextLine = remainingWord;
} else if (nextLineLength + wordLength >= maxWidth) {
completedLines.push(nextLine);
nextLine = word;
} else {
nextLine = [nextLine, word].filter(Boolean).join(' ');
}
const currentWord = index + 1;
const isLastWord = currentWord === words.length;
if (isLastWord) {
completedLines.push(nextLine);
}
});
return completedLines.filter((line) => line !== '').join(config.joinWith);
},
(label, maxWidth, config) =>
`${label}-${maxWidth}-${config.fontSize}-${config.fontWeight}-${config.fontFamily}-${config.joinWith}`
);

View File

@ -0,0 +1,26 @@
import { MermaidConfig } from '../config.type';
export interface InjectUtils {
_log: any;
_setLogLevel: any;
_getConfig: any;
_sanitizeText: any;
_setupGraphViewbox: any;
}
export interface DiagramDefinition {
db: any;
renderer: any;
parser: any;
styles: any;
init?: (config: MermaidConfig) => void;
injectUtils?: (utils: InjectUtils) => void;
}
export interface DetectorRecord {
detector: DiagramDetector;
loader?: DiagramLoader;
}
export type DiagramDetector = (text: string, config?: MermaidConfig) => boolean;
export type DiagramLoader = (() => Promise<{ id: string; diagram: DiagramDefinition }>) | null;

View File

@ -1,4 +1,4 @@
import type { DiagramDetector } from '../../diagram-api/detectType';
import type { DiagramDetector } from '../../diagram-api/types';
export const c4Detector: DiagramDetector = (txt) => {
return txt.match(/^\s*C4Context|C4Container|C4Component|C4Dynamic|C4Deployment/) !== null;

View File

@ -1,4 +1,4 @@
import type { DiagramDetector } from '../../diagram-api/detectType';
import type { DiagramDetector } from '../../diagram-api/types';
export const classDetectorV2: 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

View File

@ -1,4 +1,4 @@
import type { DiagramDetector } from '../../diagram-api/detectType';
import type { DiagramDetector } from '../../diagram-api/types';
export const classDetector: DiagramDetector = (txt, config) => {
// If we have configured to use dagre-wrapper then we should never return true in this function

View File

@ -1,4 +1,4 @@
import type { DiagramDetector } from '../../diagram-api/detectType';
import type { DiagramDetector } from '../../diagram-api/types';
export const erDetector: DiagramDetector = (txt) => {
return txt.match(/^\s*erDiagram/) !== null;

View File

@ -429,8 +429,7 @@ export const clear = function (ver = 'gen-1') {
vertices = {};
classes = {};
edges = [];
funs = [];
funs.push(setupToolTips);
funs = [setupToolTips];
subGraphs = [];
subGraphLookup = {};
subCount = 0;

View File

@ -1,4 +1,4 @@
import type { DiagramDetector } from '../../diagram-api/detectType';
import type { DiagramDetector } from '../../diagram-api/types';
export const flowDetectorV2: DiagramDetector = (txt, config) => {
// If we have configured to use dagre-wrapper then we should return true in this function for graph code thus making it use the new flowchart diagram

View File

@ -1,4 +1,4 @@
import type { DiagramDetector } from '../../diagram-api/detectType';
import type { DiagramDetector } from '../../diagram-api/types';
export const flowDetector: DiagramDetector = (txt, config) => {
// If we have conferred to only use new flow charts this function should always return false

View File

@ -1,4 +1,4 @@
import type { DiagramDetector } from '../../diagram-api/detectType';
import type { DiagramDetector } from '../../diagram-api/types';
export const ganttDetector: DiagramDetector = (txt) => {
return txt.match(/^\s*gantt/) !== null;

View File

@ -1,4 +1,4 @@
import type { DiagramDetector } from '../../diagram-api/detectType';
import type { DiagramDetector } from '../../diagram-api/types';
export const gitGraphDetector: DiagramDetector = (txt) => {
return txt.match(/^\s*gitGraph/) !== null;

View File

@ -1,4 +1,4 @@
import type { DiagramDetector } from '../../diagram-api/detectType';
import type { DiagramDetector } from '../../diagram-api/types';
export const infoDetector: DiagramDetector = (txt) => {
return txt.match(/^\s*info/) !== null;

View File

@ -1,4 +1,4 @@
import type { DiagramDetector } from '../../diagram-api/detectType';
import type { DiagramDetector } from '../../diagram-api/types';
export const pieDetector: DiagramDetector = (txt) => {
return txt.match(/^\s*pie/) !== null;

View File

@ -1,4 +1,4 @@
import type { DiagramDetector } from '../../diagram-api/detectType';
import type { DiagramDetector } from '../../diagram-api/types';
export const requirementDetector: DiagramDetector = (txt) => {
return txt.match(/^\s*requirement(Diagram)?/) !== null;

View File

@ -1,4 +1,4 @@
import type { DiagramDetector } from '../../diagram-api/detectType';
import type { DiagramDetector } from '../../diagram-api/types';
export const sequenceDetector: DiagramDetector = (txt) => {
return txt.match(/^\s*sequenceDiagram/) !== null;

View File

@ -1,4 +1,4 @@
import type { DiagramDetector } from '../../diagram-api/detectType';
import type { DiagramDetector } from '../../diagram-api/types';
export const stateDetectorV2: DiagramDetector = (text, config) => {
if (text.match(/^\s*stateDiagram-v2/) !== null) return true;

View File

@ -1,4 +1,4 @@
import type { DiagramDetector } from '../../diagram-api/detectType';
import type { DiagramDetector } from '../../diagram-api/types';
export const stateDetector: DiagramDetector = (txt, config) => {
// If we have confirmed to only use new state diagrams this function should always return false

View File

@ -1,4 +1,4 @@
import type { DiagramDetector } from '../../diagram-api/detectType';
import type { DiagramDetector } from '../../diagram-api/types';
export const journeyDetector: DiagramDetector = (txt) => {
return txt.match(/^\s*journey/) !== null;

View File

@ -35,13 +35,17 @@ import { exec } from 'child_process';
import { globby } from 'globby';
import { JSDOM } from 'jsdom';
import type { Code, Root } from 'mdast';
import { join, dirname } from 'path';
import { posix, dirname } from 'path';
import prettier from 'prettier';
import { remark } from 'remark';
// @ts-ignore No typescript declaration file
// eslint-disable-next-line @cspell/spellchecker
import flatmap from 'unist-util-flatmap';
const MERMAID_MAJOR_VERSION = (
JSON.parse(readFileSync('packages/mermaid/package.json', 'utf8')).version as string
).split('.')[0];
// These paths are from the root of the mono-repo, not from the
// mermaid sub-directory
const SOURCE_DOCS_DIR = 'packages/mermaid/src/docs';
@ -145,7 +149,7 @@ const readSyncedUTF8file = (filename: string): string => {
* @param file {string} name of the file that will be verified
*/
const transformMarkdown = (file: string) => {
const doc = readSyncedUTF8file(file);
const doc = readSyncedUTF8file(file).replace(/<MERMAID_VERSION>/g, MERMAID_MAJOR_VERSION);
const ast: Root = remark.parse(doc);
const out = flatmap(ast, (c: Code) => {
if (c.type !== 'code') {
@ -186,7 +190,10 @@ const transformHtml = (filename: string) => {
* @returns {string} The contents of the file with the comment inserted
*/
const insertAutoGeneratedComment = (fileName: string): string => {
const fileContents = readSyncedUTF8file(fileName);
const fileContents = readSyncedUTF8file(fileName).replace(
/<MERMAID_VERSION>/g,
MERMAID_MAJOR_VERSION
);
const jsdom = new JSDOM(fileContents);
const htmlDoc = jsdom.window.document;
const autoGeneratedComment = jsdom.window.document.createComment(AUTOGENERATED_TEXT);
@ -204,30 +211,28 @@ const transformHtml = (filename: string) => {
copyTransformedContents(filename, !verifyOnly, formattedHTML);
};
const getFilesFromGlobs = async (globs: string[]): Promise<string[]> => {
return await globby(globs, { dot: true });
};
/** Main method (entry point) */
(async () => {
if (verifyOnly) {
console.log('Verifying that all files are in sync with the source files');
}
const sourceDirGlob = join('.', SOURCE_DOCS_DIR, '**');
const includeFilesStartingWithDot = true;
const sourceDirGlob = posix.join('.', SOURCE_DOCS_DIR, '**');
const action = verifyOnly ? 'Verifying' : 'Transforming';
console.log('Transforming markdown files...');
const mdFiles = await globby([join(sourceDirGlob, '*.md')], {
dot: includeFilesStartingWithDot,
});
const mdFiles = await getFilesFromGlobs([posix.join(sourceDirGlob, '*.md')]);
console.log(`${action} ${mdFiles.length} markdown files...`);
mdFiles.forEach(transformMarkdown);
console.log('Transforming html files...');
const htmlFiles = await globby([join(sourceDirGlob, '*.html')], {
dot: includeFilesStartingWithDot,
});
const htmlFiles = await getFilesFromGlobs([posix.join(sourceDirGlob, '*.html')]);
console.log(`${action} ${htmlFiles.length} html files...`);
htmlFiles.forEach(transformHtml);
console.log('Transforming all other files...');
const otherFiles = await globby([sourceDirGlob, '!**/*.md', '!**/*.html'], {
dot: includeFilesStartingWithDot,
});
const otherFiles = await getFilesFromGlobs([sourceDirGlob, '!**/*.md', '!**/*.html']);
console.log(`${action} ${otherFiles.length} other files...`);
otherFiles.forEach((file: string) => {
copyTransformedContents(file, !verifyOnly); // no transformation
});
@ -238,7 +243,7 @@ const transformHtml = (filename: string) => {
process.exit(1);
}
if (git) {
console.log('Adding changes in ${FINAL_DOCS_DIR} folder to git');
console.log(`Adding changes in ${FINAL_DOCS_DIR} folder to git`);
exec('git add docs');
}
}

View File

@ -8,7 +8,7 @@ It is a JavaScript based diagramming and charting tool that renders Markdown-ins
<img src="img/header.png" alt="" />
[![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE)
[![Build CI Status](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml/badge.svg)](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml) [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid) [![NPM](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid) [![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [![Twitter Follow](https://img.shields.io/twitter/follow/mermaidjs_?style=social)](https://twitter.com/mermaidjs_)
<!-- Mermaid book banner -->
@ -187,16 +187,16 @@ To Deploy Mermaid:
### [Mermaid API](./Setup.md):
**To deploy mermaid without a bundler, one can insert a `script` tag with an absolute address and a `mermaidAPI` call into the HTML like so:**
**To deploy mermaid without a bundler, one can insert a `script` tag with an absolute address and a `mermaid.initialize` call into the HTML like so:**
```html
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
<script>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@<MERMAID_VERSION>/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
```
**Doing so will command the mermaid parser to look for the `<div>` tags with `class="mermaid"`. From these tags mermaid will try to read the diagram/chart definitions and render them into SVG charts.**
**Doing so will command the mermaid parser to look for the `<div>` or `<pre>` tags with `class="mermaid"`. From these tags mermaid will try to read the diagram/chart definitions and render them into SVG charts.**
**Examples can be found at** [Other examples](/examples)

View File

@ -1559,7 +1559,7 @@ Returns **void**
```html
<script>
var config = {
const config = {
theme: 'default',
logLevel: 'fatal',
securityLevel: 'strict',

View File

@ -399,7 +399,7 @@ click Shape2 call callbackFunction() "This is a tooltip for a callback"
```html
<script>
var callbackFunction = function () {
const callbackFunction = function () {
alert('A callback was triggered');
};
</script>
@ -451,10 +451,10 @@ Beginner's tip—a full example using interactive links in an HTML page:
</pre>
<script>
var callback = function () {
const callback = function () {
alert('A callback was triggered');
};
var config = {
const config = {
startOnLoad: true,
securityLevel: 'loose',
};

View File

@ -416,7 +416,7 @@ click nodeId call callback()
```html
<script>
var callback = function (nodeId) {
const callback = function (nodeId) {
alert('A callback was triggered on ' + nodeId);
};
</script>
@ -471,10 +471,10 @@ Beginner's tip—here's a full example of using interactive links in HTML:
</pre>
<script>
var callback = function () {
const callback = function () {
alert('A callback was triggered');
};
var config = {
const config = {
startOnLoad: true,
flowchart: {
useMaxWidth: true,

View File

@ -198,8 +198,8 @@ flowchart LR
### Dotted link
```mermaid-example
flowchart LR;
A-.->B;
flowchart LR
A-.->B
```
### Dotted link with text
@ -442,7 +442,7 @@ Examples of tooltip usage below:
```html
<script>
var callback = function () {
const callback = function () {
alert('A callback was triggered');
};
</script>
@ -495,10 +495,10 @@ Beginner's tip—a full example using interactive links in a html context:
</pre>
<script>
var callback = function () {
const callback = function () {
alert('A callback was triggered');
};
var config = {
const config = {
startOnLoad: true,
flowchart: { useMaxWidth: true, htmlLabels: true, curve: 'cardinal' },
securityLevel: 'loose',
@ -587,7 +587,7 @@ A shorter form of adding a class is to attach the classname to the node using th
```mermaid-example
flowchart LR
A:::someclass --> B
classDef someclass fill:#f96;
classDef someclass fill:#f96
```
### Css classes
@ -610,7 +610,7 @@ below:
**Example definition**
```mermaid-example
flowchart LR;
flowchart LR
A-->B[AAA<span>BBB</span>]
B-->D
class A cssClass
@ -634,7 +634,7 @@ The icons are accessed via the syntax fa:#icon class name#.
flowchart TD
B["fab:fa-twitter for peace"]
B-->C[fa:fa-ban forbidden]
B-->D(fa:fa-spinner);
B-->D(fa:fa-spinner)
B-->E(A fa:fa-camera-retro perhaps?)
```

View File

@ -327,13 +327,13 @@ Beginner's tip—a full example using interactive links in an html context:
</pre>
<script>
var printArguments = function (arg1, arg2, arg3) {
const printArguments = function (arg1, arg2, arg3) {
alert('printArguments called with arguments: ' + arg1 + ', ' + arg2 + ', ' + arg3);
};
var printTask = function (taskId) {
const printTask = function (taskId) {
alert('taskId: ' + taskId);
};
var config = {
const config = {
startOnLoad: true,
securityLevel: 'loose',
};

View File

@ -21,21 +21,34 @@
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css"
/>
<script src="//cdn.jsdelivr.net/npm/mermaid@9.1.7/dist/mermaid.min.js"></script>
<!-- <script src="http://localhost:9000/mermaid.js"></script> -->
<script
defer
data-domain="mermaid-js.github.io"
src="https://plausible.io/js/plausible.js"
></script>
<script>
var require = {
paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.29.1/min/vs' },
const require = {
paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.0/min/vs' },
};
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.29.1/min/vs/loader.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.29.1/min/vs/editor/editor.main.nls.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.29.1/min/vs/editor/editor.main.js"></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.0/min/vs/loader.min.js"
integrity="sha512-6bIYsGqvLpAiEBXPdRQeFf5cueeBECtAKJjIHer3BhBZNTV3WLcLA8Tm3pDfxUwTMIS+kAZwTUvJ1IrMdX8C5w=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.0/min/vs/editor/editor.main.nls.min.js"
integrity="sha512-CCv+DKWw+yZhxf4Z+ExT6HC5G+3S45TeMTYcJyYbdrv4BpK2vyALJ4FoVR/KGWDIPu7w4tNCOC9MJQIkYPR5FA=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.0/min/vs/editor/editor.main.min.js"
integrity="sha512-iVHvVf6TQEoF5oQrocjP88wstImQHQZCxGsa5nKYOs6gXWzsV7QZHyk80HrXhrEWRJ1ADoIV6Uji3UUXtCmBMg=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
<script>
exports = {};
</script>
@ -50,17 +63,22 @@
<body>
<div id="app"></div>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@<MERMAID_VERSION>/dist/mermaid.esm.min.mjs';
window.mermaid = mermaid;
</script>
<script>
var initEditor = exports.default;
var parser = new DOMParser();
var currentCodeExample = 0;
var colorize = [];
let initEditor = exports.default;
let parser = new DOMParser();
let currentCodeExample = 0;
let colorize = [];
let num = 0;
function colorizeEverything(html) {
initEditor(monaco);
return new Promise((resolve, reject) => {
monaco.editor.setTheme('mermaid');
var parsed = parser.parseFromString(html, 'text/html').body;
const parsed = parser.parseFromString(html, 'text/html').body;
Promise.all(
[...parsed.querySelectorAll('pre[id*="code"]')].map((codeBlock) =>
monaco.editor.colorize(codeBlock.innerText, 'mermaid')
@ -99,6 +117,7 @@
colorize.push(currentCodeExample);
return '<pre id="code' + currentCodeExample + '">' + escapeHTML(code) + '</pre>';
} else if (lang === 'mermaid') {
// TODO: This will need to be updated when render is async.
return (
'<pre class="mermaid">' + mermaid.render('mermaid-svg-' + num++, code) + '</pre>'
);
@ -117,7 +136,7 @@
function (hook, vm) {
hook.beforeEach(function (html) {
url = 'https://github.com/mermaid-js/mermaid/blob/develop/src/docs/' + vm.route.file;
var editHtml = '[:memo: Edit this Page](' + url + ')\n';
const editHtml = '[:memo: Edit this Page](' + url + ')\n';
return editHtml + html;
});
@ -136,7 +155,6 @@
],
};
var num = 0;
const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
const conf = {

View File

@ -73,23 +73,13 @@ The API works by pulling rendering instructions from the source `mermaid.js` in
### Requirements for the Mermaid API.
When writing the .html file, we give three instructions inside the html code to the web browser:
When writing the .html file, we give two instructions inside the html code to the web browser:
a. A reference for fetching the online mermaid renderer, through the `mermaid.js` or `mermaid.min.js`.
a. The mermaid code for the diagram we want to create.
b. 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 .
c. The `mermaid.initialize()` call, which dictates the appearance of diagrams and also starts the rendering process .
**a. A reference to the external CDN in a `<script src>` tag, or a reference to mermaid.js as a separate file.:**
```html
<body>
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
</body>
```
**b. The embedded mermaid diagram definition inside a `<pre class="mermaid">`:**
**a. The embedded mermaid diagram definition inside a `<pre class="mermaid">`:**
```html
<body>
@ -105,13 +95,14 @@ c. The `mermaid.initialize()` call, which dictates the appearance of diagrams an
**Notes**: Every Mermaid chart/graph/diagram definition, should have separate `<pre>` tags.
**c. The `mermaid.initialize()` call.**
**b. The import of mermaid and the `mermaid.initialize()` call.**
`mermaid.initialize()` call takes all the definitions contained in all the `<pre class="mermaid">` tags that it finds in the html body and renders them into diagrams. Example:
```html
<body>
<script>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@<MERMAID_VERSION>/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
</body>
@ -133,11 +124,6 @@ Rendering in Mermaid is initialized by `mermaid.initialize()` call. You can plac
```html
<html>
<body>
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
<script>
mermaid.initialize({ startOnLoad: true });
</script>
Here is one mermaid diagram:
<pre class="mermaid">
graph TD
@ -154,6 +140,11 @@ Rendering in Mermaid is initialized by `mermaid.initialize()` call. You can plac
B -->|tcp_456| C[Server1]
B -->|tcp_456| D[Server2]
</pre>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@<MERMAID_VERSION>/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
</body>
</html>
```
@ -179,8 +170,8 @@ In this example mermaid.js is referenced in `src` as a separate JavaScript file,
B --> C[Server1]
B --> D[Server2]
</pre>
<script src="The\Path\In\Your\Package\mermaid.js"></script>
<script>
<script type="module">
import mermaid from 'The/Path/In/Your/Package/mermaid.esm.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
</body>
@ -204,4 +195,4 @@ In this example mermaid.js is referenced in `src` as a separate JavaScript file,
**Comments from Knut Sveidqvist, creator of mermaid:**
- In early versions of mermaid, the `<script src>` tag was invoked in the `<head>` part of the web page. Nowadays we can place it in the `<body>` as seen above. Older parts of the documentation frequently reflects the previous way which still works.
- In early versions of mermaid, the `<script>` tag was invoked in the `<head>` part of the web page. Nowadays we can place it in the `<body>` as seen above. Older parts of the documentation frequently reflects the previous way which still works.

View File

@ -39,23 +39,9 @@ We have compiled some Video [Tutorials](./Tutorials.md) on how to use the mermai
> Note:This topic explored in greater depth in the [User Guide for Beginners](./n00b-gettingStarted.md)
The easiest way to integrate mermaid on a web page requires three elements:
The easiest way to integrate mermaid on a web page requires two elements:
1. Inclusion of the mermaid address in the html page using a `script` tag, in the `src` section.Example:
```html
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
```
2. The `mermaidAPI` call, in a separate `script` tag. Example:
```html
<script>
mermaid.initialize({ startOnLoad: true });
</script>
```
3. A graph definition, inside `<div>` tags labeled `class=mermaid`. Example:
- A graph definition, inside `<pre>` tags labeled `class=mermaid`. Example:
```html
<pre class="mermaid">
@ -66,8 +52,18 @@ The easiest way to integrate mermaid on a web page requires three elements:
</pre>
```
**Following these directions, mermaid starts at page load and (when the page has loaded) it will
locate the graph definitions inside the `div` tags with `class="mermaid"` and return diagrams in SVG form, following given definitions.**
- Inclusion of the mermaid address in the html page body using a `script` tag as an ESM import, and the `mermaidAPI` call.
Example:
```html
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@<MERMAID_VERSION>/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
```
**Following these directions, mermaid starts at page load and (when the page has loaded) it will locate the graph definitions inside the `pre` tags with `class="mermaid"` and return diagrams in SVG form, following given definitions.**
## Simple full example:
@ -84,8 +80,8 @@ locate the graph definitions inside the `div` tags with `class="mermaid"` and re
B-->C[fa:fa-ban forbidden]
B-->D(fa:fa-spinner);
</pre>
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
<script>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@<MERMAID_VERSION>/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
</body>
@ -204,18 +200,17 @@ fetch the graph definition from the site (perhaps from a textarea), render it an
The example below show an outline of how this could be used. The example just logs the resulting SVG to the JavaScript console.
```html
<script src="mermaid.js"></script>
<script>
<script type="module">
import mermaid from './mermaid.mjs';
mermaid.mermaidAPI.initialize({ startOnLoad: false });
$(function () {
$(async function () {
// Example of using the API var
element = document.querySelector('#graphDiv');
var insertSvg = function (svgCode, bindFunctions) {
const insertSvg = function (svgCode, bindFunctions) {
element.innerHTML = svgCode;
};
var graphDefinition = 'graph TB\na-->b';
var graph = mermaid.mermaidAPI.render('graphDiv', graphDefinition, insertSvg);
const graphDefinition = 'graph TB\na-->b';
const graph = await mermaid.mermaidAPI.render('graphDiv', graphDefinition, insertSvg);
});
</script>
```
@ -339,7 +334,7 @@ on what kind of integration you use.
```html
<script src="../dist/mermaid.js"></script>
<script>
var config = { startOnLoad: true, flowchart: { useMaxWidth: false, htmlLabels: true } };
let config = { startOnLoad: true, flowchart: { useMaxWidth: false, htmlLabels: true } };
mermaid.initialize(config);
</script>
```

View File

@ -7,15 +7,8 @@ import { log } from './logger';
import utils from './utils';
import { mermaidAPI } from './mermaidAPI';
import { addDetector } from './diagram-api/detectType';
import {
registerDiagram,
DiagramDefinition,
setLogLevel,
getConfig,
setupGraphViewbox,
sanitizeText,
} from './diagram-api/diagramAPI';
import { isDetailedError } from './utils';
import type { ParseErrorFunction } from './Diagram';
/**
* ## init
@ -53,17 +46,16 @@ const init = async function (
callback?: Function
) {
try {
log.info('Detectors in init', mermaid.detectors); // eslint-disable-line
const conf = mermaidAPI.getConfig();
if (typeof conf.lazyLoadedDiagrams !== 'undefined' && conf.lazyLoadedDiagrams.length > 0) {
for (let i = 0; i < conf.lazyLoadedDiagrams.length; i++) {
const { id, detector, loadDiagram } = await import(conf.lazyLoadedDiagrams[i]);
if (conf?.lazyLoadedDiagrams && conf.lazyLoadedDiagrams.length > 0) {
// Load all lazy loaded diagrams in parallel
await Promise.allSettled(
conf.lazyLoadedDiagrams.map(async (diagram: string) => {
const { id, detector, loadDiagram } = await import(diagram);
addDetector(id, detector, loadDiagram);
})
);
}
}
mermaid.detectors.forEach(({ id, detector, path }) => {
addDetector(id, detector, path);
});
await initThrowsErrors(config, nodes, callback);
} catch (e) {
log.warn('Syntax Error rendering');
@ -71,7 +63,7 @@ const init = async function (
log.warn(e.str);
}
if (mermaid.parseError) {
mermaid.parseError(e);
mermaid.parseError(e as string);
}
}
};
@ -218,27 +210,10 @@ const parse = (txt: string) => {
return mermaidAPI.parse(txt, mermaid.parseError);
};
const connectDiagram = (
id: string,
diagram: DiagramDefinition,
callback: (
_log: any,
_setLogLevel: any,
_getConfig: any,
_sanitizeText: any,
_setupGraphViewbox: any
) => void
) => {
registerDiagram(id, diagram, callback);
// Todo move this connect call to after the diagram is actually loaded.
callback(log, setLogLevel, getConfig, sanitizeText, setupGraphViewbox);
};
const mermaid: {
startOnLoad: boolean;
diagrams: any;
// eslint-disable-next-line @typescript-eslint/ban-types
parseError?: Function;
parseError?: ParseErrorFunction;
mermaidAPI: typeof mermaidAPI;
parse: typeof parse;
render: typeof mermaidAPI.render;
@ -247,9 +222,6 @@ const mermaid: {
initialize: typeof initialize;
contentLoaded: typeof contentLoaded;
setParseErrorHandler: typeof setParseErrorHandler;
// Array of functions to use for detecting diagram types
detectors: Array<any>; // eslint-disable-line @typescript-eslint/no-explicit-any
connectDiagram: (id: string, diagram: DiagramDefinition, callback: (id: string) => void) => void;
} = {
startOnLoad: true,
diagrams: {},
@ -262,8 +234,6 @@ const mermaid: {
parseError: undefined,
contentLoaded,
setParseErrorHandler,
detectors: [],
connectDiagram: connectDiagram,
};
export default mermaid;

View File

@ -18,12 +18,11 @@ import { compile, serialize, stringify } from 'stylis';
import pkg from '../package.json';
import * as configApi from './config';
import { addDiagrams } from './diagram-api/diagram-orchestration';
import { addDetector } from './diagram-api/detectType';
import classDb from './diagrams/class/classDb';
import flowDb from './diagrams/flowchart/flowDb';
import flowRenderer from './diagrams/flowchart/flowRenderer';
import ganttDb from './diagrams/gantt/ganttDb';
import Diagram, { getDiagramFromText } from './Diagram';
import Diagram, { getDiagramFromText, type ParseErrorFunction } from './Diagram';
import errorRenderer from './diagrams/error/errorRenderer';
import { attachFunctions } from './interactionDb';
import { log, setLogLevel } from './logger';
@ -34,18 +33,12 @@ import DOMPurify from 'dompurify';
import { MermaidConfig } from './config.type';
import { evaluate } from './diagrams/common/common';
let hasLoadedDiagrams = false;
/**
* @param text
* @param parseError
*/
// eslint-disable-next-line @typescript-eslint/ban-types
function parse(text: string, parseError?: Function): boolean {
if (!hasLoadedDiagrams) {
function parse(text: string, parseError?: ParseErrorFunction): boolean {
addDiagrams();
hasLoadedDiagrams = true;
}
const diagram = new Diagram(text, parseError);
return diagram.parse(text, parseError);
}
@ -122,10 +115,7 @@ const render = async function (
cb: (svgCode: string, bindFunctions?: (element: Element) => void) => void,
container?: Element
): Promise<void> {
if (!hasLoadedDiagrams) {
addDiagrams();
hasLoadedDiagrams = true;
}
configApi.reset();
text = text.replace(/\r\n?/g, '\n'); // parser problems on CRLF ignore all CR and leave LF;;
const graphInit = utils.detectInit(text);
@ -486,11 +476,7 @@ async function initialize(options: MermaidConfig) {
typeof options === 'object' ? configApi.setSiteConfig(options) : configApi.getSiteConfig();
setLogLevel(config.logLevel);
if (!hasLoadedDiagrams) {
addDiagrams();
hasLoadedDiagrams = true;
}
}
export const mermaidAPI = Object.freeze({

5331
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

24
renovate.json Normal file
View File

@ -0,0 +1,24 @@
{
"extends": [
"config:base",
":rebaseStalePrs",
"group:allNonMajor",
"schedule:earlyMondays",
":automergeMinor",
":automergeTesters",
":automergeLinters",
":automergeTypes",
":automergePatch"
],
"packageRules": [
{
"matchUpdateTypes": ["minor", "patch", "pin", "digest"],
"automerge": true
}
],
"dependencyDashboard": true,
"major": {
"dependencyDashboardApproval": true
},
"dependencyDashboardAutoclose": true
}

View File

@ -1,108 +0,0 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Projects */
// "incremental": true /* Enable incremental compilation */,
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "ES6" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
"lib": [
"DOM",
"ES2021"
] /* Specify a set of bundled library declaration files that describe the target runtime environment. */,
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
// "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
/* Modules */
"module": "ES6" /* Specify what module code is generated. */,
"rootDir": "./src" /* Specify the root folder within your source files. */,
"moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */,
// "baseUrl": "./src" /* Specify the base directory to resolve non-relative module names. */,
// "paths": {} /* Specify a set of entries that re-map imports to additional lookup locations. */,
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [] /* Specify multiple folders that act like `./node_modules/@types`. */,
"types": [
"vitest/globals"
] /* Specify type package names to be included without being referenced in a source file. */,
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
"resolveJsonModule": true /* Enable importing .json files */,
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
"allowJs": true /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */,
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
/* Emit */
"declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */,
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
"outDir": "./dist" /* Specify an output folder for all emitted files. */,
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
/* Interop Constraints */
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */,
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
/* Type Checking */
"strict": true /* Enable all strict type-checking options. */,
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
// "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
},
"include": ["./src/**/*.ts", "./package.json"]
}

View File

@ -29,7 +29,7 @@ mermaid.initialize({ flowchart: { htmlLabels: false } });
**Example 2:**
```js
var config = {
const config = {
startOnLoad: true,
flowchart: { useMaxWidth: true, htmlLabels: true, curve: 'cardinal' },
@ -1560,7 +1560,7 @@ Returns **void**
```html
<script>
var config = {
const config = {
theme: 'default',
logLevel: 'fatal',
securityLevel: 'strict',

View File

@ -39,23 +39,9 @@ We have compiled some Video [Tutorials](./Tutorials.md) on how to use the mermai
> Note:This topic explored in greater depth in the [User Guide for Beginners](../intro/n00b-gettingStarted.md)
The easiest way to integrate mermaid on a web page requires three elements:
The easiest way to integrate mermaid on a web page requires two elements:
1. Inclusion of the mermaid address in the html page using a `script` tag, in the `src` section.Example:
```html
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
```
2. The `mermaidAPI` call, in a separate `script` tag. Example:
```html
<script>
mermaid.initialize({ startOnLoad: true });
</script>
```
3. A graph definition, inside `<div>` tags labeled `class=mermaid`. Example:
- A graph definition, inside `<pre>` tags labeled `class=mermaid`. Example:
```html
<pre class="mermaid">
@ -66,8 +52,18 @@ The easiest way to integrate mermaid on a web page requires three elements:
</pre>
```
**Following these directions, mermaid starts at page load and (when the page has loaded) it will
locate the graph definitions inside the `div` tags with `class="mermaid"` and return diagrams in SVG form, following given definitions.**
- Inclusion of the mermaid address in the html page body using a `script` tag as an ESM import, and the `mermaidAPI` call.
Example:
```html
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@<MERMAID_VERSION>/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
```
**Following these directions, mermaid starts at page load and (when the page has loaded) it will locate the graph definitions inside the `pre` tags with `class="mermaid"` and return diagrams in SVG form, following given definitions.**
## Simple full example:
@ -84,8 +80,8 @@ locate the graph definitions inside the `div` tags with `class="mermaid"` and re
B-->C[fa:fa-ban forbidden]
B-->D(fa:fa-spinner);
</pre>
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
<script>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@<MERMAID_VERSION>/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
</body>
@ -211,11 +207,11 @@ The example below show an outline of how this could be used. The example just lo
$(function () {
// Example of using the API var
element = document.querySelector('#graphDiv');
var insertSvg = function (svgCode, bindFunctions) {
const insertSvg = function (svgCode, bindFunctions) {
element.innerHTML = svgCode;
};
var graphDefinition = 'graph TB\na-->b';
var graph = mermaid.mermaidAPI.render('graphDiv', graphDefinition, insertSvg);
const graphDefinition = 'graph TB\na-->b';
const graph = mermaid.mermaidAPI.render('graphDiv', graphDefinition, insertSvg);
});
</script>
```
@ -339,7 +335,7 @@ on what kind of integration you use.
```html
<script src="../dist/mermaid.js"></script>
<script>
var config = { startOnLoad: true, flowchart: { useMaxWidth: false, htmlLabels: true } };
let config = { startOnLoad: true, flowchart: { useMaxWidth: false, htmlLabels: true } };
mermaid.initialize(config);
</script>
```

View File

@ -8,7 +8,7 @@ It is a JavaScript based diagramming and charting tool that renders Markdown-ins
<img src="/header.png" alt="" />
[![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE)
[![Build CI Status](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml/badge.svg)](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml) [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid) [![NPM](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid) [![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [![Twitter Follow](https://img.shields.io/twitter/follow/mermaidjs_?style=social)](https://twitter.com/mermaidjs_)
<!-- Mermaid book banner -->
@ -262,16 +262,16 @@ To Deploy Mermaid:
### [Mermaid API](../config/Setup.md):
**To deploy mermaid without a bundler, one can insert a `script` tag with an absolute address and a `mermaidAPI` call into the HTML like so:**
**To deploy mermaid without a bundler, one can insert a `script` tag with an absolute address and a `mermaid.initialize` call into the HTML like so:**
```html
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
<script>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@<MERMAID_VERSION>/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
```
**Doing so will command the mermaid parser to look for the `<div>` tags with `class="mermaid"`. From these tags mermaid will try to read the diagram/chart definitions and render them into SVG charts.**
**Doing so will command the mermaid parser to look for the `<div>` or `<pre>` tags with `class="mermaid"`. From these tags mermaid will try to read the diagram/chart definitions and render them into SVG charts.**
**Examples can be found at** [Other examples](../syntax/examples)

View File

@ -82,23 +82,13 @@ The API works by pulling rendering instructions from the source `mermaid.js` in
### Requirements for the Mermaid API.
When writing the .html file, we give three instructions inside the html code to the web browser:
When writing the .html file, we give two instructions inside the html code to the web browser:
a. A reference for fetching the online mermaid renderer, through the `mermaid.js` or `mermaid.min.js`.
a. The mermaid code for the diagram we want to create.
b. 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 .
c. The `mermaid.initialize()` call, which dictates the appearance of diagrams and also starts the rendering process .
**a. A reference to the external CDN in a `<script src>` tag, or a reference to mermaid.js as a separate file.:**
```html
<body>
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
</body>
```
**b. The embedded mermaid diagram definition inside a `<pre class="mermaid">`:**
**a. The embedded mermaid diagram definition inside a `<pre class="mermaid">`:**
```html
<body>
@ -114,13 +104,14 @@ c. The `mermaid.initialize()` call, which dictates the appearance of diagrams an
**Notes**: Every Mermaid chart/graph/diagram definition, should have separate `<pre>` tags.
**c. The `mermaid.initialize()` call.**
**b. The import of mermaid and the `mermaid.initialize()` call.**
`mermaid.initialize()` call takes all the definitions contained in all the `<pre class="mermaid">` tags that it finds in the html body and renders them into diagrams. Example:
```html
<body>
<script>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@<MERMAID_VERSION>/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
</body>
@ -142,11 +133,6 @@ Rendering in Mermaid is initialized by `mermaid.initialize()` call. You can plac
```html
<html>
<body>
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
<script>
mermaid.initialize({ startOnLoad: true });
</script>
Here is one mermaid diagram:
<pre class="mermaid">
graph TD
@ -163,6 +149,11 @@ Rendering in Mermaid is initialized by `mermaid.initialize()` call. You can plac
B -->|tcp_456| C[Server1]
B -->|tcp_456| D[Server2]
</pre>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@<MERMAID_VERSION>/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
</body>
</html>
```
@ -188,8 +179,8 @@ In this example mermaid.js is referenced in `src` as a separate JavaScript file,
B --> C[Server1]
B --> D[Server2]
</pre>
<script src="The\Path\In\Your\Package\mermaid.js"></script>
<script>
<script type="module">
import mermaid from 'The/Path/In/Your/Package/mermaid.ems.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
</body>
@ -213,4 +204,4 @@ In this example mermaid.js is referenced in `src` as a separate JavaScript file,
**Comments from Knut Sveidqvist, creator of mermaid:**
- In early versions of mermaid, the `<script src>` tag was invoked in the `<head>` part of the web page. Nowadays we can place it in the `<body>` as seen above. Older parts of the documentation frequently reflects the previous way which still works.
- In early versions of mermaid, the `<script>` tag was invoked in the `<head>` part of the web page. Nowadays we can place it in the `<body>` as seen above. Older parts of the documentation frequently reflects the previous way which still works.

View File

@ -399,7 +399,7 @@ click Shape2 call callbackFunction() "This is a tooltip for a callback"
```html
<script>
var callbackFunction = function () {
const callbackFunction = function () {
alert('A callback was triggered');
};
</script>
@ -451,10 +451,10 @@ Beginner's tip—a full example using interactive links in an HTML page:
</pre>
<script>
var callback = function () {
const callback = function () {
alert('A callback was triggered');
};
var config = {
const config = {
startOnLoad: true,
securityLevel: 'loose',
};

View File

@ -449,7 +449,7 @@ Examples of tooltip usage below:
```html
<script>
var callback = function () {
const callback = function () {
alert('A callback was triggered');
};
</script>
@ -502,10 +502,10 @@ Beginner's tip—a full example using interactive links in a html context:
</pre>
<script>
var callback = function () {
const callback = function () {
alert('A callback was triggered');
};
var config = {
const config = {
startOnLoad: true,
flowchart: { useMaxWidth: true, htmlLabels: true, curve: 'cardinal' },
securityLevel: 'loose',

View File

@ -327,13 +327,13 @@ Beginner's tip—a full example using interactive links in an html context:
</pre>
<script>
var printArguments = function (arg1, arg2, arg3) {
const printArguments = function (arg1, arg2, arg3) {
alert('printArguments called with arguments: ' + arg1 + ', ' + arg2 + ', ' + arg3);
};
var printTask = function (taskId) {
const printTask = function (taskId) {
alert('taskId: ' + taskId);
};
var config = {
const config = {
startOnLoad: true,
securityLevel: 'loose',
};