mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-11-20 04:34:08 +01:00
Merge branch 'next' into sidv/esbuildV10
* next: Update assignWithDepth.ts Version update and adjusted error diagram Fix for broker error diagram related #4178 Adding new flowchart tests related to issue #2139 Fix for interim issue with classes in state diagrams redeclare `config` parameter add default value for each variable convert `assignWithDepth` to TS #2139 Applying user defined classes properly when calculating shape width chore: Ignore localhost Update packages/mermaid/src/docs/community/development.md Update docs/community/development.md docs: Add development example page. docs: Correct detectType filename chore: Minor cleanups chore: remove comment chore: Remove comments, cleanup fix: unitTests after tripleParsing removal fix: Remove triple parsing of diagrams
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -43,3 +43,6 @@ stats/
|
|||||||
**/contributor-names.json
|
**/contributor-names.json
|
||||||
.pnpm-store
|
.pnpm-store
|
||||||
.nyc_output
|
.nyc_output
|
||||||
|
|
||||||
|
demos/dev/**
|
||||||
|
!/demos/dev/example.html
|
||||||
|
|||||||
@@ -26,9 +26,14 @@ Install required packages:
|
|||||||
```bash
|
```bash
|
||||||
# npx is required for first install as volta support for pnpm is not added yet.
|
# npx is required for first install as volta support for pnpm is not added yet.
|
||||||
npx pnpm install
|
npx pnpm install
|
||||||
pnpm test
|
pnpm test # run unit tests
|
||||||
|
pnpm dev # starts a dev server
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Open <http://localhost:9000> in your browser after starting the dev server.
|
||||||
|
You can also duplicate the `example.html` file in `demos/dev`, rename it and add your own mermaid code to it.
|
||||||
|
That will be served at <http://localhost:9000/dev/your-file-name.html>.
|
||||||
|
|
||||||
### Docker
|
### Docker
|
||||||
|
|
||||||
If you are using docker and docker-compose, you have self-documented `run` bash script, which is a convenient alias for docker-compose commands:
|
If you are using docker and docker-compose, you have self-documented `run` bash script, which is a convenient alias for docker-compose commands:
|
||||||
|
|||||||
@@ -449,7 +449,7 @@ flowchart TD
|
|||||||
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
|
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('65: text-color from classes', () => {
|
it('65-1: text-color from classes', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
flowchart LR
|
flowchart LR
|
||||||
@@ -460,6 +460,31 @@ flowchart TD
|
|||||||
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
|
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
it('65-2: bold text from classes', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`
|
||||||
|
flowchart
|
||||||
|
classDef cat fill:#f9d5e5, stroke:#233d4d,stroke-width:2px, font-weight:bold;
|
||||||
|
CS(A long bold text to be viewed):::cat
|
||||||
|
`,
|
||||||
|
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('65-3: bigger font from classes', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`
|
||||||
|
flowchart
|
||||||
|
Node1:::class1 --> Node2:::class2
|
||||||
|
Node1:::class1 --> Node3:::class2
|
||||||
|
Node3 --> Node4((I am a circle)):::larger
|
||||||
|
|
||||||
|
classDef class1 fill:lightblue
|
||||||
|
classDef class2 fill:pink
|
||||||
|
classDef larger font-size:30px,fill:yellow
|
||||||
|
`,
|
||||||
|
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
|
||||||
|
);
|
||||||
|
});
|
||||||
it('66: More nested subgraph cases (TB)', () => {
|
it('66: More nested subgraph cases (TB)', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
|
|||||||
@@ -58,12 +58,21 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<pre id="diagram" class="mermaid">
|
<pre id="diagram" class="mermaid">
|
||||||
---
|
flowchart
|
||||||
title: Simple flowchart with invisible edges
|
classDef mainCategories fill:#f9d5e5, stroke:#233d4d,stroke-width:2px, font-weight:bold;
|
||||||
---
|
CS(Customer Awareness Journey):::mainCategories
|
||||||
flowchart TD
|
</pre
|
||||||
A ~~~ B
|
>
|
||||||
</pre
|
<pre id="diagram" class="mermaid">
|
||||||
|
flowchart
|
||||||
|
Node1:::class1 --> Node2:::class2
|
||||||
|
Node1:::class1 --> Node3:::class2
|
||||||
|
Node3 --> Node4((I am a circle)):::larger
|
||||||
|
|
||||||
|
classDef class1 fill:lightblue
|
||||||
|
classDef class2 fill:pink
|
||||||
|
classDef larger font-size:30px,fill:yellow
|
||||||
|
</pre
|
||||||
>
|
>
|
||||||
<pre id="diagram" class="mermaid2">
|
<pre id="diagram" class="mermaid2">
|
||||||
stateDiagram-v2
|
stateDiagram-v2
|
||||||
|
|||||||
34
demos/dev/example.html
Normal file
34
demos/dev/example.html
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<!--Do not edit this file-->
|
||||||
|
<!--Duplicate this file to any name you like, run `pnpm dev`, open http://localhost:9000/dev/name.html to view-->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Mermaid development page</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre id="diagram" class="mermaid">
|
||||||
|
graph TB
|
||||||
|
a --> b
|
||||||
|
a --> c
|
||||||
|
b --> d
|
||||||
|
c --> d
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<div id="dynamicDiagram"></div>
|
||||||
|
|
||||||
|
<script type="module">
|
||||||
|
import mermaid from '/mermaid.esm.mjs';
|
||||||
|
mermaid.parseError = function (err, hash) {
|
||||||
|
console.error('Mermaid error: ', err);
|
||||||
|
};
|
||||||
|
mermaid.initialize({
|
||||||
|
startOnLoad: true,
|
||||||
|
logLevel: 0,
|
||||||
|
});
|
||||||
|
const value = `graph TD\nHello --> World`;
|
||||||
|
const el = document.getElementById('dynamicDiagram');
|
||||||
|
const { svg } = await mermaid.render('dd', value);
|
||||||
|
console.log(svg);
|
||||||
|
el.innerHTML = svg;
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -70,7 +70,21 @@ pnpm test
|
|||||||
|
|
||||||
The `test` script and others are in the top-level `package.json` file.
|
The `test` script and others are in the top-level `package.json` file.
|
||||||
|
|
||||||
All tests should run successfully without any errors or failures. (You might see _lint_ or _formatting_ warnings; those are ok during this step.)
|
All tests should run successfully without any errors or failures. (You might see _lint_ or _formatting_ "warnings"; those are ok during this step.)
|
||||||
|
|
||||||
|
#### 4. Make your changes
|
||||||
|
|
||||||
|
Now you are ready to make your changes!
|
||||||
|
Edit whichever files in `src` as required.
|
||||||
|
|
||||||
|
#### 5. See your changes
|
||||||
|
|
||||||
|
Open <http://localhost:9000> in your browser, after starting the dev server.
|
||||||
|
There is a list of demos that can be used to see and test your changes.
|
||||||
|
|
||||||
|
If you need a specific diagram, you can duplicate the `example.html` file in `/demos/dev` and add your own mermaid code to your copy.
|
||||||
|
That will be served at <http://localhost:9000/dev/your-file-name.html>.
|
||||||
|
After making code changes, the dev server will rebuild the mermaid library. You will need to reload the browser page yourself to see the changes. (PRs for auto reload are welcome!)
|
||||||
|
|
||||||
### Docker
|
### Docker
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
#### Grammar
|
#### Grammar
|
||||||
|
|
||||||
This would be to define a jison grammar for the new diagram type. That should start with a way to identify that the text in the mermaid tag is a diagram of that type. Create a new folder under diagrams for your new diagram type and a parser folder in it. This leads us to step 2.
|
This would be to define a JISON grammar for the new diagram type. That should start with a way to identify that the text in the mermaid tag is a diagram of that type. Create a new folder under diagrams for your new diagram type and a parser folder in it. This leads us to step 2.
|
||||||
|
|
||||||
For instance:
|
For instance:
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ Place the renderer in the diagram folder.
|
|||||||
|
|
||||||
### Step 3: Detection of the new diagram type
|
### Step 3: Detection of the new diagram type
|
||||||
|
|
||||||
The second thing to do is to add the capability to detect the new diagram to type to the detectType in utils.js. The detection should return a key for the new diagram type.
|
The second thing to do is to add the capability to detect the new diagram to type to the detectType in `diagram-api/detectType.ts`. The detection should return a key for the new diagram type.
|
||||||
[This key will be used to as the aria roledescription](#aria-roledescription), so it should be a word that clearly describes the diagram type.
|
[This key will be used to as the aria roledescription](#aria-roledescription), so it should be a word that clearly describes the diagram type.
|
||||||
For example, if your new diagram use a UML deployment diagram, a good key would be "UMLDeploymentDiagram" because assistive technologies such as a screen reader
|
For example, if your new diagram use a UML deployment diagram, a good key would be "UMLDeploymentDiagram" because assistive technologies such as a screen reader
|
||||||
would voice that as "U-M-L Deployment diagram." Another good key would be "deploymentDiagram" because that would be voiced as "Deployment Diagram." A bad key would be "deployment" because that would not sufficiently describe the diagram.
|
would voice that as "U-M-L Deployment diagram." Another good key would be "deploymentDiagram" because that would be voiced as "Deployment Diagram." A bad key would be "deployment" because that would not sufficiently describe the diagram.
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ mermaid.initialize(config);
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:669](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L669)
|
[mermaidAPI.ts:668](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L668)
|
||||||
|
|
||||||
## Functions
|
## Functions
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ Return the last node appended
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:310](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L310)
|
[mermaidAPI.ts:309](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L309)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ the cleaned up svgCode
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:256](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L256)
|
[mermaidAPI.ts:255](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L255)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -179,7 +179,7 @@ the string with all the user styles
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:185](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L185)
|
[mermaidAPI.ts:184](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L184)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -202,7 +202,7 @@ the string with all the user styles
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:233](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L233)
|
[mermaidAPI.ts:232](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L232)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -229,7 +229,7 @@ with an enclosing block that has each of the cssClasses followed by !important;
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:169](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L169)
|
[mermaidAPI.ts:168](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L168)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -249,7 +249,7 @@ with an enclosing block that has each of the cssClasses followed by !important;
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:155](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L155)
|
[mermaidAPI.ts:154](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L154)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -269,7 +269,7 @@ with an enclosing block that has each of the cssClasses followed by !important;
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:126](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L126)
|
[mermaidAPI.ts:125](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L125)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -295,7 +295,7 @@ Put the svgCode into an iFrame. Return the iFrame code
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:287](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L287)
|
[mermaidAPI.ts:286](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L286)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -320,4 +320,4 @@ Remove any existing elements from the given document
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:360](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L360)
|
[mermaidAPI.ts:359](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L359)
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rimraf dist",
|
"clean": "rimraf dist",
|
||||||
|
"dev": "pnpm -w dev",
|
||||||
"docs:code": "typedoc src/defaultConfig.ts src/config.ts src/mermaidAPI.ts && prettier --write ./src/docs/config/setup",
|
"docs:code": "typedoc src/defaultConfig.ts src/config.ts src/mermaidAPI.ts && prettier --write ./src/docs/config/setup",
|
||||||
"docs:build": "rimraf ../../docs && pnpm docs:spellcheck && pnpm docs:code && ts-node-esm scripts/docs.cli.mts",
|
"docs:build": "rimraf ../../docs && pnpm docs:spellcheck && pnpm docs:code && ts-node-esm scripts/docs.cli.mts",
|
||||||
"docs:verify": "pnpm docs:spellcheck && pnpm docs:code && ts-node-esm scripts/docs.cli.mts --verify",
|
"docs:verify": "pnpm docs:spellcheck && pnpm docs:code && ts-node-esm scripts/docs.cli.mts --verify",
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ import { getDiagram, registerDiagram } from './diagram-api/diagramAPI.js';
|
|||||||
import { detectType, getDiagramLoader } from './diagram-api/detectType.js';
|
import { detectType, getDiagramLoader } from './diagram-api/detectType.js';
|
||||||
import { extractFrontMatter } from './diagram-api/frontmatter.js';
|
import { extractFrontMatter } from './diagram-api/frontmatter.js';
|
||||||
import { UnknownDiagramError } from './errors.js';
|
import { UnknownDiagramError } from './errors.js';
|
||||||
import { DetailedError } from './utils.js';
|
|
||||||
import { cleanupComments } from './diagram-api/comments.js';
|
import { cleanupComments } from './diagram-api/comments.js';
|
||||||
|
import type { DetailedError } from './utils.js';
|
||||||
|
import type { DiagramDefinition } from './diagram-api/types.js';
|
||||||
|
|
||||||
export type ParseErrorFunction = (err: string | DetailedError | unknown, hash?: any) => void;
|
export type ParseErrorFunction = (err: string | DetailedError | unknown, hash?: any) => void;
|
||||||
|
|
||||||
@@ -15,9 +16,11 @@ export type ParseErrorFunction = (err: string | DetailedError | unknown, hash?:
|
|||||||
*/
|
*/
|
||||||
export class Diagram {
|
export class Diagram {
|
||||||
type = 'graph';
|
type = 'graph';
|
||||||
parser;
|
parser: DiagramDefinition['parser'];
|
||||||
renderer;
|
renderer: DiagramDefinition['renderer'];
|
||||||
db;
|
db: DiagramDefinition['db'];
|
||||||
|
private init?: DiagramDefinition['init'];
|
||||||
|
|
||||||
private detectError?: UnknownDiagramError;
|
private detectError?: UnknownDiagramError;
|
||||||
constructor(public text: string) {
|
constructor(public text: string) {
|
||||||
this.text += '\n';
|
this.text += '\n';
|
||||||
@@ -32,7 +35,6 @@ export class Diagram {
|
|||||||
log.debug('Type ' + this.type);
|
log.debug('Type ' + this.type);
|
||||||
// Setup diagram
|
// Setup diagram
|
||||||
this.db = diagram.db;
|
this.db = diagram.db;
|
||||||
this.db.clear?.();
|
|
||||||
this.renderer = diagram.renderer;
|
this.renderer = diagram.renderer;
|
||||||
this.parser = diagram.parser;
|
this.parser = diagram.parser;
|
||||||
const originalParse = this.parser.parse.bind(this.parser);
|
const originalParse = this.parser.parse.bind(this.parser);
|
||||||
@@ -49,10 +51,7 @@ export class Diagram {
|
|||||||
originalParse(cleanupComments(extractFrontMatter(text, this.db)));
|
originalParse(cleanupComments(extractFrontMatter(text, this.db)));
|
||||||
|
|
||||||
this.parser.parser.yy = this.db;
|
this.parser.parser.yy = this.db;
|
||||||
if (diagram.init) {
|
this.init = diagram.init;
|
||||||
diagram.init(cnf);
|
|
||||||
log.info('Initialized diagram ' + this.type, cnf);
|
|
||||||
}
|
|
||||||
this.parse();
|
this.parse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,6 +60,7 @@ export class Diagram {
|
|||||||
throw this.detectError;
|
throw this.detectError;
|
||||||
}
|
}
|
||||||
this.db.clear?.();
|
this.db.clear?.();
|
||||||
|
this.init?.(configApi.getConfig());
|
||||||
this.parser.parse(this.text);
|
this.parser.parse(this.text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,32 +1,36 @@
|
|||||||
'use strict';
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function assignWithDepth Extends the functionality of {@link ObjectConstructor.assign} with the
|
* assignWithDepth Extends the functionality of {@link ObjectConstructor.assign} with the
|
||||||
* ability to merge arbitrary-depth objects For each key in src with path `k` (recursively)
|
* ability to merge arbitrary-depth objects For each key in src with path `k` (recursively)
|
||||||
* performs an Object.assign(dst[`k`], src[`k`]) with a slight change from the typical handling of
|
* performs an Object.assign(dst[`k`], src[`k`]) with a slight change from the typical handling of
|
||||||
* undefined for dst[`k`]: instead of raising an error, dst[`k`] is auto-initialized to {} and
|
* undefined for dst[`k`]: instead of raising an error, dst[`k`] is auto-initialized to `{}` and
|
||||||
* effectively merged with src[`k`]<p> Additionally, dissimilar types will not clobber unless the
|
* effectively merged with src[`k`]<p> Additionally, dissimilar types will not clobber unless the
|
||||||
* config.clobber parameter === true. Example:
|
* config.clobber parameter === true. Example:
|
||||||
*
|
*
|
||||||
* ```js
|
* ```
|
||||||
* let config_0 = { foo: { bar: 'bar' }, bar: 'foo' };
|
* const config_0 = { foo: { bar: 'bar' }, bar: 'foo' };
|
||||||
* let config_1 = { foo: 'foo', bar: 'bar' };
|
* const config_1 = { foo: 'foo', bar: 'bar' };
|
||||||
* let result = assignWithDepth(config_0, config_1);
|
* const result = assignWithDepth(config_0, config_1);
|
||||||
* console.log(result);
|
* console.log(result);
|
||||||
* //-> result: { foo: { bar: 'bar' }, bar: 'bar' }
|
* //-> result: { foo: { bar: 'bar' }, bar: 'bar' }
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* Traditional Object.assign would have clobbered foo in config_0 with foo in config_1. If src is a
|
* Traditional Object.assign would have clobbered foo in config_0 with foo in config_1. If src is a
|
||||||
* destructured array of objects and dst is not an array, assignWithDepth will apply each element
|
* destructured array of objects and dst is not an array, assignWithDepth will apply each element
|
||||||
* of src to dst in order.
|
* of src to dst in order.
|
||||||
* @param {any} dst - The destination of the merge
|
* @param dst - The destination of the merge
|
||||||
* @param {any} src - The source object(s) to merge into destination
|
* @param src - The source object(s) to merge into destination
|
||||||
* @param {{ depth: number; clobber: boolean }} [config] - Depth: depth
|
* @param config -
|
||||||
* to traverse within src and dst for merging - clobber: should dissimilar types clobber (default:
|
* * depth: depth to traverse within src and dst for merging
|
||||||
* { depth: 2, clobber: false }). Default is `{ depth: 2, clobber: false }`
|
* * clobber: should dissimilar types clobber
|
||||||
* @returns {any}
|
|
||||||
*/
|
*/
|
||||||
const assignWithDepth = function (dst, src, config) {
|
const assignWithDepth = (
|
||||||
const { depth, clobber } = Object.assign({ depth: 2, clobber: false }, config);
|
dst: any,
|
||||||
|
src: any,
|
||||||
|
{ depth = 2, clobber = false }: { depth?: number; clobber?: boolean } = {}
|
||||||
|
): any => {
|
||||||
|
const config: { depth: number; clobber: boolean } = { depth, clobber };
|
||||||
if (Array.isArray(src) && !Array.isArray(dst)) {
|
if (Array.isArray(src) && !Array.isArray(dst)) {
|
||||||
src.forEach((s) => assignWithDepth(dst, s, config));
|
src.forEach((s) => assignWithDepth(dst, s, config));
|
||||||
return dst;
|
return dst;
|
||||||
@@ -8,8 +8,25 @@ import note from './shapes/note.js';
|
|||||||
import { parseMember } from '../diagrams/class/svgDraw.js';
|
import { parseMember } from '../diagrams/class/svgDraw.js';
|
||||||
import { evaluate } from '../diagrams/common/common.js';
|
import { evaluate } from '../diagrams/common/common.js';
|
||||||
|
|
||||||
|
const formatClass = (str) => {
|
||||||
|
if (str) {
|
||||||
|
return ' ' + str;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
const getClassesFromNode = (node, otherClasses) => {
|
||||||
|
return `${otherClasses ? otherClasses : 'node default'}${formatClass(node.classes)} ${formatClass(
|
||||||
|
node.class
|
||||||
|
)}`;
|
||||||
|
};
|
||||||
|
|
||||||
const question = async (parent, node) => {
|
const question = async (parent, node) => {
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true);
|
const { shapeSvg, bbox } = await labelHelper(
|
||||||
|
parent,
|
||||||
|
node,
|
||||||
|
getClassesFromNode(node, undefined),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
const w = bbox.width + node.padding;
|
const w = bbox.width + node.padding;
|
||||||
const h = bbox.height + node.padding;
|
const h = bbox.height + node.padding;
|
||||||
@@ -70,7 +87,12 @@ const choice = (parent, node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const hexagon = async (parent, node) => {
|
const hexagon = async (parent, node) => {
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true);
|
const { shapeSvg, bbox } = await labelHelper(
|
||||||
|
parent,
|
||||||
|
node,
|
||||||
|
getClassesFromNode(node, undefined),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
const f = 4;
|
const f = 4;
|
||||||
const h = bbox.height + node.padding;
|
const h = bbox.height + node.padding;
|
||||||
@@ -97,7 +119,12 @@ const hexagon = async (parent, node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const rect_left_inv_arrow = async (parent, node) => {
|
const rect_left_inv_arrow = async (parent, node) => {
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true);
|
const { shapeSvg, bbox } = await labelHelper(
|
||||||
|
parent,
|
||||||
|
node,
|
||||||
|
getClassesFromNode(node, undefined),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
const w = bbox.width + node.padding;
|
const w = bbox.width + node.padding;
|
||||||
const h = bbox.height + node.padding;
|
const h = bbox.height + node.padding;
|
||||||
@@ -123,7 +150,7 @@ const rect_left_inv_arrow = async (parent, node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const lean_right = async (parent, node) => {
|
const lean_right = async (parent, node) => {
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true);
|
const { shapeSvg, bbox } = await labelHelper(parent, node, getClassesFromNode(node), true);
|
||||||
|
|
||||||
const w = bbox.width + node.padding;
|
const w = bbox.width + node.padding;
|
||||||
const h = bbox.height + node.padding;
|
const h = bbox.height + node.padding;
|
||||||
@@ -146,7 +173,12 @@ const lean_right = async (parent, node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const lean_left = async (parent, node) => {
|
const lean_left = async (parent, node) => {
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true);
|
const { shapeSvg, bbox } = await labelHelper(
|
||||||
|
parent,
|
||||||
|
node,
|
||||||
|
getClassesFromNode(node, undefined),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
const w = bbox.width + node.padding;
|
const w = bbox.width + node.padding;
|
||||||
const h = bbox.height + node.padding;
|
const h = bbox.height + node.padding;
|
||||||
@@ -169,7 +201,12 @@ const lean_left = async (parent, node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const trapezoid = async (parent, node) => {
|
const trapezoid = async (parent, node) => {
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true);
|
const { shapeSvg, bbox } = await labelHelper(
|
||||||
|
parent,
|
||||||
|
node,
|
||||||
|
getClassesFromNode(node, undefined),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
const w = bbox.width + node.padding;
|
const w = bbox.width + node.padding;
|
||||||
const h = bbox.height + node.padding;
|
const h = bbox.height + node.padding;
|
||||||
@@ -192,7 +229,12 @@ const trapezoid = async (parent, node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const inv_trapezoid = async (parent, node) => {
|
const inv_trapezoid = async (parent, node) => {
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true);
|
const { shapeSvg, bbox } = await labelHelper(
|
||||||
|
parent,
|
||||||
|
node,
|
||||||
|
getClassesFromNode(node, undefined),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
const w = bbox.width + node.padding;
|
const w = bbox.width + node.padding;
|
||||||
const h = bbox.height + node.padding;
|
const h = bbox.height + node.padding;
|
||||||
@@ -215,7 +257,12 @@ const inv_trapezoid = async (parent, node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const rect_right_inv_arrow = async (parent, node) => {
|
const rect_right_inv_arrow = async (parent, node) => {
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true);
|
const { shapeSvg, bbox } = await labelHelper(
|
||||||
|
parent,
|
||||||
|
node,
|
||||||
|
getClassesFromNode(node, undefined),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
const w = bbox.width + node.padding;
|
const w = bbox.width + node.padding;
|
||||||
const h = bbox.height + node.padding;
|
const h = bbox.height + node.padding;
|
||||||
@@ -239,7 +286,12 @@ const rect_right_inv_arrow = async (parent, node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const cylinder = async (parent, node) => {
|
const cylinder = async (parent, node) => {
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true);
|
const { shapeSvg, bbox } = await labelHelper(
|
||||||
|
parent,
|
||||||
|
node,
|
||||||
|
getClassesFromNode(node, undefined),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
const w = bbox.width + node.padding;
|
const w = bbox.width + node.padding;
|
||||||
const rx = w / 2;
|
const rx = w / 2;
|
||||||
@@ -314,7 +366,7 @@ const rect = async (parent, node) => {
|
|||||||
const { shapeSvg, bbox, halfPadding } = await labelHelper(
|
const { shapeSvg, bbox, halfPadding } = await labelHelper(
|
||||||
parent,
|
parent,
|
||||||
node,
|
node,
|
||||||
'node ' + node.classes,
|
'node ' + node.classes + ' ' + node.class,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -360,7 +412,7 @@ const rect = async (parent, node) => {
|
|||||||
const labelRect = async (parent, node) => {
|
const labelRect = async (parent, node) => {
|
||||||
const { shapeSvg } = await labelHelper(parent, node, 'label', true);
|
const { shapeSvg } = await labelHelper(parent, node, 'label', true);
|
||||||
|
|
||||||
log.trace('Classes = ', node.classes);
|
log.trace('Classes = ', node.class);
|
||||||
// add the rect
|
// add the rect
|
||||||
const rect = shapeSvg.insert('rect', ':first-child');
|
const rect = shapeSvg.insert('rect', ':first-child');
|
||||||
|
|
||||||
@@ -545,7 +597,12 @@ const rectWithTitle = (parent, node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const stadium = async (parent, node) => {
|
const stadium = async (parent, node) => {
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true);
|
const { shapeSvg, bbox } = await labelHelper(
|
||||||
|
parent,
|
||||||
|
node,
|
||||||
|
getClassesFromNode(node, undefined),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
const h = bbox.height + node.padding;
|
const h = bbox.height + node.padding;
|
||||||
const w = bbox.width + h / 4 + node.padding;
|
const w = bbox.width + h / 4 + node.padding;
|
||||||
@@ -571,7 +628,12 @@ const stadium = async (parent, node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const circle = async (parent, node) => {
|
const circle = async (parent, node) => {
|
||||||
const { shapeSvg, bbox, halfPadding } = await labelHelper(parent, node, undefined, true);
|
const { shapeSvg, bbox, halfPadding } = await labelHelper(
|
||||||
|
parent,
|
||||||
|
node,
|
||||||
|
getClassesFromNode(node, undefined),
|
||||||
|
true
|
||||||
|
);
|
||||||
const circle = shapeSvg.insert('circle', ':first-child');
|
const circle = shapeSvg.insert('circle', ':first-child');
|
||||||
|
|
||||||
// center the circle around its coordinate
|
// center the circle around its coordinate
|
||||||
@@ -596,7 +658,12 @@ const circle = async (parent, node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const doublecircle = async (parent, node) => {
|
const doublecircle = async (parent, node) => {
|
||||||
const { shapeSvg, bbox, halfPadding } = await labelHelper(parent, node, undefined, true);
|
const { shapeSvg, bbox, halfPadding } = await labelHelper(
|
||||||
|
parent,
|
||||||
|
node,
|
||||||
|
getClassesFromNode(node, undefined),
|
||||||
|
true
|
||||||
|
);
|
||||||
const gap = 5;
|
const gap = 5;
|
||||||
const circleGroup = shapeSvg.insert('g', ':first-child');
|
const circleGroup = shapeSvg.insert('g', ':first-child');
|
||||||
const outerCircle = circleGroup.insert('circle');
|
const outerCircle = circleGroup.insert('circle');
|
||||||
@@ -634,7 +701,12 @@ const doublecircle = async (parent, node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const subroutine = async (parent, node) => {
|
const subroutine = async (parent, node) => {
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true);
|
const { shapeSvg, bbox } = await labelHelper(
|
||||||
|
parent,
|
||||||
|
node,
|
||||||
|
getClassesFromNode(node, undefined),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
const w = bbox.width + node.padding;
|
const w = bbox.width + node.padding;
|
||||||
const h = bbox.height + node.padding;
|
const h = bbox.height + node.padding;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export const labelHelper = async (parent, node, _classes, isNode) => {
|
|||||||
} else {
|
} else {
|
||||||
classes = _classes;
|
classes = _classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add outer g element
|
// Add outer g element
|
||||||
const shapeSvg = parent
|
const shapeSvg = parent
|
||||||
.insert('g')
|
.insert('g')
|
||||||
@@ -49,7 +50,6 @@ export const labelHelper = async (parent, node, _classes, isNode) => {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the size of the label
|
// Get the size of the label
|
||||||
let bbox = text.getBBox();
|
let bbox = text.getBBox();
|
||||||
const halfPadding = node.padding / 2;
|
const halfPadding = node.padding / 2;
|
||||||
|
|||||||
@@ -69,11 +69,11 @@ export const getDiagram = (name: string): DiagramDefinition => {
|
|||||||
if (name in diagrams) {
|
if (name in diagrams) {
|
||||||
return diagrams[name];
|
return diagrams[name];
|
||||||
}
|
}
|
||||||
throw new Error(`Diagram ${name} not found.`);
|
throw new DiagramNotFoundError(name);
|
||||||
};
|
};
|
||||||
|
|
||||||
export class DiagramNotFoundError extends Error {
|
export class DiagramNotFoundError extends Error {
|
||||||
constructor(message: string) {
|
constructor(name: string) {
|
||||||
super(`Diagram ${message} not found.`);
|
super(`Diagram ${name} not found.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -555,7 +555,6 @@ const drawRelationshipFromLayout = function (svg, rel, g, insert, diagObj) {
|
|||||||
export const draw = function (text, id, _version, diagObj) {
|
export const draw = function (text, id, _version, diagObj) {
|
||||||
conf = getConfig().er;
|
conf = getConfig().er;
|
||||||
log.info('Drawing ER diagram');
|
log.info('Drawing ER diagram');
|
||||||
// diag.db.clear();
|
|
||||||
const securityLevel = getConfig().securityLevel;
|
const securityLevel = getConfig().securityLevel;
|
||||||
// Handle root and Document for when rendering in sandbox mode
|
// Handle root and Document for when rendering in sandbox mode
|
||||||
let sandboxElement;
|
let sandboxElement;
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ export const draw = (_text: string, id: string, version: string) => {
|
|||||||
log.debug('renering svg for syntax error\n');
|
log.debug('renering svg for syntax error\n');
|
||||||
|
|
||||||
const svg: SVG = selectSvgElement(id);
|
const svg: SVG = selectSvgElement(id);
|
||||||
svg.attr('viewBox', '768 0 912 512');
|
svg.attr('viewBox', '0 0 2412 512');
|
||||||
configureSvgSize(svg, 100, 500, true);
|
configureSvgSize(svg, 100, 512, true);
|
||||||
|
|
||||||
const g: Group = svg.append('g');
|
const g: Group = svg.append('g');
|
||||||
g.append('path')
|
g.append('path')
|
||||||
|
|||||||
@@ -655,14 +655,7 @@ const addMarkersToEdge = function (svgPath, edgeData, diagramType, arrowMarkerAb
|
|||||||
*/
|
*/
|
||||||
export const getClasses = function (text, diagObj) {
|
export const getClasses = function (text, diagObj) {
|
||||||
log.info('Extracting classes');
|
log.info('Extracting classes');
|
||||||
diagObj.db.clear('ver-2');
|
return diagObj.db.getClasses();
|
||||||
try {
|
|
||||||
// Parse the graph definition
|
|
||||||
diagObj.parse(text);
|
|
||||||
return diagObj.db.getClasses();
|
|
||||||
} catch (e) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const addSubGraphs = function (db) {
|
const addSubGraphs = function (db) {
|
||||||
@@ -766,14 +759,8 @@ const insertChildren = (nodeArray, parentLookupDb) => {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export const draw = async function (text, id, _version, diagObj) {
|
export const draw = async function (text, id, _version, diagObj) {
|
||||||
// Add temporary render element
|
|
||||||
diagObj.db.clear();
|
|
||||||
nodeDb = {};
|
nodeDb = {};
|
||||||
portPos = {};
|
portPos = {};
|
||||||
diagObj.db.setGen('gen-2');
|
|
||||||
// Parse the graph definition
|
|
||||||
diagObj.parser.parse(text);
|
|
||||||
|
|
||||||
const renderEl = select('body').append('div').attr('style', 'height:400px').attr('id', 'cy');
|
const renderEl = select('body').append('div').attr('style', 'height:400px').attr('id', 'cy');
|
||||||
let graph = {
|
let graph = {
|
||||||
id: 'root',
|
id: 'root',
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
|
import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
|
||||||
import { select, curveLinear, selectAll } from 'd3';
|
import { select, curveLinear, selectAll } from 'd3';
|
||||||
|
|
||||||
import flowDb from './flowDb.js';
|
|
||||||
import { getConfig } from '../../config.js';
|
import { getConfig } from '../../config.js';
|
||||||
import utils from '../../utils.js';
|
import utils from '../../utils.js';
|
||||||
|
|
||||||
import { render } from '../../dagre-wrapper/index.js';
|
import { render } from '../../dagre-wrapper/index.js';
|
||||||
import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js';
|
import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js';
|
||||||
import { log } from '../../logger.js';
|
import { log } from '../../logger.js';
|
||||||
@@ -344,15 +341,7 @@ export const addEdges = function (edges, g, diagObj) {
|
|||||||
* @returns {object} ClassDef styles
|
* @returns {object} ClassDef styles
|
||||||
*/
|
*/
|
||||||
export const getClasses = function (text, diagObj) {
|
export const getClasses = function (text, diagObj) {
|
||||||
log.info('Extracting classes');
|
return diagObj.db.getClasses();
|
||||||
diagObj.db.clear();
|
|
||||||
try {
|
|
||||||
// Parse the graph definition
|
|
||||||
diagObj.parse(text);
|
|
||||||
return diagObj.db.getClasses();
|
|
||||||
} catch (e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -364,10 +353,6 @@ export const getClasses = function (text, diagObj) {
|
|||||||
|
|
||||||
export const draw = async function (text, id, _version, diagObj) {
|
export const draw = async function (text, id, _version, diagObj) {
|
||||||
log.info('Drawing flowchart');
|
log.info('Drawing flowchart');
|
||||||
diagObj.db.clear();
|
|
||||||
flowDb.setGen('gen-2');
|
|
||||||
// Parse the graph definition
|
|
||||||
diagObj.parser.parse(text);
|
|
||||||
|
|
||||||
// Fetch the default direction, use TD if none was found
|
// Fetch the default direction, use TD if none was found
|
||||||
let dir = diagObj.db.getDirection();
|
let dir = diagObj.db.getDirection();
|
||||||
|
|||||||
@@ -273,15 +273,7 @@ export const addEdges = function (edges, g, diagObj) {
|
|||||||
*/
|
*/
|
||||||
export const getClasses = function (text, diagObj) {
|
export const getClasses = function (text, diagObj) {
|
||||||
log.info('Extracting classes');
|
log.info('Extracting classes');
|
||||||
diagObj.db.clear();
|
return diagObj.db.getClasses();
|
||||||
try {
|
|
||||||
// Parse the graph definition
|
|
||||||
diagObj.parse(text);
|
|
||||||
return diagObj.db.getClasses();
|
|
||||||
} catch (e) {
|
|
||||||
log.error(e);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -294,7 +286,6 @@ export const getClasses = function (text, diagObj) {
|
|||||||
*/
|
*/
|
||||||
export const draw = function (text, id, _version, diagObj) {
|
export const draw = function (text, id, _version, diagObj) {
|
||||||
log.info('Drawing flowchart');
|
log.info('Drawing flowchart');
|
||||||
diagObj.db.clear();
|
|
||||||
const { securityLevel, flowchart: conf } = getConfig();
|
const { securityLevel, flowchart: conf } = getConfig();
|
||||||
let sandboxElement;
|
let sandboxElement;
|
||||||
if (securityLevel === 'sandbox') {
|
if (securityLevel === 'sandbox') {
|
||||||
|
|||||||
@@ -172,14 +172,11 @@ describe('more than one sequence diagram', () => {
|
|||||||
|
|
||||||
describe('when parsing a sequenceDiagram', function () {
|
describe('when parsing a sequenceDiagram', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
// diagram.db = sequenceDb;
|
|
||||||
// diagram.db.clear();
|
|
||||||
diagram = new Diagram(`
|
diagram = new Diagram(`
|
||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
Alice->Bob:Hello Bob, how are you?
|
Alice->Bob:Hello Bob, how are you?
|
||||||
Note right of Bob: Bob thinks
|
Note right of Bob: Bob thinks
|
||||||
Bob-->Alice: I am good thanks!`);
|
Bob-->Alice: I am good thanks!`);
|
||||||
diagram.db.clear();
|
|
||||||
});
|
});
|
||||||
it('should handle a sequenceDiagram definition', async function () {
|
it('should handle a sequenceDiagram definition', async function () {
|
||||||
const str = `
|
const str = `
|
||||||
@@ -1482,8 +1479,6 @@ describe('when checking the bounds in a sequenceDiagram', function () {
|
|||||||
let conf;
|
let conf;
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
mermaidAPI.reset();
|
mermaidAPI.reset();
|
||||||
// diagram.db = sequenceDb;
|
|
||||||
// diagram.db.clear();
|
|
||||||
diagram.renderer.bounds.init();
|
diagram.renderer.bounds.init();
|
||||||
conf = diagram.db.getConfig();
|
conf = diagram.db.getConfig();
|
||||||
});
|
});
|
||||||
@@ -1635,7 +1630,6 @@ sequenceDiagram
|
|||||||
Alice->Bob:Hello Bob, how are you?
|
Alice->Bob:Hello Bob, how are you?
|
||||||
Note right of Bob: Bob thinks
|
Note right of Bob: Bob thinks
|
||||||
Bob-->Alice: I am good thanks!`);
|
Bob-->Alice: I am good thanks!`);
|
||||||
diagram.db.clear();
|
|
||||||
});
|
});
|
||||||
['tspan', 'fo', 'old', undefined].forEach(function (textPlacement) {
|
['tspan', 'fo', 'old', undefined].forEach(function (textPlacement) {
|
||||||
it(`
|
it(`
|
||||||
@@ -2009,8 +2003,6 @@ describe('when rendering a sequenceDiagram with actor mirror activated', () => {
|
|||||||
let conf;
|
let conf;
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
mermaidAPI.reset();
|
mermaidAPI.reset();
|
||||||
// diagram.db = sequenceDb;
|
|
||||||
diagram.db.clear();
|
|
||||||
conf = diagram.db.getConfig();
|
conf = diagram.db.getConfig();
|
||||||
diagram.renderer.bounds.init();
|
diagram.renderer.bounds.init();
|
||||||
});
|
});
|
||||||
@@ -2052,12 +2044,8 @@ describe('when rendering a sequenceDiagram with directives', () => {
|
|||||||
mermaidAPI.initialize({ sequence: conf });
|
mermaidAPI.initialize({ sequence: conf });
|
||||||
});
|
});
|
||||||
|
|
||||||
let conf;
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
mermaidAPI.reset();
|
mermaidAPI.reset();
|
||||||
// diagram.db = sequenceDb;
|
|
||||||
diagram.db.clear();
|
|
||||||
conf = diagram.db.getConfig();
|
|
||||||
diagram.renderer.bounds.init();
|
diagram.renderer.bounds.init();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -2069,10 +2057,7 @@ sequenceDiagram
|
|||||||
participant Alice
|
participant Alice
|
||||||
`;
|
`;
|
||||||
diagram = new Diagram(str);
|
diagram = new Diagram(str);
|
||||||
|
|
||||||
diagram.renderer.bounds.init();
|
diagram.renderer.bounds.init();
|
||||||
await mermaidAPI.parse(str);
|
|
||||||
|
|
||||||
diagram.renderer.draw(str, 'tst', '1.2.3', diagram);
|
diagram.renderer.draw(str, 'tst', '1.2.3', diagram);
|
||||||
|
|
||||||
const { bounds, models } = diagram.renderer.bounds.getBounds();
|
const { bounds, models } = diagram.renderer.bounds.getBounds();
|
||||||
@@ -2093,7 +2078,7 @@ sequenceDiagram
|
|||||||
participant Alice
|
participant Alice
|
||||||
`;
|
`;
|
||||||
|
|
||||||
diagram.parse(str);
|
diagram = new Diagram(str);
|
||||||
diagram.renderer.draw(str, 'tst', '1.2.3', diagram);
|
diagram.renderer.draw(str, 'tst', '1.2.3', diagram);
|
||||||
|
|
||||||
const { bounds, models } = diagram.renderer.bounds.getBounds();
|
const { bounds, models } = diagram.renderer.bounds.getBounds();
|
||||||
@@ -2114,7 +2099,7 @@ Alice->Bob:Hello Bob, how are you?
|
|||||||
Note right of Bob: Bob thinks
|
Note right of Bob: Bob thinks
|
||||||
Bob-->Alice: I am good thanks!`;
|
Bob-->Alice: I am good thanks!`;
|
||||||
|
|
||||||
await mermaidAPI.parse(str1);
|
diagram = new Diagram(str1);
|
||||||
diagram.renderer.draw(str1, 'tst', '1.2.3', diagram); // needs to be rendered for the correct value of visibility auto numbers
|
diagram.renderer.draw(str1, 'tst', '1.2.3', diagram); // needs to be rendered for the correct value of visibility auto numbers
|
||||||
expect(diagram.db.showSequenceNumbers()).toBe(true);
|
expect(diagram.db.showSequenceNumbers()).toBe(true);
|
||||||
|
|
||||||
@@ -2124,7 +2109,7 @@ Alice->Bob:Hello Bob, how are you?
|
|||||||
Note right of Bob: Bob thinks
|
Note right of Bob: Bob thinks
|
||||||
Bob-->Alice: I am good thanks!`;
|
Bob-->Alice: I am good thanks!`;
|
||||||
|
|
||||||
await mermaidAPI.parse(str2);
|
diagram = new Diagram(str2);
|
||||||
diagram.renderer.draw(str2, 'tst', '1.2.3', diagram);
|
diagram.renderer.draw(str2, 'tst', '1.2.3', diagram);
|
||||||
expect(diagram.db.showSequenceNumbers()).toBe(false);
|
expect(diagram.db.showSequenceNumbers()).toBe(false);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -749,9 +749,6 @@ function adjustCreatedDestroyedData(
|
|||||||
export const draw = function (_text: string, id: string, _version: string, diagObj: Diagram) {
|
export const draw = function (_text: string, id: string, _version: string, diagObj: Diagram) {
|
||||||
const { securityLevel, sequence } = configApi.getConfig();
|
const { securityLevel, sequence } = configApi.getConfig();
|
||||||
conf = sequence;
|
conf = sequence;
|
||||||
diagObj.db.clear();
|
|
||||||
// Parse the graph definition
|
|
||||||
diagObj.parser.parse(_text);
|
|
||||||
// Handle root and Document for when rendering in sandbox mode
|
// Handle root and Document for when rendering in sandbox mode
|
||||||
let sandboxElement;
|
let sandboxElement;
|
||||||
if (securityLevel === 'sandbox') {
|
if (securityLevel === 'sandbox') {
|
||||||
|
|||||||
@@ -84,17 +84,8 @@ export const setConf = function (cnf) {
|
|||||||
* @returns {object} ClassDef styles (a Map with keys = strings, values = )
|
* @returns {object} ClassDef styles (a Map with keys = strings, values = )
|
||||||
*/
|
*/
|
||||||
export const getClasses = function (text, diagramObj) {
|
export const getClasses = function (text, diagramObj) {
|
||||||
log.trace('Extracting classes');
|
diagramObj.db.extract(diagramObj.db.getRootDocV2());
|
||||||
diagramObj.db.clear();
|
return diagramObj.db.getClasses();
|
||||||
try {
|
|
||||||
// Parse the graph definition
|
|
||||||
diagramObj.parser.parse(text);
|
|
||||||
// must run extract() to turn the parsed statements into states, relationships, classes, etc.
|
|
||||||
diagramObj.db.extract(diagramObj.db.getRootDocV2());
|
|
||||||
return diagramObj.db.getClasses();
|
|
||||||
} catch (e) {
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -384,7 +375,6 @@ const getDir = (parsedItem, defaultDir = DEFAULT_NESTED_DOC_DIR) => {
|
|||||||
*/
|
*/
|
||||||
export const draw = async function (text, id, _version, diag) {
|
export const draw = async function (text, id, _version, diag) {
|
||||||
log.info('Drawing state diagram (v2)', id);
|
log.info('Drawing state diagram (v2)', id);
|
||||||
// diag.sb.clear();
|
|
||||||
nodeDb = {};
|
nodeDb = {};
|
||||||
// Fetch the default direction, use TD if none was found
|
// Fetch the default direction, use TD if none was found
|
||||||
let dir = diag.db.getDirection();
|
let dir = diag.db.getDirection();
|
||||||
|
|||||||
@@ -64,7 +64,21 @@ pnpm test
|
|||||||
|
|
||||||
The `test` script and others are in the top-level `package.json` file.
|
The `test` script and others are in the top-level `package.json` file.
|
||||||
|
|
||||||
All tests should run successfully without any errors or failures. (You might see _lint_ or _formatting_ warnings; those are ok during this step.)
|
All tests should run successfully without any errors or failures. (You might see _lint_ or _formatting_ "warnings"; those are ok during this step.)
|
||||||
|
|
||||||
|
#### 4. Make your changes
|
||||||
|
|
||||||
|
Now you are ready to make your changes!
|
||||||
|
Edit whichever files in `src` as required.
|
||||||
|
|
||||||
|
#### 5. See your changes
|
||||||
|
|
||||||
|
Open <http://localhost:9000> in your browser, after starting the dev server.
|
||||||
|
There is a list of demos that can be used to see and test your changes.
|
||||||
|
|
||||||
|
If you need a specific diagram, you can duplicate the `example.html` file in `/demos/dev` and add your own mermaid code to your copy.
|
||||||
|
That will be served at <http://localhost:9000/dev/your-file-name.html>.
|
||||||
|
After making code changes, the dev server will rebuild the mermaid library. You will need to reload the browser page yourself to see the changes. (PRs for auto reload are welcome!)
|
||||||
|
|
||||||
### Docker
|
### Docker
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#### Grammar
|
#### Grammar
|
||||||
|
|
||||||
This would be to define a jison grammar for the new diagram type. That should start with a way to identify that the text in the mermaid tag is a diagram of that type. Create a new folder under diagrams for your new diagram type and a parser folder in it. This leads us to step 2.
|
This would be to define a JISON grammar for the new diagram type. That should start with a way to identify that the text in the mermaid tag is a diagram of that type. Create a new folder under diagrams for your new diagram type and a parser folder in it. This leads us to step 2.
|
||||||
|
|
||||||
For instance:
|
For instance:
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ Place the renderer in the diagram folder.
|
|||||||
|
|
||||||
### Step 3: Detection of the new diagram type
|
### Step 3: Detection of the new diagram type
|
||||||
|
|
||||||
The second thing to do is to add the capability to detect the new diagram to type to the detectType in utils.js. The detection should return a key for the new diagram type.
|
The second thing to do is to add the capability to detect the new diagram to type to the detectType in `diagram-api/detectType.ts`. The detection should return a key for the new diagram type.
|
||||||
[This key will be used to as the aria roledescription](#aria-roledescription), so it should be a word that clearly describes the diagram type.
|
[This key will be used to as the aria roledescription](#aria-roledescription), so it should be a word that clearly describes the diagram type.
|
||||||
For example, if your new diagram use a UML deployment diagram, a good key would be "UMLDeploymentDiagram" because assistive technologies such as a screen reader
|
For example, if your new diagram use a UML deployment diagram, a good key would be "UMLDeploymentDiagram" because assistive technologies such as a screen reader
|
||||||
would voice that as "U-M-L Deployment diagram." Another good key would be "deploymentDiagram" because that would be voiced as "Deployment Diagram." A bad key would be "deployment" because that would not sufficiently describe the diagram.
|
would voice that as "U-M-L Deployment diagram." Another good key would be "deploymentDiagram" because that would be voiced as "Deployment Diagram." A bad key would be "deployment" because that would not sufficiently describe the diagram.
|
||||||
|
|||||||
@@ -108,8 +108,7 @@ export interface RenderResult {
|
|||||||
async function parse(text: string, parseOptions?: ParseOptions): Promise<boolean> {
|
async function parse(text: string, parseOptions?: ParseOptions): Promise<boolean> {
|
||||||
addDiagrams();
|
addDiagrams();
|
||||||
try {
|
try {
|
||||||
const diagram = await getDiagramFromText(text);
|
await getDiagramFromText(text);
|
||||||
diagram.parse();
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (parseOptions?.suppressErrors) {
|
if (parseOptions?.suppressErrors) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user