mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-14 06:43:25 +08:00
Merge branch 'release/10.2.4'
This commit is contained in:
commit
04b11d1ba6
11
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
11
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -53,8 +53,17 @@ body:
|
||||
Please fill out the info below.
|
||||
Note that you only need to fill out the relevant section
|
||||
value: |-
|
||||
- Mermaid version:
|
||||
- Mermaid version:
|
||||
- Browser and Version: [Chrome, Edge, Firefox]
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Suggested Solutions
|
||||
description: >
|
||||
If applicable, suggest solutions that could resolve the bug.
|
||||
It would help maintainers/contributors to not waste time looking for the solution. Even pointing the line causing the bug would be great!
|
||||
placeholder: |-
|
||||
- Variable `parser` in file <filepath> is not initialised ...
|
||||
- Add a new type for ...
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional Context
|
||||
|
13
.github/workflows/e2e.yml
vendored
13
.github/workflows/e2e.yml
vendored
@ -33,7 +33,7 @@ jobs:
|
||||
# Otherwise (e.g. if running from fork), we run on a single container only
|
||||
if: ${{ ( env.CYPRESS_RECORD_KEY != '' ) || ( matrix.containers == 1 ) }}
|
||||
with:
|
||||
start: pnpm run dev
|
||||
start: pnpm run dev:coverage
|
||||
wait-on: 'http://localhost:9000'
|
||||
# Disable recording if we don't have an API key
|
||||
# e.g. if this action was run from a fork
|
||||
@ -41,7 +41,16 @@ jobs:
|
||||
parallel: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
|
||||
env:
|
||||
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
||||
|
||||
VITEST_COVERAGE: true
|
||||
- name: Upload Coverage to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
if: steps.cypress.conclusion == 'success'
|
||||
with:
|
||||
files: coverage/cypress/lcov.info
|
||||
flags: e2e
|
||||
name: mermaid-codecov
|
||||
fail_ci_if_error: true
|
||||
verbose: true
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
if: ${{ failure() && steps.cypress.conclusion == 'failure' }}
|
||||
|
12
.github/workflows/test.yml
vendored
12
.github/workflows/test.yml
vendored
@ -31,7 +31,7 @@ jobs:
|
||||
|
||||
- name: Run Unit Tests
|
||||
run: |
|
||||
pnpm run ci --coverage
|
||||
pnpm test:coverage
|
||||
|
||||
- name: Run ganttDb tests using California timezone
|
||||
env:
|
||||
@ -39,8 +39,16 @@ jobs:
|
||||
# since some days have 25 hours instead of 24.
|
||||
TZ: America/Los_Angeles
|
||||
run: |
|
||||
pnpm exec vitest run ./packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts
|
||||
pnpm exec vitest run ./packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts --coverage
|
||||
|
||||
- name: Upload Coverage to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
files: ./coverage/vitest/lcov.info
|
||||
flags: unit
|
||||
name: mermaid-codecov
|
||||
fail_ci_if_error: true
|
||||
verbose: true
|
||||
# Coveralls is throwing 500. Disabled for now.
|
||||
# - name: Upload Coverage to Coveralls
|
||||
# uses: coverallsapp/github-action@v2
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -42,3 +42,4 @@ stats/
|
||||
**/user-avatars/*
|
||||
**/contributor-names.json
|
||||
.pnpm-store
|
||||
.nyc_output
|
||||
|
@ -6,3 +6,4 @@ coverage
|
||||
pnpm-lock.yaml
|
||||
stats
|
||||
packages/mermaid/src/docs/.vitepress/components.d.ts
|
||||
.nyc_output
|
||||
|
@ -6,10 +6,12 @@ import { readFileSync } from 'fs';
|
||||
import typescript from '@rollup/plugin-typescript';
|
||||
import { visualizer } from 'rollup-plugin-visualizer';
|
||||
import type { TemplateType } from 'rollup-plugin-visualizer/dist/plugin/template-types.js';
|
||||
import istanbul from 'vite-plugin-istanbul';
|
||||
|
||||
const visualize = process.argv.includes('--visualize');
|
||||
const watch = process.argv.includes('--watch');
|
||||
const mermaidOnly = process.argv.includes('--mermaid');
|
||||
const coverage = process.env.VITE_COVERAGE === 'true';
|
||||
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
||||
const sourcemap = false;
|
||||
|
||||
@ -121,6 +123,12 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
|
||||
jisonPlugin(),
|
||||
// @ts-expect-error According to the type definitions, rollup plugins are incompatible with vite
|
||||
typescript({ compilerOptions: { declaration: false } }),
|
||||
istanbul({
|
||||
exclude: ['node_modules', 'test/', '__mocks__'],
|
||||
extension: ['.js', '.ts'],
|
||||
requireEnv: true,
|
||||
forceBuildInstrument: coverage,
|
||||
}),
|
||||
...visualizerOptions(packageName, core),
|
||||
],
|
||||
};
|
||||
|
@ -1,8 +1,6 @@
|
||||
// @ts-ignore No typings for jison
|
||||
import jison from 'jison';
|
||||
|
||||
export const transformJison = (src: string): string => {
|
||||
// @ts-ignore No typings for jison
|
||||
const parser = new jison.Generator(src, {
|
||||
moduleType: 'js',
|
||||
'token-stack': true,
|
||||
|
16
CITATION.cff
Normal file
16
CITATION.cff
Normal file
@ -0,0 +1,16 @@
|
||||
cff-version: 1.2.0
|
||||
title: 'Mermaid: Generate diagrams from markdown-like text'
|
||||
message: >-
|
||||
If you use this software, please cite it using the metadata from this file.
|
||||
type: software
|
||||
authors:
|
||||
- family-names: Sveidqvist
|
||||
given-names: Knut
|
||||
- name: 'Contributors to Mermaid'
|
||||
repository-code: 'https://github.com/mermaid-js/mermaid'
|
||||
date-released: 2014-12-02
|
||||
url: 'https://mermaid.js.org/'
|
||||
abstract: >-
|
||||
JavaScript based diagramming and charting tool that renders Markdown-inspired
|
||||
text definitions to create and modify diagrams dynamically.
|
||||
license: MIT
|
@ -27,7 +27,7 @@ Generate diagrams from markdown-like text.
|
||||
[![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/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 minified gzipped bundle size](https://img.shields.io/bundlephobia/minzip/mermaid)](https://bundlephobia.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)
|
||||
[![Coverage Status](https://codecov.io/github/mermaid-js/mermaid/branch/develop/graph/badge.svg)](https://app.codecov.io/github/mermaid-js/mermaid/tree/develop)
|
||||
[![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid)
|
||||
[![NPM Downloads](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)
|
||||
@ -386,7 +386,7 @@ Update version number in `package.json`.
|
||||
npm publish
|
||||
```
|
||||
|
||||
The above command generates files into the `dist` folder and publishes them to npmjs.org.
|
||||
The above command generates files into the `dist` folder and publishes them to <https://www.npmjs.com>.
|
||||
|
||||
## Related projects
|
||||
|
||||
@ -402,7 +402,7 @@ Detailed information about how to contribute can be found in the [contribution g
|
||||
|
||||
## Security and safe diagrams
|
||||
|
||||
For public sites, it can be precarious to retrieve text from users on the internet, storing that content for presentation in a browser at a later stage. The reason is that the user content can contain embedded malicious scripts that will run when the data is presented. For Mermaid this is a risk, specially as mermaid diagrams contain many characters that are used in html which makes the standard sanitation unusable as it also breaks the diagrams. We still make an effort to sanitise the incoming code and keep refining the process but it is hard to guarantee that there are no loop holes.
|
||||
For public sites, it can be precarious to retrieve text from users on the internet, storing that content for presentation in a browser at a later stage. The reason is that the user content can contain embedded malicious scripts that will run when the data is presented. For Mermaid this is a risk, specially as mermaid diagrams contain many characters that are used in html which makes the standard sanitation unusable as it also breaks the diagrams. We still make an effort to sanitize the incoming code and keep refining the process but it is hard to guarantee that there are no loop holes.
|
||||
|
||||
As an extra level of security for sites with external users we are happy to introduce a new security level in which the diagram is rendered in a sandboxed iframe preventing javascript in the code from being executed. This is a great step forward for better security.
|
||||
|
||||
@ -410,7 +410,7 @@ _Unfortunately you can not have a cake and eat it at the same time which in this
|
||||
|
||||
## Reporting vulnerabilities
|
||||
|
||||
To report a vulnerability, please e-mail security@mermaid.live with a description of the issue, the steps you took to create the issue, affected versions, and if known, mitigations for the issue.
|
||||
To report a vulnerability, please e-mail <security@mermaid.live> with a description of the issue, the steps you took to create the issue, affected versions, and if known, mitigations for the issue.
|
||||
|
||||
## Appreciation
|
||||
|
||||
|
@ -27,7 +27,7 @@ Mermaid
|
||||
[![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/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 minified gzipped bundle size](https://img.shields.io/bundlephobia/minzip/mermaid)](https://bundlephobia.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)
|
||||
[![Coverage Status](https://codecov.io/github/mermaid-js/mermaid/branch/develop/graph/badge.svg)](https://app.codecov.io/github/mermaid-js/mermaid/tree/develop)
|
||||
[![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid)
|
||||
[![NPM Downloads](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)
|
||||
@ -322,7 +322,7 @@ Rel(SystemC, customerA, "Sends e-mails to")
|
||||
npm publish
|
||||
```
|
||||
|
||||
以上的命令会将文件打包到 `dist` 目录并发布至 npmjs.org.
|
||||
以上的命令会将文件打包到 `dist` 目录并发布至 <https://www.npmjs.com>.
|
||||
|
||||
## 相关项目
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
// @ts-nocheck TODO: Fix TS
|
||||
import { MockedD3 } from '../packages/mermaid/src/tests/MockedD3.js';
|
||||
|
||||
export const select = function () {
|
||||
|
@ -40,8 +40,10 @@
|
||||
"dompurify",
|
||||
"edgechromium",
|
||||
"elkjs",
|
||||
"elle",
|
||||
"faber",
|
||||
"flatmap",
|
||||
"foswiki",
|
||||
"ftplugin",
|
||||
"gantt",
|
||||
"gitea",
|
||||
@ -51,6 +53,7 @@
|
||||
"graphviz",
|
||||
"grav",
|
||||
"greywolf",
|
||||
"gzipped",
|
||||
"huynh",
|
||||
"huynhicode",
|
||||
"inkdrop",
|
||||
@ -84,6 +87,7 @@
|
||||
"mkdocs",
|
||||
"mmorel",
|
||||
"mult",
|
||||
"neurodiverse",
|
||||
"nextra",
|
||||
"orlandoni",
|
||||
"pathe",
|
||||
|
6
codecov.yaml
Normal file
6
codecov.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
comment:
|
||||
layout: 'reach, diff, flags, files'
|
||||
behavior: default
|
||||
require_changes: false # if true: only post the comment if coverage changes
|
||||
require_base: no # [yes :: must have a base report to post]
|
||||
require_head: yes # [yes :: must have a head report to post]
|
@ -2,12 +2,14 @@
|
||||
|
||||
const { defineConfig } = require('cypress');
|
||||
const { addMatchImageSnapshotPlugin } = require('cypress-image-snapshot/plugin');
|
||||
const coverage = require('@cypress/code-coverage/task');
|
||||
|
||||
module.exports = defineConfig({
|
||||
projectId: 'n2sma2',
|
||||
e2e: {
|
||||
specPattern: 'cypress/integration/**/*.{js,jsx,ts,tsx}',
|
||||
setupNodeEvents(on, config) {
|
||||
coverage(on, config);
|
||||
addMatchImageSnapshotPlugin(on, config);
|
||||
// copy any needed variables from process.env to config.env
|
||||
config.env.useAppli = process.env.USE_APPLI ? true : false;
|
||||
|
@ -172,7 +172,7 @@ describe('Flowchart v2', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('52: handle nested subgraphs in several levels', () => {
|
||||
it('52: handle nested subgraphs in several levels.', () => {
|
||||
imgSnapshotTest(
|
||||
`flowchart TB
|
||||
b-->B
|
||||
|
@ -1,13 +0,0 @@
|
||||
import { imgSnapshotTest } from '../../helpers/util.js';
|
||||
|
||||
describe('Sequencediagram', () => {
|
||||
it('should render a simple info diagrams', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
info
|
||||
showInfo
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
});
|
11
cypress/integration/rendering/info.spec.ts
Normal file
11
cypress/integration/rendering/info.spec.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { imgSnapshotTest } from '../../helpers/util.js';
|
||||
|
||||
describe('info diagram', () => {
|
||||
it('should handle an info definition', () => {
|
||||
imgSnapshotTest(`info`);
|
||||
});
|
||||
|
||||
it('should handle an info definition with showInfo', () => {
|
||||
imgSnapshotTest(`info showInfo`);
|
||||
});
|
||||
});
|
@ -1,23 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>info below</h1>
|
||||
<pre class="mermaid">
|
||||
info
|
||||
</pre>
|
||||
<script type="module">
|
||||
import mermaid from './mermaid.esm.mjs';
|
||||
mermaid.initialize({
|
||||
theme: 'forest',
|
||||
// themeCSS: '.node rect { fill: red; }',
|
||||
logLevel: 3,
|
||||
flowchart: { curve: 'linear' },
|
||||
gantt: { axisFormat: '%m/%d/%Y' },
|
||||
sequence: { actorMargin: 50 },
|
||||
// sequenceDiagram: { actorMargin: 300 } // deprecated
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -13,8 +13,8 @@
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
import '@cypress/code-coverage/support';
|
||||
import '@applitools/eyes-cypress/commands';
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands';
|
||||
|
||||
|
@ -154,6 +154,29 @@
|
||||
</pre>
|
||||
<hr />
|
||||
|
||||
<pre class="mermaid">
|
||||
classDiagram
|
||||
A1 --> B1
|
||||
namespace A {
|
||||
class A1 {
|
||||
+foo : string
|
||||
}
|
||||
class A2 {
|
||||
+bar : int
|
||||
}
|
||||
}
|
||||
namespace B {
|
||||
class B1 {
|
||||
+foo : bool
|
||||
}
|
||||
class B2 {
|
||||
+bar : float
|
||||
}
|
||||
}
|
||||
A2 --> B2
|
||||
</pre>
|
||||
<hr />
|
||||
|
||||
<script type="module">
|
||||
import mermaid from './mermaid.esm.mjs';
|
||||
mermaid.initialize({
|
||||
|
@ -1505,6 +1505,34 @@
|
||||
</pre>
|
||||
<hr />
|
||||
|
||||
<pre class="mermaid">
|
||||
graph TD
|
||||
A([Start]) ==> B[Step 1]
|
||||
B ==> C{Flow 1}
|
||||
C -- Choice 1.1 --> D[Step 2.1]
|
||||
C -- Choice 1.3 --> I[Step 2.3]
|
||||
C == Choice 1.2 ==> E[Step 2.2]
|
||||
D --> F{Flow 2}
|
||||
E ==> F{Flow 2}
|
||||
F{Flow 2} == Choice 2.1 ==> H[Feedback node]
|
||||
H[Feedback node] ==> B[Step 1]
|
||||
F{Flow 2} == Choice 2.2 ==> G((Finish))
|
||||
|
||||
linkStyle 0,1,4,6,7,8,9 stroke:gold, stroke-width:4px
|
||||
|
||||
classDef active_node fill:#0CF,stroke:#09F,stroke-width:6px
|
||||
classDef unactive_node fill:#e0e0e0,stroke:#bdbdbd,stroke-width:3px
|
||||
classDef bugged_node fill:#F88,stroke:#F22,stroke-width:3px
|
||||
classDef start_node,finish_node fill:#3B1,stroke:#391,stroke-width:8px
|
||||
|
||||
class A start_node;
|
||||
class B,C,E,F,H active_node;
|
||||
class D unactive_node;
|
||||
class G finish_node;
|
||||
class I bugged_node
|
||||
</pre>
|
||||
<hr />
|
||||
|
||||
<h1 id="link-clicked">Anchor for "link-clicked" test</h1>
|
||||
|
||||
<script type="module">
|
||||
|
@ -45,6 +45,9 @@
|
||||
<li>
|
||||
<h2><a href="./git.html">Git</a></h2>
|
||||
</li>
|
||||
<li>
|
||||
<h2><a href="./info.html">Info</a></h2>
|
||||
</li>
|
||||
<li>
|
||||
<h2><a href="./journey.html">Journey</a></h2>
|
||||
</li>
|
||||
@ -66,6 +69,9 @@
|
||||
<li>
|
||||
<h2><a href="./state.html">State</a></h2>
|
||||
</li>
|
||||
<li>
|
||||
<h2><a href="./timeline.html">Timeline</a></h2>
|
||||
</li>
|
||||
<li>
|
||||
<h2><a href="./zenuml.html">ZenUML</a></h2>
|
||||
</li>
|
||||
|
35
demos/info.html
Normal file
35
demos/info.html
Normal file
@ -0,0 +1,35 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>Mermaid Quick Test Page</title>
|
||||
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=" />
|
||||
<style>
|
||||
div.mermaid {
|
||||
font-family: 'Courier New', Courier, monospace !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Info diagram demos</h1>
|
||||
<pre class="mermaid">
|
||||
info
|
||||
</pre>
|
||||
|
||||
<hr />
|
||||
<pre class="mermaid">
|
||||
info showInfo
|
||||
</pre>
|
||||
|
||||
<script type="module">
|
||||
import mermaid from './mermaid.esm.mjs';
|
||||
mermaid.initialize({
|
||||
theme: 'forest',
|
||||
logLevel: 3,
|
||||
securityLevel: 'loose',
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,7 +1,7 @@
|
||||
version: '3.9'
|
||||
services:
|
||||
mermaid:
|
||||
image: node:18.16.0-alpine3.18
|
||||
image: node:20.3.1-alpine3.18
|
||||
stdin_open: true
|
||||
tty: true
|
||||
working_dir: /mermaid
|
||||
|
@ -26,6 +26,10 @@ The definitions that can be generated the Live-Editor are also backwards-compati
|
||||
|
||||
[Eddie Jaoude: Can you code your diagrams?](https://www.youtube.com/watch?v=9HZzKkAqrX8)
|
||||
|
||||
## Mermaid with OpenAI
|
||||
|
||||
[Elle Neal: Mind Mapping with AI: An Accessible Approach for Neurodiverse Learners Tutorial:](https://medium.com/@elle.neal_71064/mind-mapping-with-ai-an-accessible-approach-for-neurodiverse-learners-1a74767359ff), [Demo:](https://databutton.com/v/jk9vrghc)
|
||||
|
||||
## Mermaid with HTML
|
||||
|
||||
Examples are provided in [Getting Started](../intro/n00b-gettingStarted.md)
|
||||
|
@ -39,7 +39,7 @@ bindFunctions?.(div); // To call bindFunctions only if it's present.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:98](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L98)
|
||||
[mermaidAPI.ts:97](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L97)
|
||||
|
||||
---
|
||||
|
||||
@ -51,4 +51,4 @@ The svg code for the rendered graph.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:88](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L88)
|
||||
[mermaidAPI.ts:87](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L87)
|
||||
|
@ -25,7 +25,7 @@ Renames and re-exports [mermaidAPI](mermaidAPI.md#mermaidapi)
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:82](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L82)
|
||||
[mermaidAPI.ts:81](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L81)
|
||||
|
||||
## Variables
|
||||
|
||||
@ -96,7 +96,7 @@ mermaid.initialize(config);
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:670](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L670)
|
||||
[mermaidAPI.ts:663](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L663)
|
||||
|
||||
## Functions
|
||||
|
||||
@ -127,7 +127,7 @@ Return the last node appended
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:309](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L309)
|
||||
[mermaidAPI.ts:308](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L308)
|
||||
|
||||
---
|
||||
|
||||
@ -153,7 +153,7 @@ the cleaned up svgCode
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:257](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L257)
|
||||
[mermaidAPI.ts:256](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L256)
|
||||
|
||||
---
|
||||
|
||||
@ -179,7 +179,7 @@ the string with all the user styles
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:186](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L186)
|
||||
[mermaidAPI.ts:185](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L185)
|
||||
|
||||
---
|
||||
|
||||
@ -202,7 +202,7 @@ the string with all the user styles
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:234](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L234)
|
||||
[mermaidAPI.ts:233](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L233)
|
||||
|
||||
---
|
||||
|
||||
@ -229,7 +229,7 @@ with an enclosing block that has each of the cssClasses followed by !important;
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:170](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L170)
|
||||
[mermaidAPI.ts:169](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L169)
|
||||
|
||||
---
|
||||
|
||||
@ -249,7 +249,7 @@ with an enclosing block that has each of the cssClasses followed by !important;
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:156](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L156)
|
||||
[mermaidAPI.ts:155](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L155)
|
||||
|
||||
---
|
||||
|
||||
@ -269,7 +269,7 @@ with an enclosing block that has each of the cssClasses followed by !important;
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:127](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L127)
|
||||
[mermaidAPI.ts:126](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L126)
|
||||
|
||||
---
|
||||
|
||||
@ -295,7 +295,7 @@ Put the svgCode into an iFrame. Return the iFrame code
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:288](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L288)
|
||||
[mermaidAPI.ts:287](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L287)
|
||||
|
||||
---
|
||||
|
||||
@ -320,4 +320,4 @@ Remove any existing elements from the given document
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:359](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L359)
|
||||
[mermaidAPI.ts:358](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L358)
|
||||
|
@ -66,7 +66,7 @@ They also serve as proof of concept, for the variety of things that can be built
|
||||
|
||||
## Blogs
|
||||
|
||||
- [Wordpress](https://wordpress.org)
|
||||
- [WordPress](https://wordpress.org)
|
||||
- [WordPress Markdown Editor](https://wordpress.org/plugins/wp-githuber-md)
|
||||
- [WP-ReliableMD](https://wordpress.org/plugins/wp-reliablemd/)
|
||||
- [Hexo](https://hexo.io)
|
||||
@ -84,7 +84,7 @@ They also serve as proof of concept, for the variety of things that can be built
|
||||
- [Plugin for Mermaid.js](https://github.com/eFrane/vuepress-plugin-mermaidjs)
|
||||
- [Grav CMS](https://getgrav.org/)
|
||||
- [Mermaid Diagrams](https://github.com/DanielFlaum/grav-plugin-mermaid-diagrams)
|
||||
- [Gitlab Markdown Adapter](https://github.com/Goutte/grav-plugin-gitlab-markdown-adapter)
|
||||
- [GitLab Markdown Adapter](https://github.com/Goutte/grav-plugin-gitlab-markdown-adapter)
|
||||
|
||||
## Communication
|
||||
|
||||
@ -104,7 +104,7 @@ They also serve as proof of concept, for the variety of things that can be built
|
||||
- [Flex Diagrams Extension](https://www.mediawiki.org/wiki/Extension:Flex_Diagrams)
|
||||
- [Semantic Media Wiki](https://semantic-mediawiki.org)
|
||||
- [Mermaid Plugin](https://github.com/SemanticMediaWiki/Mermaid)
|
||||
- [FosWiki](https://foswiki.org)
|
||||
- [Foswiki](https://foswiki.org)
|
||||
- [Mermaid Plugin](https://foswiki.org/Extensions/MermaidPlugin)
|
||||
- [DokuWiki](https://dokuwiki.org)
|
||||
- [Mermaid Plugin](https://www.dokuwiki.org/plugin:mermaid)
|
||||
@ -161,6 +161,8 @@ They also serve as proof of concept, for the variety of things that can be built
|
||||
- [Nano Mermaid](https://github.com/Yash-Singh1/nano-mermaid)
|
||||
- [CKEditor](https://github.com/ckeditor/ckeditor5)
|
||||
- [CKEditor 5 Mermaid plugin](https://github.com/ckeditor/ckeditor5-mermaid)
|
||||
- [Standard Notes](https://standardnotes.com/)
|
||||
- [sn-mermaid](https://github.com/nienow/sn-mermaid)
|
||||
|
||||
## Document Generation
|
||||
|
||||
@ -172,7 +174,7 @@ They also serve as proof of concept, for the variety of things that can be built
|
||||
- [rehype-mermaidjs](https://github.com/remcohaszing/rehype-mermaidjs)
|
||||
- [Gatsby](https://www.gatsbyjs.com/)
|
||||
- [gatsby-remark-mermaid](https://github.com/remcohaszing/gatsby-remark-mermaid)
|
||||
- [jSDoc](https://jsdoc.app/)
|
||||
- [JSDoc](https://jsdoc.app/)
|
||||
- [jsdoc-mermaid](https://github.com/Jellyvision/jsdoc-mermaid)
|
||||
- [MkDocs](https://www.mkdocs.org)
|
||||
- [mkdocs-mermaid2-plugin](https://github.com/fralau/mkdocs-mermaid2-plugin)
|
||||
|
@ -919,6 +919,10 @@ In the example below the style defined in the linkStyle statement will belong to
|
||||
|
||||
linkStyle 3 stroke:#ff3,stroke-width:4px,color:red;
|
||||
|
||||
It is also possible to add style to multiple links in a single statement, by separating link numbers with commas:
|
||||
|
||||
linkStyle 1,2,7 color:blue;
|
||||
|
||||
### Styling line curves
|
||||
|
||||
It is possible to style the type of curve used for lines between items, if the default method does not meet your needs.
|
||||
@ -957,10 +961,14 @@ flowchart LR
|
||||
More convenient than defining the style every time is to define a class of styles and attach this class to the nodes that
|
||||
should have a different look.
|
||||
|
||||
a class definition looks like the example below:
|
||||
A class definition looks like the example below:
|
||||
|
||||
classDef className fill:#f9f,stroke:#333,stroke-width:4px;
|
||||
|
||||
Also, it is possible to define style to multiple classes in one statement:
|
||||
|
||||
classDef firstClassName,secondClassName font-size:12pt;
|
||||
|
||||
Attachment of a class to a node is done as per below:
|
||||
|
||||
class nodeId1 className;
|
||||
|
@ -25,25 +25,25 @@ Mermaid can render Gantt diagrams as SVG, PNG or a MarkDown link that can be pas
|
||||
```mermaid-example
|
||||
gantt
|
||||
title A Gantt Diagram
|
||||
dateFormat YYYY-MM-DD
|
||||
dateFormat YYYY-MM-DD
|
||||
section Section
|
||||
A task :a1, 2014-01-01, 30d
|
||||
Another task :after a1 , 20d
|
||||
A task :a1, 2014-01-01, 30d
|
||||
Another task :after a1, 20d
|
||||
section Another
|
||||
Task in sec :2014-01-12 , 12d
|
||||
another task : 24d
|
||||
Task in Another :2014-01-12, 12d
|
||||
another task :24d
|
||||
```
|
||||
|
||||
```mermaid
|
||||
gantt
|
||||
title A Gantt Diagram
|
||||
dateFormat YYYY-MM-DD
|
||||
dateFormat YYYY-MM-DD
|
||||
section Section
|
||||
A task :a1, 2014-01-01, 30d
|
||||
Another task :after a1 , 20d
|
||||
A task :a1, 2014-01-01, 30d
|
||||
Another task :after a1, 20d
|
||||
section Another
|
||||
Task in sec :2014-01-12 , 12d
|
||||
another task : 24d
|
||||
Task in Another :2014-01-12, 12d
|
||||
another task :24d
|
||||
```
|
||||
|
||||
## Syntax
|
||||
@ -117,17 +117,17 @@ gantt
|
||||
It is possible to set multiple dependencies separated by space:
|
||||
|
||||
```mermaid-example
|
||||
gantt
|
||||
apple :a, 2017-07-20, 1w
|
||||
banana :crit, b, 2017-07-23, 1d
|
||||
cherry :active, c, after b a, 1d
|
||||
gantt
|
||||
apple :a, 2017-07-20, 1w
|
||||
banana :crit, b, 2017-07-23, 1d
|
||||
cherry :active, c, after b a, 1d
|
||||
```
|
||||
|
||||
```mermaid
|
||||
gantt
|
||||
apple :a, 2017-07-20, 1w
|
||||
banana :crit, b, 2017-07-23, 1d
|
||||
cherry :active, c, after b a, 1d
|
||||
gantt
|
||||
apple :a, 2017-07-20, 1w
|
||||
banana :crit, b, 2017-07-23, 1d
|
||||
cherry :active, c, after b a, 1d
|
||||
```
|
||||
|
||||
### Title
|
||||
@ -146,22 +146,22 @@ You can add milestones to the diagrams. Milestones differ from tasks as they rep
|
||||
|
||||
```mermaid-example
|
||||
gantt
|
||||
dateFormat HH:mm
|
||||
axisFormat %H:%M
|
||||
Initial milestone : milestone, m1, 17:49,2min
|
||||
taska2 : 10min
|
||||
taska3 : 5min
|
||||
Final milestone : milestone, m2, 18:14, 2min
|
||||
dateFormat HH:mm
|
||||
axisFormat %H:%M
|
||||
Initial milestone : milestone, m1, 17:49, 2m
|
||||
Task A : 10m
|
||||
Task B : 5m
|
||||
Final milestone : milestone, m2, 18:08, 4m
|
||||
```
|
||||
|
||||
```mermaid
|
||||
gantt
|
||||
dateFormat HH:mm
|
||||
axisFormat %H:%M
|
||||
Initial milestone : milestone, m1, 17:49,2min
|
||||
taska2 : 10min
|
||||
taska3 : 5min
|
||||
Final milestone : milestone, m2, 18:14, 2min
|
||||
dateFormat HH:mm
|
||||
axisFormat %H:%M
|
||||
Initial milestone : milestone, m1, 17:49, 2m
|
||||
Task A : 10m
|
||||
Task B : 5m
|
||||
Final milestone : milestone, m2, 18:08, 4m
|
||||
```
|
||||
|
||||
## Setting dates
|
||||
@ -296,29 +296,27 @@ Comments can be entered within a gantt chart, which will be ignored by the parse
|
||||
```mermaid-example
|
||||
gantt
|
||||
title A Gantt Diagram
|
||||
%% this is a comment
|
||||
dateFormat YYYY-MM-DD
|
||||
%% This is a comment
|
||||
dateFormat YYYY-MM-DD
|
||||
section Section
|
||||
A task :a1, 2014-01-01, 30d
|
||||
Another task :after a1 , 20d
|
||||
A task :a1, 2014-01-01, 30d
|
||||
Another task :after a1, 20d
|
||||
section Another
|
||||
Task in sec :2014-01-12 , 12d
|
||||
another task : 24d
|
||||
|
||||
Task in Another :2014-01-12, 12d
|
||||
another task :24d
|
||||
```
|
||||
|
||||
```mermaid
|
||||
gantt
|
||||
title A Gantt Diagram
|
||||
%% this is a comment
|
||||
dateFormat YYYY-MM-DD
|
||||
%% This is a comment
|
||||
dateFormat YYYY-MM-DD
|
||||
section Section
|
||||
A task :a1, 2014-01-01, 30d
|
||||
Another task :after a1 , 20d
|
||||
A task :a1, 2014-01-01, 30d
|
||||
Another task :after a1, 20d
|
||||
section Another
|
||||
Task in sec :2014-01-12 , 12d
|
||||
another task : 24d
|
||||
|
||||
Task in Another :2014-01-12, 12d
|
||||
another task :24d
|
||||
```
|
||||
|
||||
## Styling
|
||||
@ -440,7 +438,7 @@ Beginner's tip—a full example using interactive links in an html context:
|
||||
dateFormat YYYY-MM-DD
|
||||
|
||||
section Clickable
|
||||
Visit mermaidjs :active, cl1, 2014-01-07, 3d
|
||||
Visit mermaidjs :active, cl1, 2014-01-07, 3d
|
||||
Print arguments :cl2, after cl1, 3d
|
||||
Print task :cl3, after cl2, 3d
|
||||
|
||||
|
@ -152,7 +152,7 @@ quadrantChart
|
||||
y-axis Not Important --> "Important ❤"
|
||||
quadrant-1 Plan
|
||||
quadrant-2 Do
|
||||
quadrant-3 Deligate
|
||||
quadrant-3 Delegate
|
||||
quadrant-4 Delete
|
||||
```
|
||||
|
||||
@ -163,6 +163,6 @@ quadrantChart
|
||||
y-axis Not Important --> "Important ❤"
|
||||
quadrant-1 Plan
|
||||
quadrant-2 Do
|
||||
quadrant-3 Deligate
|
||||
quadrant-3 Delegate
|
||||
quadrant-4 Delete
|
||||
```
|
||||
|
@ -257,9 +257,11 @@ let us look at same example, where we have disabled the multiColor option.
|
||||
|
||||
### Customizing Color scheme
|
||||
|
||||
You can customize the color scheme using the `cScale0` to `cScale11` theme variables. Mermaid allows you to set unique colors for up-to 12 sections, where `cScale0` variable will drive the value of the first section or time-period, `cScale1` will drive the value of the second section and so on.
|
||||
You can customize the color scheme using the `cScale0` to `cScale11` theme variables, which will change the background colors. Mermaid allows you to set unique colors for up-to 12 sections, where `cScale0` variable will drive the value of the first section or time-period, `cScale1` will drive the value of the second section and so on.
|
||||
In case you have more than 12 sections, the color scheme will start to repeat.
|
||||
|
||||
If you also want to change the foreground color of a section, you can do so use theme variables corresponding `cScaleLabel0` to `cScaleLabel11` variables.
|
||||
|
||||
NOTE: Default values for these theme variables are picked from the selected theme. If you want to override the default values, you can use the `initialize` call to add your custom theme variable values.
|
||||
|
||||
Example:
|
||||
@ -268,9 +270,9 @@ Now let's override the default values for the `cScale0` to `cScale2` variables:
|
||||
|
||||
```mermaid-example
|
||||
%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': {
|
||||
'cScale0': '#ff0000',
|
||||
'cScale0': '#ff0000', 'cScaleLabel0': '#ffffff',
|
||||
'cScale1': '#00ff00',
|
||||
'cScale2': '#0000ff'
|
||||
'cScale2': '#0000ff', 'cScaleLabel2': '#ffffff'
|
||||
} } }%%
|
||||
timeline
|
||||
title History of Social Media Platform
|
||||
@ -286,9 +288,9 @@ Now let's override the default values for the `cScale0` to `cScale2` variables:
|
||||
|
||||
```mermaid
|
||||
%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': {
|
||||
'cScale0': '#ff0000',
|
||||
'cScale0': '#ff0000', 'cScaleLabel0': '#ffffff',
|
||||
'cScale1': '#00ff00',
|
||||
'cScale2': '#0000ff'
|
||||
'cScale2': '#0000ff', 'cScaleLabel2': '#ffffff'
|
||||
} } }%%
|
||||
timeline
|
||||
title History of Social Media Platform
|
||||
|
43
package.json
43
package.json
@ -1,10 +1,10 @@
|
||||
{
|
||||
"name": "mermaid-monorepo",
|
||||
"private": true,
|
||||
"version": "10.2.3",
|
||||
"version": "10.2.4",
|
||||
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
|
||||
"type": "module",
|
||||
"packageManager": "pnpm@8.5.1",
|
||||
"packageManager": "pnpm@8.6.5",
|
||||
"keywords": [
|
||||
"diagram",
|
||||
"markdown",
|
||||
@ -22,6 +22,7 @@
|
||||
"build:watch": "pnpm build:vite --watch",
|
||||
"build": "pnpm run -r clean && pnpm build:types && pnpm build:vite",
|
||||
"dev": "concurrently \"pnpm build:vite --watch\" \"ts-node-esm .vite/server.ts\"",
|
||||
"dev:coverage": "pnpm coverage:cypress:clean && VITE_COVERAGE=true pnpm dev",
|
||||
"release": "pnpm build",
|
||||
"lint": "eslint --cache --cache-strategy content --ignore-path .gitignore . && pnpm lint:jison && prettier --cache --check .",
|
||||
"lint:fix": "eslint --cache --cache-strategy content --fix --ignore-path .gitignore . && prettier --write . && ts-node-esm scripts/fixCSpell.ts",
|
||||
@ -30,6 +31,10 @@
|
||||
"cypress": "cypress run",
|
||||
"cypress:open": "cypress open",
|
||||
"e2e": "start-server-and-test dev http://localhost:9000/ cypress",
|
||||
"coverage:cypress:clean": "rimraf .nyc_output coverage/cypress",
|
||||
"e2e:coverage": "pnpm coverage:cypress:clean && VITE_COVERAGE=true pnpm e2e",
|
||||
"coverage:merge": "ts-node-esm scripts/coverage.ts",
|
||||
"coverage": "pnpm test:coverage --run && pnpm e2e:coverage && pnpm coverage:merge",
|
||||
"ci": "vitest run",
|
||||
"test": "pnpm lint && vitest run",
|
||||
"test:watch": "vitest --watch",
|
||||
@ -55,11 +60,12 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@applitools/eyes-cypress": "^3.32.0",
|
||||
"@applitools/eyes-cypress": "^3.33.1",
|
||||
"@commitlint/cli": "^17.6.1",
|
||||
"@commitlint/config-conventional": "^17.6.1",
|
||||
"@cspell/eslint-plugin": "^6.31.1",
|
||||
"@rollup/plugin-typescript": "^11.1.0",
|
||||
"@cypress/code-coverage": "^3.10.7",
|
||||
"@rollup/plugin-typescript": "^11.1.1",
|
||||
"@types/cors": "^2.8.13",
|
||||
"@types/eslint": "^8.37.0",
|
||||
"@types/express": "^4.17.17",
|
||||
@ -72,48 +78,53 @@
|
||||
"@types/rollup-plugin-visualizer": "^4.2.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.0",
|
||||
"@typescript-eslint/parser": "^5.59.0",
|
||||
"@vitest/coverage-c8": "^0.31.0",
|
||||
"@vitest/spy": "^0.31.0",
|
||||
"@vitest/ui": "^0.31.0",
|
||||
"@vitest/coverage-v8": "^0.32.2",
|
||||
"@vitest/spy": "^0.32.2",
|
||||
"@vitest/ui": "^0.32.2",
|
||||
"concurrently": "^8.0.1",
|
||||
"cors": "^2.8.5",
|
||||
"coveralls": "^3.1.1",
|
||||
"cypress": "^12.10.0",
|
||||
"cypress-image-snapshot": "^4.0.1",
|
||||
"esbuild": "^0.17.18",
|
||||
"esbuild": "^0.18.0",
|
||||
"eslint": "^8.39.0",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
"eslint-plugin-cypress": "^2.13.2",
|
||||
"eslint-plugin-html": "^7.1.0",
|
||||
"eslint-plugin-jest": "^27.2.1",
|
||||
"eslint-plugin-jsdoc": "^43.0.7",
|
||||
"eslint-plugin-jsdoc": "^46.0.0",
|
||||
"eslint-plugin-json": "^3.1.0",
|
||||
"eslint-plugin-lodash": "^7.4.0",
|
||||
"eslint-plugin-markdown": "^3.0.0",
|
||||
"eslint-plugin-no-only-tests": "^3.1.0",
|
||||
"eslint-plugin-tsdoc": "^0.2.17",
|
||||
"eslint-plugin-unicorn": "^46.0.0",
|
||||
"eslint-plugin-unicorn": "^47.0.0",
|
||||
"express": "^4.18.2",
|
||||
"globby": "^13.1.4",
|
||||
"husky": "^8.0.3",
|
||||
"jest": "^29.5.0",
|
||||
"jison": "^0.4.18",
|
||||
"js-yaml": "^4.1.0",
|
||||
"jsdom": "^21.1.1",
|
||||
"jsdom": "^22.0.0",
|
||||
"lint-staged": "^13.2.1",
|
||||
"nyc": "^15.1.0",
|
||||
"path-browserify": "^1.0.1",
|
||||
"pnpm": "^8.3.1",
|
||||
"prettier": "^2.8.8",
|
||||
"prettier-plugin-jsdoc": "^0.4.2",
|
||||
"rimraf": "^5.0.0",
|
||||
"rollup-plugin-visualizer": "^5.9.0",
|
||||
"rollup-plugin-visualizer": "^5.9.2",
|
||||
"start-server-and-test": "^2.0.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^5.0.4",
|
||||
"vite": "^4.3.1",
|
||||
"vitest": "^0.31.0"
|
||||
"typescript": "^5.1.3",
|
||||
"vite": "^4.3.9",
|
||||
"vite-plugin-istanbul": "^4.1.0",
|
||||
"vitest": "^0.32.2"
|
||||
},
|
||||
"volta": {
|
||||
"node": "18.16.0"
|
||||
"node": "18.16.1"
|
||||
},
|
||||
"nyc": {
|
||||
"report-dir": "coverage/cypress"
|
||||
}
|
||||
}
|
||||
|
@ -52,9 +52,6 @@
|
||||
"rimraf": "^5.0.0",
|
||||
"mermaid": "workspace:*"
|
||||
},
|
||||
"resolutions": {
|
||||
"d3": "^7.0.0"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
|
@ -3,7 +3,7 @@ import type { ExternalDiagramDefinition } from 'mermaid';
|
||||
const id = 'example-diagram';
|
||||
|
||||
const detector = (txt: string) => {
|
||||
return txt.match(/^\s*example-diagram/) !== null;
|
||||
return /^\s*example-diagram/.test(txt);
|
||||
};
|
||||
|
||||
const loader = async () => {
|
||||
|
@ -1,10 +1,9 @@
|
||||
import type { ExternalDiagramDefinition } from 'mermaid';
|
||||
|
||||
const id = 'zenuml';
|
||||
const regexp = /^\s*zenuml/;
|
||||
|
||||
const detector = (txt: string) => {
|
||||
return txt.match(regexp) !== null;
|
||||
return /^\s*zenuml/.test(txt);
|
||||
};
|
||||
|
||||
const loader = async () => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mermaid",
|
||||
"version": "10.2.3",
|
||||
"version": "10.2.4",
|
||||
"description": "Markdown-ish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
|
||||
"type": "module",
|
||||
"module": "./dist/mermaid.core.mjs",
|
||||
@ -73,6 +73,7 @@
|
||||
"devDependencies": {
|
||||
"@types/cytoscape": "^3.19.9",
|
||||
"@types/d3": "^7.4.0",
|
||||
"@types/d3-selection": "^3.0.5",
|
||||
"@types/dompurify": "^3.0.2",
|
||||
"@types/jsdom": "^21.1.1",
|
||||
"@types/lodash-es": "^4.17.7",
|
||||
@ -91,7 +92,7 @@
|
||||
"globby": "^13.1.4",
|
||||
"jison": "^0.4.18",
|
||||
"js-base64": "^3.7.5",
|
||||
"jsdom": "^21.1.1",
|
||||
"jsdom": "^22.0.0",
|
||||
"micromatch": "^4.0.5",
|
||||
"path-browserify": "^1.0.1",
|
||||
"prettier": "^2.8.8",
|
||||
|
@ -51,7 +51,6 @@ describe('accessibility', () => {
|
||||
desc: string | null | undefined,
|
||||
givenId: string
|
||||
) {
|
||||
// @ts-ignore Required to easily handle the d3 select types
|
||||
const svgAttrSpy = vi.spyOn(svgD3Node, 'attr').mockReturnValue(svgD3Node);
|
||||
addSVGa11yTitleDescription(svgD3Node, title, desc, givenId);
|
||||
expect(svgAttrSpy).toHaveBeenCalledWith('aria-labelledby', `chart-title-${givenId}`);
|
||||
@ -63,7 +62,6 @@ describe('accessibility', () => {
|
||||
desc: string | null | undefined,
|
||||
givenId: string
|
||||
) {
|
||||
// @ts-ignore Required to easily handle the d3 select types
|
||||
const svgAttrSpy = vi.spyOn(svgD3Node, 'attr').mockReturnValue(svgD3Node);
|
||||
addSVGa11yTitleDescription(svgD3Node, title, desc, givenId);
|
||||
expect(svgAttrSpy).toHaveBeenCalledWith('aria-describedby', `chart-desc-${givenId}`);
|
||||
|
@ -20,7 +20,7 @@
|
||||
* of src to dst in order.
|
||||
* @param {any} dst - The destination of the merge
|
||||
* @param {any} src - The source object(s) to merge into destination
|
||||
* @param {{ depth: number; clobber: boolean }} [config={ depth: 2, clobber: false }] - Depth: depth
|
||||
* @param {{ depth: number; clobber: boolean }} [config] - Depth: depth
|
||||
* to traverse within src and dst for merging - clobber: should dissimilar types clobber (default:
|
||||
* { depth: 2, clobber: false }). Default is `{ depth: 2, clobber: false }`
|
||||
* @returns {any}
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Cluster handling
|
||||
|
||||
Dagre does not support edges between nodes and clusters or between clusters to other clusters. In order to remedy this shortcoming the dagre wrapper implements a few work-arounds.
|
||||
Dagre does not support edges between nodes and clusters or between clusters to other clusters. In order to remedy this shortcoming the dagre wrapper implements a few workarounds.
|
||||
|
||||
In the diagram below there are two clusters and there are no edges to nodes outside the own cluster.
|
||||
|
||||
@ -73,7 +73,7 @@ Sample object:
|
||||
}
|
||||
```
|
||||
|
||||
This is set by the renderer of the diagram and insert the data that the wrapper neds for rendering.
|
||||
This is set by the renderer of the diagram and insert the data that the wrapper needs for rendering.
|
||||
|
||||
| property | description |
|
||||
| ---------- | ------------------------------------------------------------------------------------------------ |
|
||||
@ -114,7 +114,7 @@ Required edgeData for proper rendering:
|
||||
| label | overlap between label and labelText? |
|
||||
| labelPos | |
|
||||
| labelType | overlap between label and labelText? |
|
||||
| thickness | Sets the thinkess of the edge. Can be \['normal', 'thick'\] |
|
||||
| thickness | Sets the thickness of the edge. Can be \['normal', 'thick'\] |
|
||||
| pattern | Sets the pattern of the edge. Can be \['solid', 'dotted', 'dashed'\] |
|
||||
|
||||
# Markers
|
||||
|
@ -602,6 +602,8 @@ const doublecircle = async (parent, node) => {
|
||||
const outerCircle = circleGroup.insert('circle');
|
||||
const innerCircle = circleGroup.insert('circle');
|
||||
|
||||
circleGroup.attr('class', node.class);
|
||||
|
||||
// center the circle around its coordinate
|
||||
outerCircle
|
||||
.attr('style', node.style)
|
||||
|
@ -4,7 +4,7 @@ import flowchartV2 from '../diagrams/flowchart/flowDetector-v2.js';
|
||||
import er from '../diagrams/er/erDetector.js';
|
||||
import git from '../diagrams/git/gitGraphDetector.js';
|
||||
import gantt from '../diagrams/gantt/ganttDetector.js';
|
||||
import info from '../diagrams/info/infoDetector.js';
|
||||
import { info } from '../diagrams/info/infoDetector.js';
|
||||
import pie from '../diagrams/pie/pieDetector.js';
|
||||
import quadrantChart from '../diagrams/quadrant-chart/quadrantDetector.js';
|
||||
import requirement from '../diagrams/requirement/requirementDetector.js';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { DiagramDb } from './types.js';
|
||||
import { DiagramDB } from './types.js';
|
||||
// The "* as yaml" part is necessary for tree-shaking
|
||||
import * as yaml from 'js-yaml';
|
||||
|
||||
@ -22,7 +22,7 @@ type FrontMatterMetadata = {
|
||||
* @param db - Diagram database, could be of any diagram.
|
||||
* @returns text with frontmatter stripped out
|
||||
*/
|
||||
export function extractFrontMatter(text: string, db: DiagramDb): string {
|
||||
export function extractFrontMatter(text: string, db: DiagramDB): string {
|
||||
const matches = text.match(frontMatterRegex);
|
||||
if (matches) {
|
||||
const parsed: FrontMatterMetadata = yaml.load(matches[1], {
|
||||
|
@ -1,4 +1,6 @@
|
||||
import { Diagram } from '../Diagram.js';
|
||||
import { MermaidConfig } from '../config.type.js';
|
||||
import type * as d3 from 'd3';
|
||||
|
||||
export interface InjectUtils {
|
||||
_log: any;
|
||||
@ -13,7 +15,7 @@ export interface InjectUtils {
|
||||
/**
|
||||
* Generic Diagram DB that may apply to any diagram type.
|
||||
*/
|
||||
export interface DiagramDb {
|
||||
export interface DiagramDB {
|
||||
clear?: () => void;
|
||||
setDiagramTitle?: (title: string) => void;
|
||||
setDisplayMode?: (title: string) => void;
|
||||
@ -23,10 +25,10 @@ export interface DiagramDb {
|
||||
}
|
||||
|
||||
export interface DiagramDefinition {
|
||||
db: DiagramDb;
|
||||
db: DiagramDB;
|
||||
renderer: any;
|
||||
parser: any;
|
||||
styles: any;
|
||||
styles?: any;
|
||||
init?: (config: MermaidConfig) => void;
|
||||
injectUtils?: (
|
||||
_log: InjectUtils['_log'],
|
||||
@ -52,3 +54,33 @@ export interface ExternalDiagramDefinition {
|
||||
|
||||
export type DiagramDetector = (text: string, config?: MermaidConfig) => boolean;
|
||||
export type DiagramLoader = () => Promise<{ id: string; diagram: DiagramDefinition }>;
|
||||
|
||||
/**
|
||||
* Type for function draws diagram in the tag with id: id based on the graph definition in text.
|
||||
*
|
||||
* @param text - The text of the diagram.
|
||||
* @param id - The id of the diagram which will be used as a DOM element id.
|
||||
* @param version - MermaidJS version from package.json.
|
||||
* @param diagramObject - A standard diagram containing the DB and the text and type etc of the diagram.
|
||||
*/
|
||||
export type DrawDefinition = (
|
||||
text: string,
|
||||
id: string,
|
||||
version: string,
|
||||
diagramObject: Diagram
|
||||
) => void;
|
||||
|
||||
/**
|
||||
* Type for function parse directive from diagram code.
|
||||
*
|
||||
* @param statement -
|
||||
* @param context -
|
||||
* @param type -
|
||||
*/
|
||||
export type ParseDirectiveDefinition = (statement: string, context: string, type: string) => void;
|
||||
|
||||
export type HTML = d3.Selection<HTMLIFrameElement, unknown, Element, unknown>;
|
||||
|
||||
export type SVG = d3.Selection<SVGSVGElement, unknown, Element, unknown>;
|
||||
|
||||
export type DiagramStylesProvider = (options?: any) => string;
|
||||
|
@ -1,12 +1,16 @@
|
||||
import type { ExternalDiagramDefinition } from '../../diagram-api/types.js';
|
||||
import type {
|
||||
DiagramDetector,
|
||||
DiagramLoader,
|
||||
ExternalDiagramDefinition,
|
||||
} from '../../diagram-api/types.js';
|
||||
|
||||
const id = 'c4';
|
||||
|
||||
const detector = (txt: string) => {
|
||||
return txt.match(/^\s*C4Context|C4Container|C4Component|C4Dynamic|C4Deployment/) !== null;
|
||||
const detector: DiagramDetector = (txt) => {
|
||||
return /^\s*C4Context|C4Container|C4Component|C4Dynamic|C4Deployment/.test(txt);
|
||||
};
|
||||
|
||||
const loader = async () => {
|
||||
const loader: DiagramLoader = async () => {
|
||||
const { diagram } = await import('./c4Diagram.js');
|
||||
return { id, diagram };
|
||||
};
|
||||
|
@ -220,7 +220,7 @@ export const drawC4ShapeArray = function (currentBounds, diagram, c4ShapeArray,
|
||||
let c4ShapeTypeConf = c4ShapeFont(conf, c4Shape.typeC4Shape.text);
|
||||
c4ShapeTypeConf.fontSize = c4ShapeTypeConf.fontSize - 2;
|
||||
c4Shape.typeC4Shape.width = calculateTextWidth(
|
||||
'<<' + c4Shape.typeC4Shape.text + '>>',
|
||||
'«' + c4Shape.typeC4Shape.text + '»',
|
||||
c4ShapeTypeConf
|
||||
);
|
||||
c4Shape.typeC4Shape.height = c4ShapeTypeConf.fontSize + 2;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// @ts-expect-error - d3 types issue
|
||||
// @ts-nocheck - don't check until handle it
|
||||
import { select, Selection } from 'd3';
|
||||
import { log } from '../../logger.js';
|
||||
import * as configApi from '../../config.js';
|
||||
@ -367,7 +367,6 @@ export const relationType = {
|
||||
const setupToolTips = function (element: Element) {
|
||||
let tooltipElem: Selection<HTMLDivElement, unknown, HTMLElement, unknown> =
|
||||
select('.mermaidTooltip');
|
||||
// @ts-ignore - _groups is a dynamic property
|
||||
if ((tooltipElem._groups || tooltipElem)[0][0] === null) {
|
||||
tooltipElem = select('body').append('div').attr('class', 'mermaidTooltip').style('opacity', 0);
|
||||
}
|
||||
@ -449,9 +448,8 @@ const getNamespaces = function (): NamespaceMap {
|
||||
export const addClassesToNamespace = function (id: string, classNames: string[]) {
|
||||
if (namespaces[id] !== undefined) {
|
||||
classNames.map((className) => {
|
||||
classes[className].parent = id;
|
||||
namespaces[id].classes[className] = classes[className];
|
||||
delete classes[className];
|
||||
classCounter--;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -1,20 +1,21 @@
|
||||
import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types.js';
|
||||
import type {
|
||||
DiagramDetector,
|
||||
DiagramLoader,
|
||||
ExternalDiagramDefinition,
|
||||
} from '../../diagram-api/types.js';
|
||||
|
||||
const id = 'classDiagram';
|
||||
|
||||
const detector: DiagramDetector = (txt, config) => {
|
||||
// If we have configured to use dagre-wrapper then we should return true in this function for classDiagram code thus making it use the new class diagram
|
||||
if (
|
||||
txt.match(/^\s*classDiagram/) !== null &&
|
||||
config?.class?.defaultRenderer === 'dagre-wrapper'
|
||||
) {
|
||||
if (/^\s*classDiagram/.test(txt) && config?.class?.defaultRenderer === 'dagre-wrapper') {
|
||||
return true;
|
||||
}
|
||||
// We have not opted to use the new renderer so we should return true if we detect a class diagram
|
||||
return txt.match(/^\s*classDiagram-v2/) !== null;
|
||||
return /^\s*classDiagram-v2/.test(txt);
|
||||
};
|
||||
|
||||
const loader = async () => {
|
||||
const loader: DiagramLoader = async () => {
|
||||
const { diagram } = await import('./classDiagram-v2.js');
|
||||
return { id, diagram };
|
||||
};
|
||||
|
@ -1,4 +1,8 @@
|
||||
import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types.js';
|
||||
import type {
|
||||
DiagramDetector,
|
||||
DiagramLoader,
|
||||
ExternalDiagramDefinition,
|
||||
} from '../../diagram-api/types.js';
|
||||
|
||||
const id = 'class';
|
||||
|
||||
@ -8,10 +12,10 @@ const detector: DiagramDetector = (txt, config) => {
|
||||
return false;
|
||||
}
|
||||
// We have not opted to use the new renderer so we should return true if we detect a class diagram
|
||||
return txt.match(/^\s*classDiagram/) !== null;
|
||||
return /^\s*classDiagram/.test(txt);
|
||||
};
|
||||
|
||||
const loader = async () => {
|
||||
const loader: DiagramLoader = async () => {
|
||||
const { diagram } = await import('./classDiagram.js');
|
||||
return { id, diagram };
|
||||
};
|
||||
|
@ -1373,9 +1373,54 @@ class Class2
|
||||
parser.parse(str);
|
||||
|
||||
const testNamespace = parser.yy.getNamespace('Namespace1');
|
||||
const testClasses = parser.yy.getClasses();
|
||||
expect(Object.keys(testNamespace.classes).length).toBe(2);
|
||||
expect(Object.keys(testNamespace.children).length).toBe(0);
|
||||
expect(testNamespace.classes['Class1'].id).toBe('Class1');
|
||||
expect(Object.keys(testClasses).length).toBe(2);
|
||||
});
|
||||
|
||||
it('should add relations between classes of different namespaces', function () {
|
||||
const str = `classDiagram
|
||||
A1 --> B1
|
||||
namespace A {
|
||||
class A1 {
|
||||
+foo : string
|
||||
}
|
||||
class A2 {
|
||||
+bar : int
|
||||
}
|
||||
}
|
||||
namespace B {
|
||||
class B1 {
|
||||
+foo : bool
|
||||
}
|
||||
class B2 {
|
||||
+bar : float
|
||||
}
|
||||
}
|
||||
A2 --> B2`;
|
||||
|
||||
parser.parse(str);
|
||||
const testNamespaceA = parser.yy.getNamespace('A');
|
||||
const testNamespaceB = parser.yy.getNamespace('B');
|
||||
const testClasses = parser.yy.getClasses();
|
||||
const testRelations = parser.yy.getRelations();
|
||||
expect(Object.keys(testNamespaceA.classes).length).toBe(2);
|
||||
expect(testNamespaceA.classes['A1'].members[0]).toBe('+foo : string');
|
||||
expect(testNamespaceA.classes['A2'].members[0]).toBe('+bar : int');
|
||||
expect(Object.keys(testNamespaceB.classes).length).toBe(2);
|
||||
expect(testNamespaceB.classes['B1'].members[0]).toBe('+foo : bool');
|
||||
expect(testNamespaceB.classes['B2'].members[0]).toBe('+bar : float');
|
||||
expect(Object.keys(testClasses).length).toBe(4);
|
||||
expect(testClasses['A1'].parent).toBe('A');
|
||||
expect(testClasses['A2'].parent).toBe('A');
|
||||
expect(testClasses['B1'].parent).toBe('B');
|
||||
expect(testClasses['B2'].parent).toBe('B');
|
||||
expect(testRelations[0].id1).toBe('A1');
|
||||
expect(testRelations[0].id2).toBe('B1');
|
||||
expect(testRelations[1].id1).toBe('A2');
|
||||
expect(testRelations[1].id2).toBe('B2');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// @ts-ignore d3 types are not available
|
||||
// @ts-nocheck - don't check until handle it
|
||||
import { select, curveLinear } from 'd3';
|
||||
import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
|
||||
import { log } from '../../logger.js';
|
||||
@ -93,52 +93,51 @@ export const addClasses = function (
|
||||
log.info(classes);
|
||||
|
||||
// Iterate through each item in the vertex object (containing all the vertices found) in the graph definition
|
||||
keys.forEach(function (id) {
|
||||
const vertex = classes[id];
|
||||
keys
|
||||
.filter((id) => classes[id].parent == parent)
|
||||
.forEach(function (id) {
|
||||
const vertex = classes[id];
|
||||
|
||||
/**
|
||||
* Variable for storing the classes for the vertex
|
||||
*/
|
||||
let cssClassStr = '';
|
||||
if (vertex.cssClasses.length > 0) {
|
||||
cssClassStr = cssClassStr + ' ' + vertex.cssClasses.join(' ');
|
||||
}
|
||||
/**
|
||||
* Variable for storing the classes for the vertex
|
||||
*/
|
||||
const cssClassStr = vertex.cssClasses.join(' ');
|
||||
|
||||
const styles = { labelStyle: '', style: '' }; //getStylesFromArray(vertex.styles);
|
||||
const styles = { labelStyle: '', style: '' }; //getStylesFromArray(vertex.styles);
|
||||
|
||||
// Use vertex id as text in the box if no text is provided by the graph definition
|
||||
const vertexText = vertex.label ?? vertex.id;
|
||||
const radius = 0;
|
||||
const shape = 'class_box';
|
||||
// Use vertex id as text in the box if no text is provided by the graph definition
|
||||
const vertexText = vertex.label ?? vertex.id;
|
||||
const radius = 0;
|
||||
const shape = 'class_box';
|
||||
|
||||
// Add the node
|
||||
const node = {
|
||||
labelStyle: styles.labelStyle,
|
||||
shape: shape,
|
||||
labelText: sanitizeText(vertexText),
|
||||
classData: vertex,
|
||||
rx: radius,
|
||||
ry: radius,
|
||||
class: cssClassStr,
|
||||
style: styles.style,
|
||||
id: vertex.id,
|
||||
domId: vertex.domId,
|
||||
tooltip: diagObj.db.getTooltip(vertex.id, parent) || '',
|
||||
haveCallback: vertex.haveCallback,
|
||||
link: vertex.link,
|
||||
width: vertex.type === 'group' ? 500 : undefined,
|
||||
type: vertex.type,
|
||||
// TODO V10: Flowchart ? Keeping flowchart for backwards compatibility. Remove in next major release
|
||||
padding: getConfig().flowchart?.padding ?? getConfig().class?.padding,
|
||||
};
|
||||
g.setNode(vertex.id, node);
|
||||
// Add the node
|
||||
const node = {
|
||||
labelStyle: styles.labelStyle,
|
||||
shape: shape,
|
||||
labelText: sanitizeText(vertexText),
|
||||
classData: vertex,
|
||||
rx: radius,
|
||||
ry: radius,
|
||||
class: cssClassStr,
|
||||
style: styles.style,
|
||||
id: vertex.id,
|
||||
domId: vertex.domId,
|
||||
tooltip: diagObj.db.getTooltip(vertex.id, parent) || '',
|
||||
haveCallback: vertex.haveCallback,
|
||||
link: vertex.link,
|
||||
width: vertex.type === 'group' ? 500 : undefined,
|
||||
type: vertex.type,
|
||||
// TODO V10: Flowchart ? Keeping flowchart for backwards compatibility. Remove in next major release
|
||||
padding: getConfig().flowchart?.padding ?? getConfig().class?.padding,
|
||||
};
|
||||
g.setNode(vertex.id, node);
|
||||
|
||||
if (parent) {
|
||||
g.setParent(vertex.id, parent);
|
||||
}
|
||||
if (parent) {
|
||||
g.setParent(vertex.id, parent);
|
||||
}
|
||||
|
||||
log.info('setNode', node);
|
||||
});
|
||||
log.info('setNode', node);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -353,15 +352,11 @@ export const draw = async function (text: string, id: string, _version: string,
|
||||
}
|
||||
const root =
|
||||
securityLevel === 'sandbox'
|
||||
? // @ts-ignore Ignore type error for now
|
||||
|
||||
select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
: select('body');
|
||||
// @ts-ignore Ignore type error for now
|
||||
const svg = root.select(`[id="${id}"]`);
|
||||
|
||||
// Run the renderer. This is what draws the final graph.
|
||||
// @ts-ignore Ignore type error for now
|
||||
const element = root.select('#' + id + ' g');
|
||||
await render(
|
||||
element,
|
||||
@ -377,7 +372,6 @@ export const draw = async function (text: string, id: string, _version: string,
|
||||
|
||||
// Add label rects for non html labels
|
||||
if (!conf?.htmlLabels) {
|
||||
// @ts-ignore Ignore type error for now
|
||||
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
||||
const labels = doc.querySelectorAll('[id="' + id + '"] .edgeLabel .label');
|
||||
for (const label of labels) {
|
||||
|
@ -7,6 +7,7 @@ export interface ClassNode {
|
||||
members: string[];
|
||||
annotations: string[];
|
||||
domId: string;
|
||||
parent?: string;
|
||||
link?: string;
|
||||
linkTarget?: string;
|
||||
haveCallback?: boolean;
|
||||
|
@ -1,12 +1,16 @@
|
||||
import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types.js';
|
||||
import type {
|
||||
DiagramDetector,
|
||||
DiagramLoader,
|
||||
ExternalDiagramDefinition,
|
||||
} from '../../diagram-api/types.js';
|
||||
|
||||
const id = 'er';
|
||||
|
||||
const detector: DiagramDetector = (txt) => {
|
||||
return txt.match(/^\s*erDiagram/) !== null;
|
||||
return /^\s*erDiagram/.test(txt);
|
||||
};
|
||||
|
||||
const loader = async () => {
|
||||
const loader: DiagramLoader = async () => {
|
||||
const { diagram } = await import('./erDiagram.js');
|
||||
return { id, diagram };
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
// @ts-ignore: TODO Fix ts errors
|
||||
// @ts-ignore: TODO: Fix ts errors
|
||||
import erParser from './parser/erDiagram.jison';
|
||||
import erDb from './erDb.js';
|
||||
import erRenderer from './erRenderer.js';
|
||||
|
@ -1,21 +1,24 @@
|
||||
import type { MermaidConfig } from '../../../config.type.js';
|
||||
import type { ExternalDiagramDefinition, DiagramDetector } from '../../../diagram-api/types.js';
|
||||
import type {
|
||||
ExternalDiagramDefinition,
|
||||
DiagramDetector,
|
||||
DiagramLoader,
|
||||
} from '../../../diagram-api/types.js';
|
||||
|
||||
const id = 'flowchart-elk';
|
||||
|
||||
const detector: DiagramDetector = (txt: string, config?: MermaidConfig): boolean => {
|
||||
const detector: DiagramDetector = (txt, config): boolean => {
|
||||
if (
|
||||
// If diagram explicitly states flowchart-elk
|
||||
txt.match(/^\s*flowchart-elk/) ||
|
||||
/^\s*flowchart-elk/.test(txt) ||
|
||||
// If a flowchart/graph diagram has their default renderer set to elk
|
||||
(txt.match(/^\s*flowchart|graph/) && config?.flowchart?.defaultRenderer === 'elk')
|
||||
(/^\s*flowchart|graph/.test(txt) && config?.flowchart?.defaultRenderer === 'elk')
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const loader = async () => {
|
||||
const loader: DiagramLoader = async () => {
|
||||
const { diagram } = await import('./flowchart-elk-definition.js');
|
||||
return { id, diagram };
|
||||
};
|
||||
|
@ -208,21 +208,22 @@ export const updateLink = function (positions, style) {
|
||||
});
|
||||
};
|
||||
|
||||
export const addClass = function (id, style) {
|
||||
if (classes[id] === undefined) {
|
||||
classes[id] = { id: id, styles: [], textStyles: [] };
|
||||
}
|
||||
export const addClass = function (ids, style) {
|
||||
ids.split(',').forEach(function (id) {
|
||||
if (classes[id] === undefined) {
|
||||
classes[id] = { id, styles: [], textStyles: [] };
|
||||
}
|
||||
|
||||
if (style !== undefined && style !== null) {
|
||||
style.forEach(function (s) {
|
||||
if (s.match('color')) {
|
||||
const newStyle1 = s.replace('fill', 'bgFill');
|
||||
const newStyle2 = newStyle1.replace('color', 'fill');
|
||||
classes[id].textStyles.push(newStyle2);
|
||||
}
|
||||
classes[id].styles.push(s);
|
||||
});
|
||||
}
|
||||
if (style !== undefined && style !== null) {
|
||||
style.forEach(function (s) {
|
||||
if (s.match('color')) {
|
||||
const newStyle = s.replace('fill', 'bgFill').replace('color', 'fill');
|
||||
classes[id].textStyles.push(newStyle);
|
||||
}
|
||||
classes[id].styles.push(s);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -41,3 +41,26 @@ describe('flow db subgraphs', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('flow db addClass', () => {
|
||||
beforeEach(() => {
|
||||
flowDb.clear();
|
||||
});
|
||||
it('should detect many classes', () => {
|
||||
flowDb.addClass('a,b', ['stroke-width: 8px']);
|
||||
const classes = flowDb.getClasses();
|
||||
|
||||
expect(classes.hasOwnProperty('a')).toBe(true);
|
||||
expect(classes.hasOwnProperty('b')).toBe(true);
|
||||
expect(classes['a']['styles']).toEqual(['stroke-width: 8px']);
|
||||
expect(classes['b']['styles']).toEqual(['stroke-width: 8px']);
|
||||
});
|
||||
|
||||
it('should detect single class', () => {
|
||||
flowDb.addClass('a', ['stroke-width: 8px']);
|
||||
const classes = flowDb.getClasses();
|
||||
|
||||
expect(classes.hasOwnProperty('a')).toBe(true);
|
||||
expect(classes['a']['styles']).toEqual(['stroke-width: 8px']);
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { DiagramDetector } from '../../diagram-api/types.js';
|
||||
import type { DiagramDetector, DiagramLoader } from '../../diagram-api/types.js';
|
||||
import type { ExternalDiagramDefinition } from '../../diagram-api/types.js';
|
||||
|
||||
const id = 'flowchart-v2';
|
||||
@ -12,13 +12,13 @@ const detector: 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
|
||||
if (txt.match(/^\s*graph/) !== null && config?.flowchart?.defaultRenderer === 'dagre-wrapper') {
|
||||
if (/^\s*graph/.test(txt) && config?.flowchart?.defaultRenderer === 'dagre-wrapper') {
|
||||
return true;
|
||||
}
|
||||
return txt.match(/^\s*flowchart/) !== null;
|
||||
return /^\s*flowchart/.test(txt);
|
||||
};
|
||||
|
||||
const loader = async () => {
|
||||
const loader: DiagramLoader = async () => {
|
||||
const { diagram } = await import('./flowDiagram-v2.js');
|
||||
return { id, diagram };
|
||||
};
|
||||
|
@ -1,4 +1,8 @@
|
||||
import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types.js';
|
||||
import type {
|
||||
DiagramDetector,
|
||||
DiagramLoader,
|
||||
ExternalDiagramDefinition,
|
||||
} from '../../diagram-api/types.js';
|
||||
|
||||
const id = 'flowchart';
|
||||
|
||||
@ -11,10 +15,10 @@ const detector: DiagramDetector = (txt, config) => {
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return txt.match(/^\s*graph/) !== null;
|
||||
return /^\s*graph/.test(txt);
|
||||
};
|
||||
|
||||
const loader = async () => {
|
||||
const loader: DiagramLoader = async () => {
|
||||
const { diagram } = await import('./flowDiagram.js');
|
||||
return { id, diagram };
|
||||
};
|
||||
|
@ -113,6 +113,22 @@ describe('[Style] when parsing', () => {
|
||||
expect(classes['exClass'].styles[1]).toBe('border:1px solid red');
|
||||
});
|
||||
|
||||
it('should be possible to declare multiple classes', function () {
|
||||
const res = flow.parser.parse(
|
||||
'graph TD;classDef firstClass,secondClass background:#bbb,border:1px solid red;'
|
||||
);
|
||||
|
||||
const classes = flow.parser.yy.getClasses();
|
||||
|
||||
expect(classes['firstClass'].styles.length).toBe(2);
|
||||
expect(classes['firstClass'].styles[0]).toBe('background:#bbb');
|
||||
expect(classes['firstClass'].styles[1]).toBe('border:1px solid red');
|
||||
|
||||
expect(classes['secondClass'].styles.length).toBe(2);
|
||||
expect(classes['secondClass'].styles[0]).toBe('background:#bbb');
|
||||
expect(classes['secondClass'].styles[1]).toBe('border:1px solid red');
|
||||
});
|
||||
|
||||
it('should be possible to declare a class with a dot in the style', function () {
|
||||
const res = flow.parser.parse(
|
||||
'graph TD;classDef exClass background:#bbb,border:1.5px solid red;'
|
||||
@ -322,4 +338,20 @@ describe('[Style] when parsing', () => {
|
||||
|
||||
expect(edges[0].type).toBe('arrow_point');
|
||||
});
|
||||
|
||||
it('should handle multiple vertices with style', function () {
|
||||
const res = flow.parser.parse(`
|
||||
graph TD
|
||||
classDef C1 stroke-dasharray:4
|
||||
classDef C2 stroke-dasharray:6
|
||||
A & B:::C1 & D:::C1 --> E:::C2
|
||||
`);
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
|
||||
expect(vert['A'].classes.length).toBe(0);
|
||||
expect(vert['B'].classes[0]).toBe('C1');
|
||||
expect(vert['D'].classes[0]).toBe('C1');
|
||||
expect(vert['E'].classes[0]).toBe('C2');
|
||||
});
|
||||
});
|
||||
|
@ -359,7 +359,7 @@ statement
|
||||
|
||||
separator: NEWLINE | SEMI | EOF ;
|
||||
|
||||
|
||||
|
||||
verticeStatement: verticeStatement link node
|
||||
{ /* console.warn('vs',$1.stmt,$3); */ yy.addLink($1.stmt,$3,$2); $$ = { stmt: $3, nodes: $3.concat($1.nodes) } }
|
||||
| verticeStatement link node spaceList
|
||||
@ -368,12 +368,16 @@ verticeStatement: verticeStatement link node
|
||||
|node { /*console.warn('noda', $1);*/ $$ = {stmt: $1, nodes:$1 }}
|
||||
;
|
||||
|
||||
node: vertex
|
||||
node: styledVertex
|
||||
{ /* console.warn('nod', $1); */ $$ = [$1];}
|
||||
| node spaceList AMP spaceList vertex
|
||||
| node spaceList AMP spaceList styledVertex
|
||||
{ $$ = $1.concat($5); /* console.warn('pip', $1[0], $5, $$); */ }
|
||||
;
|
||||
|
||||
styledVertex: vertex
|
||||
{ /* console.warn('nod', $1); */ $$ = $1;}
|
||||
| vertex STYLE_SEPARATOR idString
|
||||
{$$ = [$1];yy.setClass($1,$3)}
|
||||
{$$ = $1;yy.setClass($1,$3)}
|
||||
;
|
||||
|
||||
vertex: idString SQS text SQE
|
||||
|
@ -1,12 +1,16 @@
|
||||
import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types.js';
|
||||
import type {
|
||||
DiagramDetector,
|
||||
DiagramLoader,
|
||||
ExternalDiagramDefinition,
|
||||
} from '../../diagram-api/types.js';
|
||||
|
||||
const id = 'gantt';
|
||||
|
||||
const detector: DiagramDetector = (txt) => {
|
||||
return txt.match(/^\s*gantt/) !== null;
|
||||
return /^\s*gantt/.test(txt);
|
||||
};
|
||||
|
||||
const loader = async () => {
|
||||
const loader: DiagramLoader = async () => {
|
||||
const { diagram } = await import('./ganttDiagram.js');
|
||||
return { id, diagram };
|
||||
};
|
||||
|
@ -1,13 +1,13 @@
|
||||
import type { DiagramDetector } from '../../diagram-api/types.js';
|
||||
import type { DiagramDetector, DiagramLoader } from '../../diagram-api/types.js';
|
||||
import type { ExternalDiagramDefinition } from '../../diagram-api/types.js';
|
||||
|
||||
const id = 'gitGraph';
|
||||
|
||||
const detector: DiagramDetector = (txt) => {
|
||||
return txt.match(/^\s*gitGraph/) !== null;
|
||||
return /^\s*gitGraph/.test(txt);
|
||||
};
|
||||
|
||||
const loader = async () => {
|
||||
const loader: DiagramLoader = async () => {
|
||||
const { diagram } = await import('./gitGraphDiagram.js');
|
||||
return { id, diagram };
|
||||
};
|
||||
|
@ -1,16 +0,0 @@
|
||||
import { parser } from './parser/info.jison';
|
||||
import infoDb from './infoDb.js';
|
||||
describe('when parsing an info graph it', function () {
|
||||
let ex;
|
||||
beforeEach(function () {
|
||||
ex = parser;
|
||||
ex.yy = infoDb;
|
||||
});
|
||||
|
||||
it('should handle an info definition', function () {
|
||||
let str = `info
|
||||
showInfo`;
|
||||
|
||||
ex.parse(str);
|
||||
});
|
||||
});
|
24
packages/mermaid/src/diagrams/info/info.spec.ts
Normal file
24
packages/mermaid/src/diagrams/info/info.spec.ts
Normal file
@ -0,0 +1,24 @@
|
||||
// @ts-ignore - jison doesn't export types
|
||||
import { parser } from './parser/info.jison';
|
||||
import { db } from './infoDb.js';
|
||||
|
||||
describe('info diagram', () => {
|
||||
beforeEach(() => {
|
||||
parser.yy = db;
|
||||
parser.yy.clear();
|
||||
});
|
||||
|
||||
it('should handle an info definition', () => {
|
||||
const str = `info`;
|
||||
parser.parse(str);
|
||||
|
||||
expect(db.getInfo()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should handle an info definition with showInfo', () => {
|
||||
const str = `info showInfo`;
|
||||
parser.parse(str);
|
||||
|
||||
expect(db.getInfo()).toBeTruthy();
|
||||
});
|
||||
});
|
@ -1,36 +0,0 @@
|
||||
/** Created by knut on 15-01-14. */
|
||||
import { log } from '../../logger.js';
|
||||
import { clear } from '../../commonDb.js';
|
||||
|
||||
var message = '';
|
||||
var info = false;
|
||||
|
||||
export const setMessage = (txt) => {
|
||||
log.debug('Setting message to: ' + txt);
|
||||
message = txt;
|
||||
};
|
||||
|
||||
export const getMessage = () => {
|
||||
return message;
|
||||
};
|
||||
|
||||
export const setInfo = (inf) => {
|
||||
info = inf;
|
||||
};
|
||||
|
||||
export const getInfo = () => {
|
||||
return info;
|
||||
};
|
||||
|
||||
// export const parseError = (err, hash) => {
|
||||
// global.mermaidAPI.parseError(err, hash)
|
||||
// }
|
||||
|
||||
export default {
|
||||
setMessage,
|
||||
getMessage,
|
||||
setInfo,
|
||||
getInfo,
|
||||
clear,
|
||||
// parseError
|
||||
};
|
23
packages/mermaid/src/diagrams/info/infoDb.ts
Normal file
23
packages/mermaid/src/diagrams/info/infoDb.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import type { InfoFields, InfoDB } from './infoTypes.js';
|
||||
|
||||
export const DEFAULT_INFO_DB: InfoFields = {
|
||||
info: false,
|
||||
} as const;
|
||||
|
||||
let info: boolean = DEFAULT_INFO_DB.info;
|
||||
|
||||
export const setInfo = (toggle: boolean): void => {
|
||||
info = toggle;
|
||||
};
|
||||
|
||||
export const getInfo = (): boolean => info;
|
||||
|
||||
const clear = (): void => {
|
||||
info = DEFAULT_INFO_DB.info;
|
||||
};
|
||||
|
||||
export const db: InfoDB = {
|
||||
clear,
|
||||
setInfo,
|
||||
getInfo,
|
||||
};
|
@ -1,20 +1,22 @@
|
||||
import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types.js';
|
||||
import type {
|
||||
DiagramDetector,
|
||||
DiagramLoader,
|
||||
ExternalDiagramDefinition,
|
||||
} from '../../diagram-api/types.js';
|
||||
|
||||
const id = 'info';
|
||||
|
||||
const detector: DiagramDetector = (txt) => {
|
||||
return txt.match(/^\s*info/) !== null;
|
||||
return /^\s*info/.test(txt);
|
||||
};
|
||||
|
||||
const loader = async () => {
|
||||
const loader: DiagramLoader = async () => {
|
||||
const { diagram } = await import('./infoDiagram.js');
|
||||
return { id, diagram };
|
||||
};
|
||||
|
||||
const plugin: ExternalDiagramDefinition = {
|
||||
export const info: ExternalDiagramDefinition = {
|
||||
id,
|
||||
detector,
|
||||
loader,
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
|
@ -1,13 +1,11 @@
|
||||
import { DiagramDefinition } from '../../diagram-api/types.js';
|
||||
// @ts-ignore: TODO Fix ts errors
|
||||
import type { DiagramDefinition } from '../../diagram-api/types.js';
|
||||
// @ts-ignore - jison doesn't export types
|
||||
import parser from './parser/info.jison';
|
||||
import db from './infoDb.js';
|
||||
import styles from './styles.js';
|
||||
import renderer from './infoRenderer.js';
|
||||
import { db } from './infoDb.js';
|
||||
import { renderer } from './infoRenderer.js';
|
||||
|
||||
export const diagram: DiagramDefinition = {
|
||||
parser,
|
||||
db,
|
||||
renderer,
|
||||
styles,
|
||||
};
|
||||
|
@ -1,57 +0,0 @@
|
||||
/** Created by knut on 14-12-11. */
|
||||
import { select } from 'd3';
|
||||
import { log } from '../../logger.js';
|
||||
import { getConfig } from '../../config.js';
|
||||
|
||||
/**
|
||||
* Draws a an info picture in the tag with id: id based on the graph definition in text.
|
||||
*
|
||||
* @param {any} text
|
||||
* @param {any} id
|
||||
* @param {any} version
|
||||
*/
|
||||
export const draw = (text, id, version) => {
|
||||
try {
|
||||
// const parser = infoParser.parser;
|
||||
// parser.yy = db;
|
||||
log.debug('Rendering info diagram\n' + text);
|
||||
|
||||
const securityLevel = getConfig().securityLevel;
|
||||
// Handle root and Document for when rendering in sandbox mode
|
||||
let sandboxElement;
|
||||
if (securityLevel === 'sandbox') {
|
||||
sandboxElement = select('#i' + id);
|
||||
}
|
||||
const root =
|
||||
securityLevel === 'sandbox'
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
: select('body');
|
||||
|
||||
// Parse the graph definition
|
||||
// parser.parse(text);
|
||||
// log.debug('Parsed info diagram');
|
||||
// Fetch the default direction, use TD if none was found
|
||||
const svg = root.select('#' + id);
|
||||
|
||||
const g = svg.append('g');
|
||||
|
||||
g.append('text') // text label for the x axis
|
||||
.attr('x', 100)
|
||||
.attr('y', 40)
|
||||
.attr('class', 'version')
|
||||
.attr('font-size', '32px')
|
||||
.style('text-anchor', 'middle')
|
||||
.text('v ' + version);
|
||||
|
||||
svg.attr('height', 100);
|
||||
svg.attr('width', 400);
|
||||
// svg.attr('viewBox', '0 0 300 150');
|
||||
} catch (e) {
|
||||
log.error('Error while rendering info diagram');
|
||||
log.error(e.message);
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
draw,
|
||||
};
|
50
packages/mermaid/src/diagrams/info/infoRenderer.ts
Normal file
50
packages/mermaid/src/diagrams/info/infoRenderer.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import { select } from 'd3';
|
||||
import { log } from '../../logger.js';
|
||||
import { getConfig } from '../../config.js';
|
||||
import type { DrawDefinition, HTML, SVG } from '../../diagram-api/types.js';
|
||||
|
||||
/**
|
||||
* Draws a an info picture in the tag with id: id based on the graph definition in text.
|
||||
*
|
||||
* @param text - The text of the diagram.
|
||||
* @param id - The id of the diagram which will be used as a DOM element id.
|
||||
* @param version - MermaidJS version.
|
||||
*/
|
||||
const draw: DrawDefinition = (text, id, version) => {
|
||||
try {
|
||||
log.debug('rendering info diagram\n' + text);
|
||||
|
||||
const { securityLevel } = getConfig();
|
||||
// handle root and document for when rendering in sandbox mode
|
||||
let sandboxElement: HTML | undefined;
|
||||
let document: Document | null | undefined;
|
||||
if (securityLevel === 'sandbox') {
|
||||
sandboxElement = select('#i' + id);
|
||||
document = sandboxElement.nodes()[0].contentDocument;
|
||||
}
|
||||
|
||||
// @ts-ignore - figure out how to assign HTML to document type
|
||||
const root: HTML =
|
||||
sandboxElement !== undefined && document !== undefined && document !== null
|
||||
? select(document)
|
||||
: select('body');
|
||||
|
||||
const svg: SVG = root.select('#' + id);
|
||||
svg.attr('height', 100);
|
||||
svg.attr('width', 400);
|
||||
|
||||
const g = svg.append('g');
|
||||
|
||||
g.append('text') // text label for the x axis
|
||||
.attr('x', 100)
|
||||
.attr('y', 40)
|
||||
.attr('class', 'version')
|
||||
.attr('font-size', '32px')
|
||||
.style('text-anchor', 'middle')
|
||||
.text('v ' + version);
|
||||
} catch (e) {
|
||||
log.error('error while rendering info diagram', e);
|
||||
}
|
||||
};
|
||||
|
||||
export const renderer = { draw };
|
11
packages/mermaid/src/diagrams/info/infoTypes.ts
Normal file
11
packages/mermaid/src/diagrams/info/infoTypes.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import type { DiagramDB } from '../../diagram-api/types.js';
|
||||
|
||||
export interface InfoFields {
|
||||
info: boolean;
|
||||
}
|
||||
|
||||
export interface InfoDB extends DiagramDB {
|
||||
clear: () => void;
|
||||
setInfo: (info: boolean) => void;
|
||||
getInfo: () => boolean;
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
const getStyles = () => ``;
|
||||
|
||||
export default getStyles;
|
@ -1,11 +1,15 @@
|
||||
import type { ExternalDiagramDefinition } from '../../diagram-api/types.js';
|
||||
import type {
|
||||
DiagramDetector,
|
||||
DiagramLoader,
|
||||
ExternalDiagramDefinition,
|
||||
} from '../../diagram-api/types.js';
|
||||
const id = 'mindmap';
|
||||
|
||||
const detector = (txt: string) => {
|
||||
return txt.match(/^\s*mindmap/) !== null;
|
||||
const detector: DiagramDetector = (txt) => {
|
||||
return /^\s*mindmap/.test(txt);
|
||||
};
|
||||
|
||||
const loader = async () => {
|
||||
const loader: DiagramLoader = async () => {
|
||||
const { diagram } = await import('./mindmap-definition.js');
|
||||
return { id, diagram };
|
||||
};
|
||||
|
@ -1,12 +1,16 @@
|
||||
import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types.js';
|
||||
import type {
|
||||
DiagramDetector,
|
||||
DiagramLoader,
|
||||
ExternalDiagramDefinition,
|
||||
} from '../../diagram-api/types.js';
|
||||
|
||||
const id = 'pie';
|
||||
|
||||
const detector: DiagramDetector = (txt) => {
|
||||
return txt.match(/^\s*pie/) !== null;
|
||||
return /^\s*pie/.test(txt);
|
||||
};
|
||||
|
||||
const loader = async () => {
|
||||
const loader: DiagramLoader = async () => {
|
||||
const { diagram } = await import('./pieDiagram.js');
|
||||
return { id, diagram };
|
||||
};
|
||||
|
@ -1,12 +1,16 @@
|
||||
import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types.js';
|
||||
import type {
|
||||
DiagramDetector,
|
||||
DiagramLoader,
|
||||
ExternalDiagramDefinition,
|
||||
} from '../../diagram-api/types.js';
|
||||
|
||||
const id = 'quadrantChart';
|
||||
|
||||
const detector: DiagramDetector = (txt) => {
|
||||
return txt.match(/^\s*quadrantChart/) !== null;
|
||||
return /^\s*quadrantChart/.test(txt);
|
||||
};
|
||||
|
||||
const loader = async () => {
|
||||
const loader: DiagramLoader = async () => {
|
||||
const { diagram } = await import('./quadrantDiagram.js');
|
||||
return { id, diagram };
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
// @ts-ignore: TODO Fix ts errors
|
||||
// @ts-nocheck - don't check until handle it
|
||||
import { select } from 'd3';
|
||||
import * as configApi from '../../config.js';
|
||||
import { log } from '../../logger.js';
|
||||
|
@ -1,12 +1,16 @@
|
||||
import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types.js';
|
||||
import type {
|
||||
DiagramDetector,
|
||||
DiagramLoader,
|
||||
ExternalDiagramDefinition,
|
||||
} from '../../diagram-api/types.js';
|
||||
|
||||
const id = 'requirement';
|
||||
|
||||
const detector: DiagramDetector = (txt) => {
|
||||
return txt.match(/^\s*requirement(Diagram)?/) !== null;
|
||||
return /^\s*requirement(Diagram)?/.test(txt);
|
||||
};
|
||||
|
||||
const loader = async () => {
|
||||
const loader: DiagramLoader = async () => {
|
||||
const { diagram } = await import('./requirementDiagram.js');
|
||||
return { id, diagram };
|
||||
};
|
||||
|
@ -1,12 +1,16 @@
|
||||
import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types.js';
|
||||
import type {
|
||||
DiagramDetector,
|
||||
DiagramLoader,
|
||||
ExternalDiagramDefinition,
|
||||
} from '../../diagram-api/types.js';
|
||||
|
||||
const id = 'sequence';
|
||||
|
||||
const detector: DiagramDetector = (txt) => {
|
||||
return txt.match(/^\s*sequenceDiagram/) !== null;
|
||||
return /^\s*sequenceDiagram/.test(txt);
|
||||
};
|
||||
|
||||
const loader = async () => {
|
||||
const loader: DiagramLoader = async () => {
|
||||
const { diagram } = await import('./sequenceDiagram.js');
|
||||
return { id, diagram };
|
||||
};
|
||||
|
@ -1,21 +1,22 @@
|
||||
import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types.js';
|
||||
import type {
|
||||
DiagramDetector,
|
||||
DiagramLoader,
|
||||
ExternalDiagramDefinition,
|
||||
} from '../../diagram-api/types.js';
|
||||
|
||||
const id = 'stateDiagram';
|
||||
|
||||
const detector: DiagramDetector = (text, config) => {
|
||||
if (text.match(/^\s*stateDiagram-v2/) !== null) {
|
||||
const detector: DiagramDetector = (txt, config) => {
|
||||
if (/^\s*stateDiagram-v2/.test(txt)) {
|
||||
return true;
|
||||
}
|
||||
if (text.match(/^\s*stateDiagram/) && config?.state?.defaultRenderer === 'dagre-wrapper') {
|
||||
return true;
|
||||
}
|
||||
if (text.match(/^\s*stateDiagram/) && config?.state?.defaultRenderer === 'dagre-wrapper') {
|
||||
if (/^\s*stateDiagram/.test(txt) && config?.state?.defaultRenderer === 'dagre-wrapper') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const loader = async () => {
|
||||
const loader: DiagramLoader = async () => {
|
||||
const { diagram } = await import('./stateDiagram-v2.js');
|
||||
return { id, diagram };
|
||||
};
|
||||
|
@ -1,4 +1,8 @@
|
||||
import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types.js';
|
||||
import type {
|
||||
DiagramDetector,
|
||||
DiagramLoader,
|
||||
ExternalDiagramDefinition,
|
||||
} from '../../diagram-api/types.js';
|
||||
|
||||
const id = 'state';
|
||||
|
||||
@ -8,10 +12,10 @@ const detector: DiagramDetector = (txt, config) => {
|
||||
if (config?.state?.defaultRenderer === 'dagre-wrapper') {
|
||||
return false;
|
||||
}
|
||||
return txt.match(/^\s*stateDiagram/) !== null;
|
||||
return /^\s*stateDiagram/.test(txt);
|
||||
};
|
||||
|
||||
const loader = async () => {
|
||||
const loader: DiagramLoader = async () => {
|
||||
const { diagram } = await import('./stateDiagram.js');
|
||||
return { id, diagram };
|
||||
};
|
||||
|
@ -358,7 +358,7 @@ const setupDoc = (g, parentParsedItem, doc, diagramStates, diagramDb, altFlag) =
|
||||
* Look through all of the documents (docs) in the parsedItems
|
||||
* Because is a _document_ direction, the default direction is not necessarily the same as the overall default _diagram_ direction.
|
||||
* @param {object[]} parsedItem - the parsed statement item to look through
|
||||
* @param [defaultDir=DEFAULT_NESTED_DOC_DIR] - the direction to use if none is found
|
||||
* @param [defaultDir] - the direction to use if none is found
|
||||
* @returns {string}
|
||||
*/
|
||||
const getDir = (parsedItem, defaultDir = DEFAULT_NESTED_DOC_DIR) => {
|
||||
|
@ -1,12 +1,16 @@
|
||||
import type { ExternalDiagramDefinition } from '../../diagram-api/types.js';
|
||||
import type {
|
||||
DiagramDetector,
|
||||
DiagramLoader,
|
||||
ExternalDiagramDefinition,
|
||||
} from '../../diagram-api/types.js';
|
||||
|
||||
const id = 'timeline';
|
||||
|
||||
const detector = (txt: string) => {
|
||||
return txt.match(/^\s*timeline/) !== null;
|
||||
const detector: DiagramDetector = (txt) => {
|
||||
return /^\s*timeline/.test(txt);
|
||||
};
|
||||
|
||||
const loader = async () => {
|
||||
const loader: DiagramLoader = async () => {
|
||||
const { diagram } = await import('./timeline-definition.js');
|
||||
return { id, diagram };
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
// @ts-ignore - db not typed yet
|
||||
// @ts-nocheck - don't check until handle it
|
||||
import { select, Selection } from 'd3';
|
||||
import svgDraw from './svgDraw.js';
|
||||
import { log } from '../../logger.js';
|
||||
@ -46,11 +46,9 @@ export const draw = function (text: string, id: string, version: string, diagObj
|
||||
}
|
||||
const root =
|
||||
securityLevel === 'sandbox'
|
||||
? // @ts-ignore d3 types are wrong
|
||||
select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
: select('body');
|
||||
|
||||
// @ts-ignore d3 types are wrong
|
||||
const svg = root.select('#' + id);
|
||||
|
||||
svg.append('g');
|
||||
|
@ -1,12 +1,16 @@
|
||||
import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types.js';
|
||||
import type {
|
||||
DiagramDetector,
|
||||
DiagramLoader,
|
||||
ExternalDiagramDefinition,
|
||||
} from '../../diagram-api/types.js';
|
||||
|
||||
const id = 'journey';
|
||||
|
||||
const detector: DiagramDetector = (txt) => {
|
||||
return txt.match(/^\s*journey/) !== null;
|
||||
return /^\s*journey/.test(txt);
|
||||
};
|
||||
|
||||
const loader = async () => {
|
||||
const loader: DiagramLoader = async () => {
|
||||
const { diagram } = await import('./journeyDiagram.js');
|
||||
return { id, diagram };
|
||||
};
|
||||
|
@ -20,6 +20,10 @@ The definitions that can be generated the Live-Editor are also backwards-compati
|
||||
|
||||
[Eddie Jaoude: Can you code your diagrams?](https://www.youtube.com/watch?v=9HZzKkAqrX8)
|
||||
|
||||
## Mermaid with OpenAI
|
||||
|
||||
[Elle Neal: Mind Mapping with AI: An Accessible Approach for Neurodiverse Learners Tutorial:](https://medium.com/@elle.neal_71064/mind-mapping-with-ai-an-accessible-approach-for-neurodiverse-learners-1a74767359ff), [Demo:](https://databutton.com/v/jk9vrghc)
|
||||
|
||||
## Mermaid with HTML
|
||||
|
||||
Examples are provided in [Getting Started](../intro/n00b-gettingStarted.md)
|
||||
|
@ -60,7 +60,7 @@ They also serve as proof of concept, for the variety of things that can be built
|
||||
|
||||
## Blogs
|
||||
|
||||
- [Wordpress](https://wordpress.org)
|
||||
- [WordPress](https://wordpress.org)
|
||||
- [WordPress Markdown Editor](https://wordpress.org/plugins/wp-githuber-md)
|
||||
- [WP-ReliableMD](https://wordpress.org/plugins/wp-reliablemd/)
|
||||
- [Hexo](https://hexo.io)
|
||||
@ -78,7 +78,7 @@ They also serve as proof of concept, for the variety of things that can be built
|
||||
- [Plugin for Mermaid.js](https://github.com/eFrane/vuepress-plugin-mermaidjs)
|
||||
- [Grav CMS](https://getgrav.org/)
|
||||
- [Mermaid Diagrams](https://github.com/DanielFlaum/grav-plugin-mermaid-diagrams)
|
||||
- [Gitlab Markdown Adapter](https://github.com/Goutte/grav-plugin-gitlab-markdown-adapter)
|
||||
- [GitLab Markdown Adapter](https://github.com/Goutte/grav-plugin-gitlab-markdown-adapter)
|
||||
|
||||
## Communication
|
||||
|
||||
@ -98,7 +98,7 @@ They also serve as proof of concept, for the variety of things that can be built
|
||||
- [Flex Diagrams Extension](https://www.mediawiki.org/wiki/Extension:Flex_Diagrams)
|
||||
- [Semantic Media Wiki](https://semantic-mediawiki.org)
|
||||
- [Mermaid Plugin](https://github.com/SemanticMediaWiki/Mermaid)
|
||||
- [FosWiki](https://foswiki.org)
|
||||
- [Foswiki](https://foswiki.org)
|
||||
- [Mermaid Plugin](https://foswiki.org/Extensions/MermaidPlugin)
|
||||
- [DokuWiki](https://dokuwiki.org)
|
||||
- [Mermaid Plugin](https://www.dokuwiki.org/plugin:mermaid)
|
||||
@ -155,6 +155,8 @@ They also serve as proof of concept, for the variety of things that can be built
|
||||
- [Nano Mermaid](https://github.com/Yash-Singh1/nano-mermaid)
|
||||
- [CKEditor](https://github.com/ckeditor/ckeditor5)
|
||||
- [CKEditor 5 Mermaid plugin](https://github.com/ckeditor/ckeditor5-mermaid)
|
||||
- [Standard Notes](https://standardnotes.com/)
|
||||
- [sn-mermaid](https://github.com/nienow/sn-mermaid)
|
||||
|
||||
## Document Generation
|
||||
|
||||
@ -166,7 +168,7 @@ They also serve as proof of concept, for the variety of things that can be built
|
||||
- [rehype-mermaidjs](https://github.com/remcohaszing/rehype-mermaidjs)
|
||||
- [Gatsby](https://www.gatsbyjs.com/)
|
||||
- [gatsby-remark-mermaid](https://github.com/remcohaszing/gatsby-remark-mermaid)
|
||||
- [jSDoc](https://jsdoc.app/)
|
||||
- [JSDoc](https://jsdoc.app/)
|
||||
- [jsdoc-mermaid](https://github.com/Jellyvision/jsdoc-mermaid)
|
||||
- [MkDocs](https://www.mkdocs.org)
|
||||
- [mkdocs-mermaid2-plugin](https://github.com/fralau/mkdocs-mermaid2-plugin)
|
||||
|
@ -20,17 +20,17 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@iconify-json/carbon": "^1.1.16",
|
||||
"@unocss/reset": "^0.52.0",
|
||||
"@vite-pwa/vitepress": "^0.0.5",
|
||||
"@unocss/reset": "^0.53.0",
|
||||
"@vite-pwa/vitepress": "^0.2.0",
|
||||
"@vitejs/plugin-vue": "^4.2.1",
|
||||
"fast-glob": "^3.2.12",
|
||||
"https-localhost": "^4.7.1",
|
||||
"pathe": "^1.1.0",
|
||||
"unocss": "^0.52.0",
|
||||
"unplugin-vue-components": "^0.24.1",
|
||||
"unocss": "^0.53.0",
|
||||
"unplugin-vue-components": "^0.25.0",
|
||||
"vite": "^4.3.3",
|
||||
"vite-plugin-pwa": "^0.15.0",
|
||||
"vitepress": "1.0.0-beta.1",
|
||||
"workbox-window": "^6.5.4"
|
||||
"vite-plugin-pwa": "^0.16.0",
|
||||
"vitepress": "1.0.0-beta.3",
|
||||
"workbox-window": "^7.0.0"
|
||||
}
|
||||
}
|
||||
|
@ -605,6 +605,12 @@ In the example below the style defined in the linkStyle statement will belong to
|
||||
linkStyle 3 stroke:#ff3,stroke-width:4px,color:red;
|
||||
```
|
||||
|
||||
It is also possible to add style to multiple links in a single statement, by separating link numbers with commas:
|
||||
|
||||
```
|
||||
linkStyle 1,2,7 color:blue;
|
||||
```
|
||||
|
||||
### Styling line curves
|
||||
|
||||
It is possible to style the type of curve used for lines between items, if the default method does not meet your needs.
|
||||
@ -638,12 +644,18 @@ flowchart LR
|
||||
More convenient than defining the style every time is to define a class of styles and attach this class to the nodes that
|
||||
should have a different look.
|
||||
|
||||
a class definition looks like the example below:
|
||||
A class definition looks like the example below:
|
||||
|
||||
```
|
||||
classDef className fill:#f9f,stroke:#333,stroke-width:4px;
|
||||
```
|
||||
|
||||
Also, it is possible to define style to multiple classes in one statement:
|
||||
|
||||
```
|
||||
classDef firstClassName,secondClassName font-size:12pt;
|
||||
```
|
||||
|
||||
Attachment of a class to a node is done as per below:
|
||||
|
||||
```
|
||||
|
@ -19,13 +19,13 @@ Mermaid can render Gantt diagrams as SVG, PNG or a MarkDown link that can be pas
|
||||
```mermaid-example
|
||||
gantt
|
||||
title A Gantt Diagram
|
||||
dateFormat YYYY-MM-DD
|
||||
dateFormat YYYY-MM-DD
|
||||
section Section
|
||||
A task :a1, 2014-01-01, 30d
|
||||
Another task :after a1 , 20d
|
||||
A task :a1, 2014-01-01, 30d
|
||||
Another task :after a1, 20d
|
||||
section Another
|
||||
Task in sec :2014-01-12 , 12d
|
||||
another task : 24d
|
||||
Task in Another :2014-01-12, 12d
|
||||
another task :24d
|
||||
```
|
||||
|
||||
## Syntax
|
||||
@ -66,10 +66,10 @@ gantt
|
||||
It is possible to set multiple dependencies separated by space:
|
||||
|
||||
```mermaid-example
|
||||
gantt
|
||||
apple :a, 2017-07-20, 1w
|
||||
banana :crit, b, 2017-07-23, 1d
|
||||
cherry :active, c, after b a, 1d
|
||||
gantt
|
||||
apple :a, 2017-07-20, 1w
|
||||
banana :crit, b, 2017-07-23, 1d
|
||||
cherry :active, c, after b a, 1d
|
||||
```
|
||||
|
||||
### Title
|
||||
@ -88,12 +88,12 @@ You can add milestones to the diagrams. Milestones differ from tasks as they rep
|
||||
|
||||
```mermaid-example
|
||||
gantt
|
||||
dateFormat HH:mm
|
||||
axisFormat %H:%M
|
||||
Initial milestone : milestone, m1, 17:49,2min
|
||||
taska2 : 10min
|
||||
taska3 : 5min
|
||||
Final milestone : milestone, m2, 18:14, 2min
|
||||
dateFormat HH:mm
|
||||
axisFormat %H:%M
|
||||
Initial milestone : milestone, m1, 17:49, 2m
|
||||
Task A : 10m
|
||||
Task B : 5m
|
||||
Final milestone : milestone, m2, 18:08, 4m
|
||||
```
|
||||
|
||||
## Setting dates
|
||||
@ -214,15 +214,14 @@ Comments can be entered within a gantt chart, which will be ignored by the parse
|
||||
```mermaid
|
||||
gantt
|
||||
title A Gantt Diagram
|
||||
%% this is a comment
|
||||
dateFormat YYYY-MM-DD
|
||||
%% This is a comment
|
||||
dateFormat YYYY-MM-DD
|
||||
section Section
|
||||
A task :a1, 2014-01-01, 30d
|
||||
Another task :after a1 , 20d
|
||||
A task :a1, 2014-01-01, 30d
|
||||
Another task :after a1, 20d
|
||||
section Another
|
||||
Task in sec :2014-01-12 , 12d
|
||||
another task : 24d
|
||||
|
||||
Task in Another :2014-01-12, 12d
|
||||
another task :24d
|
||||
```
|
||||
|
||||
## Styling
|
||||
@ -350,7 +349,7 @@ Beginner's tip—a full example using interactive links in an html context:
|
||||
dateFormat YYYY-MM-DD
|
||||
|
||||
section Clickable
|
||||
Visit mermaidjs :active, cl1, 2014-01-07, 3d
|
||||
Visit mermaidjs :active, cl1, 2014-01-07, 3d
|
||||
Print arguments :cl2, after cl1, 3d
|
||||
Print task :cl3, after cl2, 3d
|
||||
|
||||
|
@ -133,6 +133,6 @@ quadrantChart
|
||||
y-axis Not Important --> "Important ❤"
|
||||
quadrant-1 Plan
|
||||
quadrant-2 Do
|
||||
quadrant-3 Deligate
|
||||
quadrant-3 Delegate
|
||||
quadrant-4 Delete
|
||||
```
|
||||
|
@ -172,9 +172,11 @@ let us look at same example, where we have disabled the multiColor option.
|
||||
|
||||
### Customizing Color scheme
|
||||
|
||||
You can customize the color scheme using the `cScale0` to `cScale11` theme variables. Mermaid allows you to set unique colors for up-to 12 sections, where `cScale0` variable will drive the value of the first section or time-period, `cScale1` will drive the value of the second section and so on.
|
||||
You can customize the color scheme using the `cScale0` to `cScale11` theme variables, which will change the background colors. Mermaid allows you to set unique colors for up-to 12 sections, where `cScale0` variable will drive the value of the first section or time-period, `cScale1` will drive the value of the second section and so on.
|
||||
In case you have more than 12 sections, the color scheme will start to repeat.
|
||||
|
||||
If you also want to change the foreground color of a section, you can do so use theme variables corresponding `cScaleLabel0` to `cScaleLabel11` variables.
|
||||
|
||||
NOTE: Default values for these theme variables are picked from the selected theme. If you want to override the default values, you can use the `initialize` call to add your custom theme variable values.
|
||||
|
||||
Example:
|
||||
@ -183,9 +185,9 @@ Now let's override the default values for the `cScale0` to `cScale2` variables:
|
||||
|
||||
```mermaid-example
|
||||
%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': {
|
||||
'cScale0': '#ff0000',
|
||||
'cScale0': '#ff0000', 'cScaleLabel0': '#ffffff',
|
||||
'cScale1': '#00ff00',
|
||||
'cScale2': '#0000ff'
|
||||
'cScale2': '#0000ff', 'cScaleLabel2': '#ffffff'
|
||||
} } }%%
|
||||
timeline
|
||||
title History of Social Media Platform
|
||||
|
@ -78,7 +78,6 @@ export interface ParseOptions {
|
||||
}
|
||||
|
||||
// This makes it clear that we're working with a d3 selected element of some kind, even though it's hard to specify the exact type.
|
||||
// @ts-ignore Could replicate the type definition in d3. This also makes it possible to use the untyped info from the js diagram files.
|
||||
export type D3Element = any;
|
||||
|
||||
export interface RenderResult {
|
||||
@ -491,13 +490,7 @@ const render = async function (
|
||||
? diag.renderer.getClasses(text, diag)
|
||||
: {};
|
||||
|
||||
const rules = createUserStyles(
|
||||
config,
|
||||
graphType,
|
||||
// @ts-ignore convert renderer to TS.
|
||||
diagramClassDefs,
|
||||
idSelector
|
||||
);
|
||||
const rules = createUserStyles(config, graphType, diagramClassDefs, idSelector);
|
||||
|
||||
const style1 = document.createElement('style');
|
||||
style1.innerHTML = rules;
|
||||
|
@ -22,7 +22,6 @@ import er from './diagrams/er/styles.js';
|
||||
import error from './diagrams/error/styles.js';
|
||||
import git from './diagrams/git/styles.js';
|
||||
import gantt from './diagrams/gantt/styles.js';
|
||||
import info from './diagrams/info/styles.js';
|
||||
import pie from './diagrams/pie/styles.js';
|
||||
import requirement from './diagrams/requirement/styles.js';
|
||||
import sequence from './diagrams/sequence/styles.js';
|
||||
@ -92,7 +91,6 @@ describe('styles', () => {
|
||||
flowchartElk,
|
||||
gantt,
|
||||
git,
|
||||
info,
|
||||
journey,
|
||||
mindmap,
|
||||
pie,
|
||||
|
@ -1,7 +1,8 @@
|
||||
import type { FlowChartStyleOptions } from './diagrams/flowchart/styles.js';
|
||||
import { log } from './logger.js';
|
||||
import type { DiagramStylesProvider } from './diagram-api/types.js';
|
||||
|
||||
const themes: Record<string, any> = {};
|
||||
const themes: Record<string, DiagramStylesProvider> = {};
|
||||
|
||||
const getStyles = (
|
||||
type: string,
|
||||
@ -73,8 +74,10 @@ const getStyles = (
|
||||
`;
|
||||
};
|
||||
|
||||
export const addStylesForDiagram = (type: string, diagramTheme: unknown): void => {
|
||||
themes[type] = diagramTheme;
|
||||
export const addStylesForDiagram = (type: string, diagramTheme?: DiagramStylesProvider): void => {
|
||||
if (diagramTheme !== undefined) {
|
||||
themes[type] = diagramTheme;
|
||||
}
|
||||
};
|
||||
|
||||
export default getStyles;
|
||||
|
2512
pnpm-lock.yaml
generated
2512
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
19
scripts/coverage.ts
Normal file
19
scripts/coverage.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { execSync } from 'child_process';
|
||||
import { cp } from 'fs/promises';
|
||||
|
||||
const main = async () => {
|
||||
const coverageDir = 'coverage';
|
||||
const coverageFiles = ['vitest', 'cypress'].map(
|
||||
(dir) => `${coverageDir}/${dir}/coverage-final.json`
|
||||
);
|
||||
|
||||
//copy coverage files from vitest and cypress to coverage folder
|
||||
await Promise.all(
|
||||
coverageFiles.map((file) => cp(file, `${coverageDir}/combined/${file.split('/')[1]}.json`))
|
||||
);
|
||||
|
||||
execSync('npx nyc merge coverage/combined coverage/combined-final.json');
|
||||
execSync('npx nyc report -t coverage --report-dir coverage/html --reporter=html-spa');
|
||||
};
|
||||
|
||||
void main();
|
@ -17,7 +17,10 @@ export default defineConfig({
|
||||
// TODO: should we move this to a mermaid-core package?
|
||||
setupFiles: ['packages/mermaid/src/tests/setup.ts'],
|
||||
coverage: {
|
||||
provider: 'v8',
|
||||
reporter: ['text', 'json', 'html', 'lcov'],
|
||||
reportsDirectory: './coverage/vitest',
|
||||
exclude: ['**/node_modules/**', '**/tests/**', '**/__mocks__/**'],
|
||||
},
|
||||
},
|
||||
build: {
|
||||
|
Loading…
x
Reference in New Issue
Block a user