mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-13 04:19:44 +02:00
Compare commits
36 Commits
v10.2.2
...
sidv/zenum
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1b40f552b2 | ||
![]() |
5b696a72f8 | ||
![]() |
d148a65967 | ||
![]() |
74ccf6410d | ||
![]() |
c2c8024718 | ||
![]() |
5338d90077 | ||
![]() |
180c695f2f | ||
![]() |
38d9ebc5da | ||
![]() |
5fd5de10b5 | ||
![]() |
cb2bc2a587 | ||
![]() |
102b9bc8c3 | ||
![]() |
9cec5ae1c4 | ||
![]() |
acc19db5bb | ||
![]() |
6cce1b20fb | ||
![]() |
a00616863d | ||
![]() |
49c97dad4c | ||
![]() |
e984b34af4 | ||
![]() |
c255d95ae2 | ||
![]() |
27e59e5adc | ||
![]() |
507e24cc72 | ||
![]() |
bb400d53b9 | ||
![]() |
6a89ef94f7 | ||
![]() |
97be4983f0 | ||
![]() |
c7affbe33b | ||
![]() |
82eccb70fa | ||
![]() |
c889ef0c30 | ||
![]() |
cce5505662 | ||
![]() |
b925849893 | ||
![]() |
d86d1e7887 | ||
![]() |
a01343bf1b | ||
![]() |
88f9233aa8 | ||
![]() |
8cd48bf405 | ||
![]() |
8b18fd93f4 | ||
![]() |
ec62c2bf5b | ||
![]() |
b9e7ba023f | ||
![]() |
12ed81855a |
@@ -4,4 +4,5 @@ docs/Setup.md
|
|||||||
cypress.config.js
|
cypress.config.js
|
||||||
cypress/plugins/index.js
|
cypress/plugins/index.js
|
||||||
coverage
|
coverage
|
||||||
*.json
|
*.json
|
||||||
|
node_modules
|
||||||
|
26
.github/ISSUE_TEMPLATE/diagram_proposal.yml
vendored
26
.github/ISSUE_TEMPLATE/diagram_proposal.yml
vendored
@@ -3,6 +3,7 @@ description: Suggest a new Diagram Type to add to Mermaid.
|
|||||||
labels:
|
labels:
|
||||||
- 'Status: Triage'
|
- 'Status: Triage'
|
||||||
- 'Type: Enhancement'
|
- 'Type: Enhancement'
|
||||||
|
- 'Type: New Diagram'
|
||||||
|
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
- type: markdown
|
||||||
@@ -17,6 +18,14 @@ body:
|
|||||||
- Use a clear and concise title
|
- Use a clear and concise title
|
||||||
- Fill out the text fields with as much detail as possible.
|
- Fill out the text fields with as much detail as possible.
|
||||||
- Never be shy to give us screenshots and/or code samples. It will help!
|
- Never be shy to give us screenshots and/or code samples. It will help!
|
||||||
|
|
||||||
|
## Example issues
|
||||||
|
|
||||||
|
Refer to the discussions here to get an idea of how the diagram syntax is created.
|
||||||
|
|
||||||
|
- https://github.com/mermaid-js/mermaid/issues/4269
|
||||||
|
- https://github.com/mermaid-js/mermaid/issues/4282
|
||||||
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: Proposal
|
label: Proposal
|
||||||
@@ -35,8 +44,17 @@ body:
|
|||||||
description: If applicable, add screenshots to show possible examples of how the diagram may look like.
|
description: If applicable, add screenshots to show possible examples of how the diagram may look like.
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: Code Sample
|
label: Syntax
|
||||||
description: |-
|
description: |-
|
||||||
If applicable, add a code sample for how to implement this new diagram.
|
If possible, include a syntax which could be used to write the diagram.
|
||||||
The text will automatically be rendered as JavaScript code.
|
Try to add one or two examples of valid use-cases here.
|
||||||
render: javascript
|
- type: dropdown
|
||||||
|
id: implementation
|
||||||
|
attributes:
|
||||||
|
label: Implementation
|
||||||
|
description: |-
|
||||||
|
Would you like to implement this yourself, or is it a proposal for the community?
|
||||||
|
If there is no corresponding PR from your side after 30 days, the diagram will be open for everyone to implement.
|
||||||
|
options:
|
||||||
|
- I will try and implement it myself.
|
||||||
|
- This is a proposal which I'd love to see built into mermaid by the wonderful community.
|
||||||
|
@@ -44,6 +44,11 @@ const packageOptions = {
|
|||||||
packageName: 'mermaid-example-diagram',
|
packageName: 'mermaid-example-diagram',
|
||||||
file: 'detector.ts',
|
file: 'detector.ts',
|
||||||
},
|
},
|
||||||
|
'mermaid-zenuml': {
|
||||||
|
name: 'mermaid-zenuml',
|
||||||
|
packageName: 'mermaid-zenuml',
|
||||||
|
file: 'detector.ts',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
interface BuildOptions {
|
interface BuildOptions {
|
||||||
@@ -146,6 +151,7 @@ if (watch) {
|
|||||||
build(getBuildConfig({ minify: false, watch, core: false, entryName: 'mermaid' }));
|
build(getBuildConfig({ minify: false, watch, core: false, entryName: 'mermaid' }));
|
||||||
if (!mermaidOnly) {
|
if (!mermaidOnly) {
|
||||||
build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-example-diagram' }));
|
build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-example-diagram' }));
|
||||||
|
build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-zenuml' }));
|
||||||
}
|
}
|
||||||
} else if (visualize) {
|
} else if (visualize) {
|
||||||
await build(getBuildConfig({ minify: false, core: true, entryName: 'mermaid' }));
|
await build(getBuildConfig({ minify: false, core: true, entryName: 'mermaid' }));
|
||||||
|
@@ -15,6 +15,7 @@ async function createServer() {
|
|||||||
|
|
||||||
app.use(cors());
|
app.use(cors());
|
||||||
app.use(express.static('./packages/mermaid/dist'));
|
app.use(express.static('./packages/mermaid/dist'));
|
||||||
|
app.use(express.static('./packages/mermaid-zenuml/dist'));
|
||||||
app.use(express.static('./packages/mermaid-example-diagram/dist'));
|
app.use(express.static('./packages/mermaid-example-diagram/dist'));
|
||||||
app.use(vite.middlewares);
|
app.use(vite.middlewares);
|
||||||
app.use(express.static('demos'));
|
app.use(express.static('demos'));
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
"alois",
|
"alois",
|
||||||
"aloisklink",
|
"aloisklink",
|
||||||
"antiscript",
|
"antiscript",
|
||||||
|
"antlr",
|
||||||
"appli",
|
"appli",
|
||||||
"applitools",
|
"applitools",
|
||||||
"asciidoctor",
|
"asciidoctor",
|
||||||
@@ -134,7 +135,8 @@
|
|||||||
"vitepress",
|
"vitepress",
|
||||||
"vueuse",
|
"vueuse",
|
||||||
"xlink",
|
"xlink",
|
||||||
"yash"
|
"yash",
|
||||||
|
"zenuml"
|
||||||
],
|
],
|
||||||
"patterns": [
|
"patterns": [
|
||||||
{ "name": "Markdown links", "pattern": "\\((.*)\\)", "description": "" },
|
{ "name": "Markdown links", "pattern": "\\((.*)\\)", "description": "" },
|
||||||
|
@@ -60,7 +60,7 @@ export const renderGraph = (graphStr, options, api) => {
|
|||||||
openURLAndVerifyRendering(url, options);
|
openURLAndVerifyRendering(url, options);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const openURLAndVerifyRendering = (url, options, validation = undefined) => {
|
const openURLAndVerifyRendering = (url, options, validation = undefined) => {
|
||||||
const useAppli = Cypress.env('useAppli');
|
const useAppli = Cypress.env('useAppli');
|
||||||
const name = (options.name || cy.state('runnable').fullTitle()).replace(/\s+/g, '-');
|
const name = (options.name || cy.state('runnable').fullTitle()).replace(/\s+/g, '-');
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { urlSnapshotTest, openURLAndVerifyRendering } from '../../helpers/util.js';
|
import { urlSnapshotTest } from '../../helpers/util.js';
|
||||||
|
|
||||||
describe('CSS injections', () => {
|
describe('CSS injections', () => {
|
||||||
it('should not allow CSS injections outside of the diagram', () => {
|
it('should not allow CSS injections outside of the diagram', () => {
|
||||||
@@ -13,11 +13,4 @@ describe('CSS injections', () => {
|
|||||||
flowchart: { htmlLabels: false },
|
flowchart: { htmlLabels: false },
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('should not allow manipulating styletags using arrowheads', () => {
|
|
||||||
openURLAndVerifyRendering('http://localhost:9000/xss23-css.html', {
|
|
||||||
logLevel: 1,
|
|
||||||
arrowMarkerAbsolute: false,
|
|
||||||
flowchart: { htmlLabels: true },
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
19
cypress/integration/rendering/zenuml.spec.js
Normal file
19
cypress/integration/rendering/zenuml.spec.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { imgSnapshotTest } from '../../helpers/util.js';
|
||||||
|
|
||||||
|
describe('Zen UML', () => {
|
||||||
|
it('Basic Zen UML diagram', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`
|
||||||
|
zenuml
|
||||||
|
A.method() {
|
||||||
|
if(x) {
|
||||||
|
B.method() {
|
||||||
|
selfCall() { return X }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
@@ -1,5 +1,6 @@
|
|||||||
import mermaid2 from './mermaid.esm.mjs';
|
import mermaid2 from './mermaid.esm.mjs';
|
||||||
import externalExample from '../../packages/mermaid-example-diagram/dist/mermaid-example-diagram.core.mjs';
|
import externalExample from '../../packages/mermaid-example-diagram/dist/mermaid-example-diagram.core.mjs';
|
||||||
|
import zenUml from '../../packages/mermaid-zenuml/dist/mermaid-zenuml.core.mjs';
|
||||||
|
|
||||||
function b64ToUtf8(str) {
|
function b64ToUtf8(str) {
|
||||||
return decodeURIComponent(escape(window.atob(str)));
|
return decodeURIComponent(escape(window.atob(str)));
|
||||||
@@ -44,7 +45,7 @@ const contentLoaded = async function () {
|
|||||||
document.getElementsByTagName('body')[0].appendChild(div);
|
document.getElementsByTagName('body')[0].appendChild(div);
|
||||||
}
|
}
|
||||||
|
|
||||||
await mermaid2.registerExternalDiagrams([externalExample]);
|
await mermaid2.registerExternalDiagrams([externalExample, zenUml]);
|
||||||
mermaid2.initialize(graphObj.mermaid);
|
mermaid2.initialize(graphObj.mermaid);
|
||||||
await mermaid2.run();
|
await mermaid2.run();
|
||||||
}
|
}
|
||||||
|
@@ -1,85 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
|
|
||||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
|
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
|
||||||
/>
|
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
|
|
||||||
rel="stylesheet"
|
|
||||||
/>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
/* background: rgb(221, 208, 208); */
|
|
||||||
/* background:#333; */
|
|
||||||
font-family: 'Arial';
|
|
||||||
/* font-size: 18px !important; */
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
color: grey;
|
|
||||||
}
|
|
||||||
.mermaid2 {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.mermaid svg {
|
|
||||||
/* font-size: 18px !important; */
|
|
||||||
}
|
|
||||||
.malware {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
height: 150px;
|
|
||||||
background: red;
|
|
||||||
color: black;
|
|
||||||
display: flex;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
font-family: monospace;
|
|
||||||
font-size: 72px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div>Security check</div>
|
|
||||||
<div class="flex">
|
|
||||||
<div id="diagram" class="mermaid"></div>
|
|
||||||
<div id="graph-div"></div>
|
|
||||||
<div id="res" class=""></div>
|
|
||||||
</div>
|
|
||||||
<script type="module">
|
|
||||||
import mermaid from './mermaid.esm.mjs';
|
|
||||||
mermaid.parseError = function (err, hash) {
|
|
||||||
// console.error('Mermaid error: ', err);
|
|
||||||
};
|
|
||||||
mermaid.initialize({
|
|
||||||
theme: 'base',
|
|
||||||
startOnLoad: false,
|
|
||||||
flowcharts: { htmlLabels: true },
|
|
||||||
});
|
|
||||||
function callback() {
|
|
||||||
alert('It worked');
|
|
||||||
}
|
|
||||||
function xssAttack() {
|
|
||||||
const div = document.createElement('div');
|
|
||||||
div.id = 'the-malware';
|
|
||||||
div.className = 'malware';
|
|
||||||
div.innerHTML = 'XSS Succeeded';
|
|
||||||
document.getElementsByTagName('body')[0].appendChild(div);
|
|
||||||
throw new Error('XSS Succeeded');
|
|
||||||
}
|
|
||||||
|
|
||||||
let diagram = `graph TD
|
|
||||||
A[["a marker-end=#quot;url(<s title='#<style>*{background:red}</style>'>b"]]
|
|
||||||
`;
|
|
||||||
const el = document.querySelector('#graph-div');
|
|
||||||
console.log(diagram);
|
|
||||||
const { svg } = await mermaid.render('graph-div', diagram);
|
|
||||||
document.querySelector('#res').innerHTML = svg;
|
|
||||||
window.rendered = true;
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@@ -66,6 +66,9 @@
|
|||||||
<li>
|
<li>
|
||||||
<h2><a href="./state.html">State</a></h2>
|
<h2><a href="./state.html">State</a></h2>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<h2><a href="./zenuml.html">ZenUML</a></h2>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
53
demos/zenuml.html
Normal file
53
demos/zenuml.html
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<title>Mermaid Zenuml Test Page</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>Zenuml demos</h1>
|
||||||
|
<pre class="mermaid">
|
||||||
|
zenuml
|
||||||
|
title Sync Messages (Design Pattern: Adapter)
|
||||||
|
@Starter(Client)
|
||||||
|
Adapter.interfaceMethod() {
|
||||||
|
translateParameter(parameter)
|
||||||
|
|
||||||
|
result = Implementation.implementationMethod()
|
||||||
|
|
||||||
|
translateResult()
|
||||||
|
return translatedResult
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<pre class="mermaid">
|
||||||
|
zenuml
|
||||||
|
title Async Messages (SPA Authentication)
|
||||||
|
// ```
|
||||||
|
// GET https://${account.namespace}/authorize/?
|
||||||
|
// response_type=token
|
||||||
|
// &client_id=${account.clientId}
|
||||||
|
// &redirect_url=YOUR_CALLBACK_URL
|
||||||
|
// &state=VALUE_THAT_SURVIVES_REDIRECTS
|
||||||
|
// &scope=openid
|
||||||
|
// ```
|
||||||
|
Browser->Auth0: 1. initiate the authentication
|
||||||
|
Auth0->"Identity Provider": 2. OAuth2 / SAML, etc
|
||||||
|
"Identity Provider"->"Identity Provider": 3. user gets authenticated
|
||||||
|
Auth0->Browser: 4. redirect to ${YOUR_CALLBACK_URL}/#id_token=e68...
|
||||||
|
Browser->Auth0: 5. validate id_token and get user profile
|
||||||
|
Browser->"Your API": 6. call API sending JWT in Authorization header
|
||||||
|
"Your API"->"Your API": 7. validate token
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<script type="module">
|
||||||
|
import mermaid from './mermaid.esm.mjs';
|
||||||
|
import zenuml from './mermaid-zenuml.esm.mjs';
|
||||||
|
await mermaid.registerExternalDiagrams([zenuml]);
|
||||||
|
mermaid.initialize({
|
||||||
|
logLevel: 3,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@@ -96,7 +96,7 @@ mermaid.initialize(config);
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:670](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L670)
|
[mermaidAPI.ts:667](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L667)
|
||||||
|
|
||||||
## Functions
|
## Functions
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ Return the last node appended
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:309](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L309)
|
[mermaidAPI.ts:306](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L306)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -295,7 +295,7 @@ Put the svgCode into an iFrame. Return the iFrame code
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:288](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L288)
|
[mermaidAPI.ts:285](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L285)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -320,4 +320,4 @@ Remove any existing elements from the given document
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:359](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L359)
|
[mermaidAPI.ts:356](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L356)
|
||||||
|
@@ -16,6 +16,7 @@ They also serve as proof of concept, for the variety of things that can be built
|
|||||||
- [Using code blocks](https://github.blog/2022-02-14-include-diagrams-markdown-files-mermaid/) (**Native support**)
|
- [Using code blocks](https://github.blog/2022-02-14-include-diagrams-markdown-files-mermaid/) (**Native support**)
|
||||||
- [GitHub action: Compile mermaid to image](https://github.com/neenjaw/compile-mermaid-markdown-action)
|
- [GitHub action: Compile mermaid to image](https://github.com/neenjaw/compile-mermaid-markdown-action)
|
||||||
- [svg-generator](https://github.com/SimonKenyonShepard/mermaidjs-github-svg-generator)
|
- [svg-generator](https://github.com/SimonKenyonShepard/mermaidjs-github-svg-generator)
|
||||||
|
- [GitHub Writer](https://github.com/ckeditor/github-writer)
|
||||||
- [GitLab](https://docs.gitlab.com/ee/user/markdown.html#diagrams-and-flowcharts) (**Native support**)
|
- [GitLab](https://docs.gitlab.com/ee/user/markdown.html#diagrams-and-flowcharts) (**Native support**)
|
||||||
- [Gitea](https://gitea.io) (**Native support**)
|
- [Gitea](https://gitea.io) (**Native support**)
|
||||||
- [Azure Devops](https://docs.microsoft.com/en-us/azure/devops/project/wiki/wiki-markdown-guidance?view=azure-devops#add-mermaid-diagrams-to-a-wiki-page) (**Native support**)
|
- [Azure Devops](https://docs.microsoft.com/en-us/azure/devops/project/wiki/wiki-markdown-guidance?view=azure-devops#add-mermaid-diagrams-to-a-wiki-page) (**Native support**)
|
||||||
@@ -142,6 +143,8 @@ They also serve as proof of concept, for the variety of things that can be built
|
|||||||
- [Named block =Diagram](https://github.com/zag/podlite/tree/main/packages/podlite-diagrams)
|
- [Named block =Diagram](https://github.com/zag/podlite/tree/main/packages/podlite-diagrams)
|
||||||
- [GNU Nano](https://www.nano-editor.org/)
|
- [GNU Nano](https://www.nano-editor.org/)
|
||||||
- [Nano Mermaid](https://github.com/Yash-Singh1/nano-mermaid)
|
- [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)
|
||||||
|
|
||||||
## Document Generation
|
## Document Generation
|
||||||
|
|
||||||
|
BIN
docs/syntax/img/zenuml-participant-annotators.png
Normal file
BIN
docs/syntax/img/zenuml-participant-annotators.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 255 KiB |
@@ -46,6 +46,9 @@ quadrantChart
|
|||||||
|
|
||||||
## Syntax
|
## Syntax
|
||||||
|
|
||||||
|
> **Note**
|
||||||
|
> In place of `<text>` you can use text like `this is a sample text` or inside **double quotes** like `"This type of text may contain unicode like ❤"`.
|
||||||
|
|
||||||
> **Note**
|
> **Note**
|
||||||
> If there is no points available in the chart both **axis** text and **quadrant** will be rendered in the center of the respective quadrant.
|
> If there is no points available in the chart both **axis** text and **quadrant** will be rendered in the center of the respective quadrant.
|
||||||
> If there are points **x-axis** labels will rendered from left of the respective quadrant also they will be displayed in bottom of the chart, and **y-axis** lables will be rendered in bottom of the respective quadrant, the quadrant text will render at top of the respective quadrant.
|
> If there are points **x-axis** labels will rendered from left of the respective quadrant also they will be displayed in bottom of the chart, and **y-axis** lables will be rendered in bottom of the respective quadrant, the quadrant text will render at top of the respective quadrant.
|
||||||
@@ -149,7 +152,7 @@ Points are used to plot a circle inside the quadrantChart. The syntax is `<text>
|
|||||||
%%{init: {"quadrantChart": {"chartWidth": 400, "chartHeight": 400}, "themeVariables": {"quadrant1TextFill": "#ff0000"} }}%%
|
%%{init: {"quadrantChart": {"chartWidth": 400, "chartHeight": 400}, "themeVariables": {"quadrant1TextFill": "#ff0000"} }}%%
|
||||||
quadrantChart
|
quadrantChart
|
||||||
x-axis Urgent --> Not Urgent
|
x-axis Urgent --> Not Urgent
|
||||||
y-axis Not Important --> "Important ❤"
|
y-axis Not Important --> important
|
||||||
quadrant-1 Plan
|
quadrant-1 Plan
|
||||||
quadrant-2 Do
|
quadrant-2 Do
|
||||||
quadrant-3 Deligate
|
quadrant-3 Deligate
|
||||||
@@ -160,7 +163,7 @@ quadrantChart
|
|||||||
%%{init: {"quadrantChart": {"chartWidth": 400, "chartHeight": 400}, "themeVariables": {"quadrant1TextFill": "#ff0000"} }}%%
|
%%{init: {"quadrantChart": {"chartWidth": 400, "chartHeight": 400}, "themeVariables": {"quadrant1TextFill": "#ff0000"} }}%%
|
||||||
quadrantChart
|
quadrantChart
|
||||||
x-axis Urgent --> Not Urgent
|
x-axis Urgent --> Not Urgent
|
||||||
y-axis Not Important --> "Important ❤"
|
y-axis Not Important --> important
|
||||||
quadrant-1 Plan
|
quadrant-1 Plan
|
||||||
quadrant-2 Do
|
quadrant-2 Do
|
||||||
quadrant-3 Deligate
|
quadrant-3 Deligate
|
||||||
|
472
docs/syntax/zenuml.md
Normal file
472
docs/syntax/zenuml.md
Normal file
@@ -0,0 +1,472 @@
|
|||||||
|
> **Warning**
|
||||||
|
>
|
||||||
|
> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT.
|
||||||
|
>
|
||||||
|
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/zenuml.md](../../packages/mermaid/src/docs/syntax/zenuml.md).
|
||||||
|
|
||||||
|
# ZenUML
|
||||||
|
|
||||||
|
> A Sequence diagram is an interaction diagram that shows how processes operate with one another and in what order.
|
||||||
|
|
||||||
|
Mermaid can render sequence diagrams with [ZenUML](https://zenuml.com). Note that ZenUML uses a different
|
||||||
|
syntax than the original Sequence Diagram in mermaid.
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
title Demo
|
||||||
|
Alice->John: Hello John, how are you?
|
||||||
|
John->Alice: Great!
|
||||||
|
Alice->John: See you later!
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
zenuml
|
||||||
|
title Demo
|
||||||
|
Alice->John: Hello John, how are you?
|
||||||
|
John->Alice: Great!
|
||||||
|
Alice->John: See you later!
|
||||||
|
```
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
### Participants
|
||||||
|
|
||||||
|
The participants can be defined implicitly as in the first example on this page. The participants or actors are
|
||||||
|
rendered in order of appearance in the diagram source text. Sometimes you might want to show the participants in a
|
||||||
|
different order than how they appear in the first message. It is possible to specify the actor's order of
|
||||||
|
appearance by doing the following:
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
title Declare participant (optional)
|
||||||
|
Bob
|
||||||
|
Alice
|
||||||
|
Alice->Bob: Hi Bob
|
||||||
|
Bob->Alice: Hi Alice
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
zenuml
|
||||||
|
title Declare participant (optional)
|
||||||
|
Bob
|
||||||
|
Alice
|
||||||
|
Alice->Bob: Hi Bob
|
||||||
|
Bob->Alice: Hi Alice
|
||||||
|
```
|
||||||
|
|
||||||
|
### Annotators
|
||||||
|
|
||||||
|
If you specifically want to use symbols instead of just rectangles with text you can do so by using the annotator syntax to declare participants as per below.
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
title Annotators
|
||||||
|
@Actor Alice
|
||||||
|
@Database Bob
|
||||||
|
Alice->Bob: Hi Bob
|
||||||
|
Bob->Alice: Hi Alice
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
zenuml
|
||||||
|
title Annotators
|
||||||
|
@Actor Alice
|
||||||
|
@Database Bob
|
||||||
|
Alice->Bob: Hi Bob
|
||||||
|
Bob->Alice: Hi Alice
|
||||||
|
```
|
||||||
|
|
||||||
|
Here are the available annotators:
|
||||||
|

|
||||||
|
|
||||||
|
### Aliases
|
||||||
|
|
||||||
|
The participants can have a convenient identifier and a descriptive label.
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
title Aliases
|
||||||
|
A as Alice
|
||||||
|
J as John
|
||||||
|
A->J: Hello John, how are you?
|
||||||
|
J->A: Great!
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
zenuml
|
||||||
|
title Aliases
|
||||||
|
A as Alice
|
||||||
|
J as John
|
||||||
|
A->J: Hello John, how are you?
|
||||||
|
J->A: Great!
|
||||||
|
```
|
||||||
|
|
||||||
|
## Messages
|
||||||
|
|
||||||
|
Messages can be one of:
|
||||||
|
|
||||||
|
1. Sync message
|
||||||
|
2. Async message
|
||||||
|
3. Creation message
|
||||||
|
4. Reply message
|
||||||
|
|
||||||
|
### Sync message
|
||||||
|
|
||||||
|
You can think of a sync (blocking) method in a programming language.
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
title Sync message
|
||||||
|
A.SyncMessage
|
||||||
|
A.SyncMessage(with, parameters) {
|
||||||
|
B.nestedSyncMessage()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
zenuml
|
||||||
|
title Sync message
|
||||||
|
A.SyncMessage
|
||||||
|
A.SyncMessage(with, parameters) {
|
||||||
|
B.nestedSyncMessage()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Async message
|
||||||
|
|
||||||
|
You can think of an async (non-blocking) method in a programming language.
|
||||||
|
Fire an event and forget about it.
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
title Async message
|
||||||
|
Alice->Bob: How are you?
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
zenuml
|
||||||
|
title Async message
|
||||||
|
Alice->Bob: How are you?
|
||||||
|
```
|
||||||
|
|
||||||
|
### Creation message
|
||||||
|
|
||||||
|
We use `new` keyword to create an object.
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
new A1
|
||||||
|
new A2(with, parameters)
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
zenuml
|
||||||
|
new A1
|
||||||
|
new A2(with, parameters)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reply message
|
||||||
|
|
||||||
|
There are three ways to express a reply message:
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
// 1. assign a variable from a sync message.
|
||||||
|
a = A.SyncMessage()
|
||||||
|
|
||||||
|
// 1.1. optionally give the variable a type
|
||||||
|
SomeType a = A.SyncMessage()
|
||||||
|
|
||||||
|
// 2. use return keyword
|
||||||
|
A.SyncMessage() {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. use @return or @reply annotator on an async message
|
||||||
|
@return
|
||||||
|
A->B: result
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
zenuml
|
||||||
|
// 1. assign a variable from a sync message.
|
||||||
|
a = A.SyncMessage()
|
||||||
|
|
||||||
|
// 1.1. optionally give the variable a type
|
||||||
|
SomeType a = A.SyncMessage()
|
||||||
|
|
||||||
|
// 2. use return keyword
|
||||||
|
A.SyncMessage() {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. use @return or @reply annotator on an async message
|
||||||
|
@return
|
||||||
|
A->B: result
|
||||||
|
```
|
||||||
|
|
||||||
|
The third way `@return` is rarely used, but it is useful when you want to return to one level up.
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
title Reply message
|
||||||
|
Client->A.method() {
|
||||||
|
B.method() {
|
||||||
|
if(condition) {
|
||||||
|
return x1
|
||||||
|
// return early
|
||||||
|
@return
|
||||||
|
A->Client: x11
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return x2
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
zenuml
|
||||||
|
title Reply message
|
||||||
|
Client->A.method() {
|
||||||
|
B.method() {
|
||||||
|
if(condition) {
|
||||||
|
return x1
|
||||||
|
// return early
|
||||||
|
@return
|
||||||
|
A->Client: x11
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return x2
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Nesting
|
||||||
|
|
||||||
|
Sync messages and Creation messages are naturally nestable with `{}`.
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
A.method() {
|
||||||
|
B.nested_sync_method()
|
||||||
|
B->C: nested async message
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
zenuml
|
||||||
|
A.method() {
|
||||||
|
B.nested_sync_method()
|
||||||
|
B->C: nested async message
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Comments
|
||||||
|
|
||||||
|
It is possible to add comments to a sequence diagram with `// comment` syntax.
|
||||||
|
Comments will be rendered above the messages or fragments. Comments on other places
|
||||||
|
are ignored. Markdown is supported.
|
||||||
|
|
||||||
|
See the example below:
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
// a comment on a participant will not be rendered
|
||||||
|
BookService
|
||||||
|
// a comment on a message.
|
||||||
|
// **Markdown** is supported.
|
||||||
|
BookService.getBook()
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
zenuml
|
||||||
|
// a comment on a participant will not be rendered
|
||||||
|
BookService
|
||||||
|
// a comment on a message.
|
||||||
|
// **Markdown** is supported.
|
||||||
|
BookService.getBook()
|
||||||
|
```
|
||||||
|
|
||||||
|
## Loops
|
||||||
|
|
||||||
|
It is possible to express loops in a ZenUML diagram. This is done by any of the
|
||||||
|
following notations:
|
||||||
|
|
||||||
|
1. while
|
||||||
|
2. for
|
||||||
|
3. forEach, foreach
|
||||||
|
4. loop
|
||||||
|
|
||||||
|
```zenuml
|
||||||
|
while(condition) {
|
||||||
|
...statements...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See the example below:
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
Alice->John: Hello John, how are you?
|
||||||
|
while(true) {
|
||||||
|
John->Alice: Great!
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
zenuml
|
||||||
|
Alice->John: Hello John, how are you?
|
||||||
|
while(true) {
|
||||||
|
John->Alice: Great!
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Alt
|
||||||
|
|
||||||
|
It is possible to express alternative paths in a sequence diagram. This is done by the notation
|
||||||
|
|
||||||
|
```zenuml
|
||||||
|
if(condition1) {
|
||||||
|
...statements...
|
||||||
|
} else if(condition2) {
|
||||||
|
...statements...
|
||||||
|
} else {
|
||||||
|
...statements...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See the example below:
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
Alice->Bob: Hello Bob, how are you?
|
||||||
|
if(is_sick) {
|
||||||
|
Bob->Alice: Not so good :(
|
||||||
|
} else {
|
||||||
|
Bob->Alice: Feeling fresh like a daisy
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
zenuml
|
||||||
|
Alice->Bob: Hello Bob, how are you?
|
||||||
|
if(is_sick) {
|
||||||
|
Bob->Alice: Not so good :(
|
||||||
|
} else {
|
||||||
|
Bob->Alice: Feeling fresh like a daisy
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Opt
|
||||||
|
|
||||||
|
It is possible to render an `opt` fragment. This is done by the notation
|
||||||
|
|
||||||
|
```zenuml
|
||||||
|
opt {
|
||||||
|
...statements...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See the example below:
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
Alice->Bob: Hello Bob, how are you?
|
||||||
|
Bob->Alice: Not so good :(
|
||||||
|
opt {
|
||||||
|
Bob->Alice: Thanks for asking
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
zenuml
|
||||||
|
Alice->Bob: Hello Bob, how are you?
|
||||||
|
Bob->Alice: Not so good :(
|
||||||
|
opt {
|
||||||
|
Bob->Alice: Thanks for asking
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Parallel
|
||||||
|
|
||||||
|
It is possible to show actions that are happening in parallel.
|
||||||
|
|
||||||
|
This is done by the notation
|
||||||
|
|
||||||
|
```zenuml
|
||||||
|
par {
|
||||||
|
statement1
|
||||||
|
statement2
|
||||||
|
statement3
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See the example below:
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
par {
|
||||||
|
Alice->Bob: Hello guys!
|
||||||
|
Alice->John: Hello guys!
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
zenuml
|
||||||
|
par {
|
||||||
|
Alice->Bob: Hello guys!
|
||||||
|
Alice->John: Hello guys!
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Try/Catch/Finally (Break)
|
||||||
|
|
||||||
|
It is possible to indicate a stop of the sequence within the flow (usually used to model exceptions).
|
||||||
|
|
||||||
|
This is done by the notation
|
||||||
|
|
||||||
|
try {
|
||||||
|
...statements...
|
||||||
|
} catch {
|
||||||
|
...statements...
|
||||||
|
} finally {
|
||||||
|
...statements...
|
||||||
|
}
|
||||||
|
|
||||||
|
See the example below:
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
try {
|
||||||
|
Consumer->API: Book something
|
||||||
|
API->BookingService: Start booking process
|
||||||
|
} catch {
|
||||||
|
API->Consumer: show failure
|
||||||
|
} finally {
|
||||||
|
API->BookingService: rollback status
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
zenuml
|
||||||
|
try {
|
||||||
|
Consumer->API: Book something
|
||||||
|
API->BookingService: Start booking process
|
||||||
|
} catch {
|
||||||
|
API->Consumer: show failure
|
||||||
|
} finally {
|
||||||
|
API->BookingService: rollback status
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Integrating with your library/website.
|
||||||
|
|
||||||
|
Zenuml uses the experimental lazy loading & async rendering features which could change in the future.
|
||||||
|
|
||||||
|
You can use this method to add mermaid including the zenuml diagram to a web page:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script type="module">
|
||||||
|
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
|
||||||
|
import zenuml from 'https://cdn.jsdelivr.net/npm/@mermaid-js/mermaid-zenuml@0.1.0/dist/mermaid-zenuml.esm.min.mjs';
|
||||||
|
await mermaid.registerExternalDiagrams([zenuml]);
|
||||||
|
</script>
|
||||||
|
```
|
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "mermaid-monorepo",
|
"name": "mermaid-monorepo",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "10.2.2",
|
"version": "10.2.0",
|
||||||
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
|
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"packageManager": "pnpm@8.5.1",
|
"packageManager": "pnpm@8.5.1",
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
"build:vite": "ts-node-esm --transpileOnly .vite/build.ts",
|
"build:vite": "ts-node-esm --transpileOnly .vite/build.ts",
|
||||||
"build:mermaid": "pnpm build:vite --mermaid",
|
"build:mermaid": "pnpm build:vite --mermaid",
|
||||||
"build:viz": "pnpm build:mermaid --visualize",
|
"build:viz": "pnpm build:mermaid --visualize",
|
||||||
"build:types": "tsc -p ./packages/mermaid/tsconfig.json --emitDeclarationOnly && tsc -p ./packages/mermaid-example-diagram/tsconfig.json --emitDeclarationOnly",
|
"build:types": "tsc -p ./packages/mermaid/tsconfig.json --emitDeclarationOnly && tsc -p ./packages/mermaid-zenuml/tsconfig.json --emitDeclarationOnly && tsc -p ./packages/mermaid-example-diagram/tsconfig.json --emitDeclarationOnly",
|
||||||
"build:watch": "pnpm build:vite --watch",
|
"build:watch": "pnpm build:vite --watch",
|
||||||
"build": "pnpm run -r clean && pnpm build:types && pnpm build:vite",
|
"build": "pnpm run -r clean && pnpm build:types && pnpm build:vite",
|
||||||
"dev": "concurrently \"pnpm build:vite --watch\" \"ts-node-esm .vite/server.ts\"",
|
"dev": "concurrently \"pnpm build:vite --watch\" \"ts-node-esm .vite/server.ts\"",
|
||||||
|
1
packages/mermaid-zenuml/README.md
Symbolic link
1
packages/mermaid-zenuml/README.md
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../mermaid/src/docs/syntax/zenuml.md
|
47
packages/mermaid-zenuml/package.json
Normal file
47
packages/mermaid-zenuml/package.json
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"name": "@mermaid-js/mermaid-zenuml",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "MermaidJS plugin for ZenUML integration",
|
||||||
|
"module": "dist/mermaid-zenuml.core.mjs",
|
||||||
|
"types": "dist/detector.d.ts",
|
||||||
|
"type": "module",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"import": "./dist/mermaid-zenuml.core.mjs",
|
||||||
|
"types": "./dist/detector.d.ts"
|
||||||
|
},
|
||||||
|
"./*": "./*"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"diagram",
|
||||||
|
"markdown",
|
||||||
|
"zenuml",
|
||||||
|
"mermaid"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"prepublishOnly": "pnpm -w run build"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/mermaid-js/mermaid",
|
||||||
|
"directory": "packages/mermaid-zenuml"
|
||||||
|
},
|
||||||
|
"contributors": [
|
||||||
|
"Peng Xiao (https://github.com/MrCoder)",
|
||||||
|
"Sidharth Vinod (https://sidharth.dev)",
|
||||||
|
"Dong Cai (https://github.com/dontry)"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@zenuml/core": "^3.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"mermaid": "workspace:^"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"mermaid": "workspace:>=10.0.0"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
]
|
||||||
|
}
|
21
packages/mermaid-zenuml/src/detector.ts
Normal file
21
packages/mermaid-zenuml/src/detector.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import type { ExternalDiagramDefinition } from 'mermaid';
|
||||||
|
|
||||||
|
const id = 'zenuml';
|
||||||
|
const regexp = /^\s*zenuml/;
|
||||||
|
|
||||||
|
const detector = (txt: string) => {
|
||||||
|
return txt.match(regexp) !== null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const loader = async () => {
|
||||||
|
const { diagram } = await import('./zenuml-definition.js');
|
||||||
|
return { id, diagram };
|
||||||
|
};
|
||||||
|
|
||||||
|
const plugin: ExternalDiagramDefinition = {
|
||||||
|
id,
|
||||||
|
detector,
|
||||||
|
loader,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default plugin;
|
58
packages/mermaid-zenuml/src/mermaidUtils.ts
Normal file
58
packages/mermaid-zenuml/src/mermaidUtils.ts
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import type { MermaidConfig } from 'mermaid';
|
||||||
|
|
||||||
|
const warning = (s: string) => {
|
||||||
|
// Todo remove debug code
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error('Log function was called before initialization', s);
|
||||||
|
};
|
||||||
|
|
||||||
|
export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';
|
||||||
|
|
||||||
|
export const LEVELS: Record<LogLevel, number> = {
|
||||||
|
trace: 0,
|
||||||
|
debug: 1,
|
||||||
|
info: 2,
|
||||||
|
warn: 3,
|
||||||
|
error: 4,
|
||||||
|
fatal: 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const log: Record<keyof typeof LEVELS, typeof console.log> = {
|
||||||
|
trace: warning,
|
||||||
|
debug: warning,
|
||||||
|
info: warning,
|
||||||
|
warn: warning,
|
||||||
|
error: warning,
|
||||||
|
fatal: warning,
|
||||||
|
};
|
||||||
|
|
||||||
|
export let setLogLevel: (level: keyof typeof LEVELS | number | string) => void;
|
||||||
|
export let getConfig: () => MermaidConfig;
|
||||||
|
export let sanitizeText: (str: string) => string;
|
||||||
|
// eslint-disable @typescript-eslint/no-explicit-any
|
||||||
|
export let setupGraphViewbox: (
|
||||||
|
graph: any,
|
||||||
|
svgElem: any,
|
||||||
|
padding: any,
|
||||||
|
useMaxWidth: boolean
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
export const injectUtils = (
|
||||||
|
_log: Record<keyof typeof LEVELS, typeof console.log>,
|
||||||
|
_setLogLevel: any,
|
||||||
|
_getConfig: any,
|
||||||
|
_sanitizeText: any,
|
||||||
|
_setupGraphViewbox: any
|
||||||
|
) => {
|
||||||
|
_log.info('Mermaid utils injected');
|
||||||
|
log.trace = _log.trace;
|
||||||
|
log.debug = _log.debug;
|
||||||
|
log.info = _log.info;
|
||||||
|
log.warn = _log.warn;
|
||||||
|
log.error = _log.error;
|
||||||
|
log.fatal = _log.fatal;
|
||||||
|
setLogLevel = _setLogLevel;
|
||||||
|
getConfig = _getConfig;
|
||||||
|
sanitizeText = _sanitizeText;
|
||||||
|
setupGraphViewbox = _setupGraphViewbox;
|
||||||
|
};
|
12
packages/mermaid-zenuml/src/parser.ts
Normal file
12
packages/mermaid-zenuml/src/parser.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* ZenUML manage parsing internally. It uses Antlr4 to parse the DSL.
|
||||||
|
* The parser is defined in https://github.com/ZenUml/vue-sequence/blob/main/src/parser/index.js
|
||||||
|
*
|
||||||
|
* This is a dummy parser that satisfies the mermaid API logic.
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
parser: { yy: {} },
|
||||||
|
parse: () => {
|
||||||
|
// no op
|
||||||
|
},
|
||||||
|
};
|
17
packages/mermaid-zenuml/src/zenuml-definition.ts
Normal file
17
packages/mermaid-zenuml/src/zenuml-definition.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { injectUtils } from './mermaidUtils.js';
|
||||||
|
import parser from './parser.js';
|
||||||
|
import renderer from './zenumlRenderer.js';
|
||||||
|
|
||||||
|
export const diagram = {
|
||||||
|
db: {
|
||||||
|
clear: () => {
|
||||||
|
// no-op
|
||||||
|
},
|
||||||
|
},
|
||||||
|
renderer,
|
||||||
|
parser,
|
||||||
|
styles: () => {
|
||||||
|
// no-op
|
||||||
|
},
|
||||||
|
injectUtils,
|
||||||
|
};
|
68
packages/mermaid-zenuml/src/zenumlRenderer.ts
Normal file
68
packages/mermaid-zenuml/src/zenumlRenderer.ts
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import { getConfig, log } from './mermaidUtils.js';
|
||||||
|
import ZenUml from '@zenuml/core';
|
||||||
|
|
||||||
|
const regexp = /^\s*zenuml/;
|
||||||
|
|
||||||
|
// Create a Zen UML container outside the svg first for rendering, otherwise the Zen UML diagram cannot be rendered properly
|
||||||
|
function createTemporaryZenumlContainer(id: string) {
|
||||||
|
const container = document.createElement('div');
|
||||||
|
container.id = `container-${id}`;
|
||||||
|
container.style.display = 'flex';
|
||||||
|
container.innerHTML = `<div id="zenUMLApp-${id}"></div>`;
|
||||||
|
const app = container.querySelector(`#zenUMLApp-${id}`) as HTMLElement;
|
||||||
|
return { container, app };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a foreignObject to wrap the Zen UML container in the svg
|
||||||
|
function createForeignObject(id: string) {
|
||||||
|
const foreignObject = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
|
||||||
|
foreignObject.setAttribute('x', '0');
|
||||||
|
foreignObject.setAttribute('y', '0');
|
||||||
|
foreignObject.setAttribute('width', '100%');
|
||||||
|
foreignObject.setAttribute('height', '100%');
|
||||||
|
const { container, app } = createTemporaryZenumlContainer(id);
|
||||||
|
foreignObject.appendChild(container);
|
||||||
|
return { foreignObject, container, app };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws a Zen UML 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¨
|
||||||
|
*/
|
||||||
|
export const draw = async function (text: string, id: string) {
|
||||||
|
log.info('draw with Zen UML renderer', ZenUml);
|
||||||
|
|
||||||
|
text = text.replace(regexp, '');
|
||||||
|
const { securityLevel } = getConfig();
|
||||||
|
// Handle root and Document for when rendering in sandbox mode
|
||||||
|
let sandboxElement: HTMLIFrameElement | null = null;
|
||||||
|
if (securityLevel === 'sandbox') {
|
||||||
|
sandboxElement = document.getElementById('i' + id) as HTMLIFrameElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
const root = securityLevel === 'sandbox' ? sandboxElement?.contentWindow?.document : document;
|
||||||
|
|
||||||
|
const svgContainer = root?.querySelector(`svg#${id}`);
|
||||||
|
|
||||||
|
if (!root || !svgContainer) {
|
||||||
|
log.error('Cannot find root or svgContainer');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { foreignObject, container, app } = createForeignObject(id);
|
||||||
|
svgContainer.appendChild(foreignObject);
|
||||||
|
// @ts-expect-error @zenuml/core@3.0.0 exports the wrong type for ZenUml
|
||||||
|
const zenuml = new ZenUml(app);
|
||||||
|
// default is a theme name. More themes to be added and will be configurable in the future
|
||||||
|
await zenuml.render(text, 'theme-mermaid');
|
||||||
|
|
||||||
|
const { width, height } = window.getComputedStyle(container);
|
||||||
|
log.debug('zenuml diagram size', width, height);
|
||||||
|
svgContainer.setAttribute('style', `width: ${width}; height: ${height};`);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
draw,
|
||||||
|
};
|
9
packages/mermaid-zenuml/tsconfig.json
Normal file
9
packages/mermaid-zenuml/tsconfig.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"rootDir": "./src",
|
||||||
|
"outDir": "./dist"
|
||||||
|
},
|
||||||
|
"include": ["./src/**/*.ts"],
|
||||||
|
"typeRoots": ["./src/types"]
|
||||||
|
}
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mermaid",
|
"name": "mermaid",
|
||||||
"version": "10.2.2",
|
"version": "10.2.0",
|
||||||
"description": "Markdown-ish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
|
"description": "Markdown-ish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"module": "./dist/mermaid.core.mjs",
|
"module": "./dist/mermaid.core.mjs",
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
"docs:build": "rimraf ../../docs && pnpm docs:spellcheck && pnpm docs:code && ts-node-esm src/docs.mts",
|
"docs:build": "rimraf ../../docs && pnpm docs:spellcheck && pnpm docs:code && ts-node-esm src/docs.mts",
|
||||||
"docs:verify": "pnpm docs:spellcheck && pnpm docs:code && ts-node-esm src/docs.mts --verify",
|
"docs:verify": "pnpm docs:spellcheck && pnpm docs:code && ts-node-esm src/docs.mts --verify",
|
||||||
"docs:pre:vitepress": "rimraf src/vitepress && pnpm docs:code && ts-node-esm src/docs.mts --vitepress",
|
"docs:pre:vitepress": "rimraf src/vitepress && pnpm docs:code && ts-node-esm src/docs.mts --vitepress",
|
||||||
"docs:build:vitepress": "pnpm docs:pre:vitepress && (cd src/vitepress && pnpm --filter ./ install --no-frozen-lockfile --ignore-scripts && pnpm run build) && cpy --flat src/docs/landing/ ./src/vitepress/.vitepress/dist/landing",
|
"docs:build:vitepress": "pnpm docs:pre:vitepress && (cd src/vitepress && pnpm --filter ./ install --no-frozen-lockfile && pnpm run build) && cpy --flat src/docs/landing/ ./src/vitepress/.vitepress/dist/landing",
|
||||||
"docs:dev": "pnpm docs:pre:vitepress && concurrently \"pnpm --filter ./ src/vitepress dev\" \"ts-node-esm src/docs.mts --watch --vitepress\"",
|
"docs:dev": "pnpm docs:pre:vitepress && concurrently \"pnpm --filter ./ src/vitepress dev\" \"ts-node-esm src/docs.mts --watch --vitepress\"",
|
||||||
"docs:serve": "pnpm docs:build:vitepress && vitepress serve src/vitepress",
|
"docs:serve": "pnpm docs:build:vitepress && vitepress serve src/vitepress",
|
||||||
"docs:spellcheck": "cspell --config ../../cSpell.json \"src/docs/**/*.md\"",
|
"docs:spellcheck": "cspell --config ../../cSpell.json \"src/docs/**/*.md\"",
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
import { sanitizeUrl } from '@braintree/sanitize-url';
|
import { sanitizeUrl } from '@braintree/sanitize-url';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs/esm/index.js';
|
||||||
import dayjsIsoWeek from 'dayjs/plugin/isoWeek.js';
|
import dayjsIsoWeek from 'dayjs/esm/plugin/isoWeek/index.js';
|
||||||
import dayjsCustomParseFormat from 'dayjs/plugin/customParseFormat.js';
|
import dayjsCustomParseFormat from 'dayjs/esm/plugin/customParseFormat/index.js';
|
||||||
import dayjsAdvancedFormat from 'dayjs/plugin/advancedFormat.js';
|
import dayjsAdvancedFormat from 'dayjs/esm/plugin/advancedFormat/index.js';
|
||||||
import { log } from '../../logger.js';
|
import { log } from '../../logger.js';
|
||||||
import * as configApi from '../../config.js';
|
import * as configApi from '../../config.js';
|
||||||
import utils from '../../utils.js';
|
import utils from '../../utils.js';
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
// @ts-nocheck TODO: Fix TS
|
// @ts-nocheck TODO: Fix TS
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs/esm/index.js';
|
||||||
import ganttDb from './ganttDb.js';
|
import ganttDb from './ganttDb.js';
|
||||||
import { convert } from '../../tests/util.js';
|
import { convert } from '../../tests/util.js';
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs/esm/index.js';
|
||||||
import { log } from '../../logger.js';
|
import { log } from '../../logger.js';
|
||||||
import {
|
import {
|
||||||
select,
|
select,
|
||||||
|
@@ -119,10 +119,10 @@ points
|
|||||||
|
|
||||||
axisDetails
|
axisDetails
|
||||||
: X-AXIS text AXIS-TEXT-DELIMITER text {yy.setXAxisLeftText($2); yy.setXAxisRightText($4);}
|
: X-AXIS text AXIS-TEXT-DELIMITER text {yy.setXAxisLeftText($2); yy.setXAxisRightText($4);}
|
||||||
| X-AXIS text AXIS-TEXT-DELIMITER {$2.text += $3; yy.setXAxisLeftText($2);}
|
| X-AXIS text AXIS-TEXT-DELIMITER {$2.text += " ⟶ "; yy.setXAxisLeftText($2);}
|
||||||
| X-AXIS text {yy.setXAxisLeftText($2);}
|
| X-AXIS text {yy.setXAxisLeftText($2);}
|
||||||
| Y-AXIS text AXIS-TEXT-DELIMITER text {yy.setYAxisBottomText($2); yy.setYAxisTopText($4);}
|
| Y-AXIS text AXIS-TEXT-DELIMITER text {yy.setYAxisBottomText($2); yy.setYAxisTopText($4);}
|
||||||
| Y-AXIS text AXIS-TEXT-DELIMITER {$2.text += $3; yy.setYAxisBottomText($2);}
|
| Y-AXIS text AXIS-TEXT-DELIMITER {$2.text += " ⟶ "; yy.setYAxisBottomText($2);}
|
||||||
| Y-AXIS text {yy.setYAxisBottomText($2);}
|
| Y-AXIS text {yy.setYAxisBottomText($2);}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@@ -93,7 +93,7 @@ describe('Testing quadrantChart jison file', () => {
|
|||||||
str = 'quadrantChart\n x-AxIs "Urgent(* +=[❤" --> ';
|
str = 'quadrantChart\n x-AxIs "Urgent(* +=[❤" --> ';
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(mockDB.setXAxisLeftText).toHaveBeenCalledWith({
|
expect(mockDB.setXAxisLeftText).toHaveBeenCalledWith({
|
||||||
text: 'Urgent(* +=[❤ --> ',
|
text: 'Urgent(* +=[❤ ⟶ ',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
});
|
});
|
||||||
expect(mockDB.setXAxisRightText).not.toHaveBeenCalled();
|
expect(mockDB.setXAxisRightText).not.toHaveBeenCalled();
|
||||||
@@ -131,7 +131,7 @@ describe('Testing quadrantChart jison file', () => {
|
|||||||
str = 'quadrantChart\n y-AxIs "Urgent(* +=[❤" --> ';
|
str = 'quadrantChart\n y-AxIs "Urgent(* +=[❤" --> ';
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(mockDB.setYAxisBottomText).toHaveBeenCalledWith({
|
expect(mockDB.setYAxisBottomText).toHaveBeenCalledWith({
|
||||||
text: 'Urgent(* +=[❤ --> ',
|
text: 'Urgent(* +=[❤ ⟶ ',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
});
|
});
|
||||||
expect(mockDB.setYAxisTopText).not.toHaveBeenCalled();
|
expect(mockDB.setYAxisTopText).not.toHaveBeenCalled();
|
||||||
|
@@ -5,12 +5,12 @@ import { contributors } from '../contributors';
|
|||||||
<template>
|
<template>
|
||||||
<div flex="~ wrap gap2" justify-center>
|
<div flex="~ wrap gap2" justify-center>
|
||||||
<a
|
<a
|
||||||
v-for="{ username, avatar } of contributors"
|
v-for="{ name, avatar } of contributors"
|
||||||
:key="username"
|
:key="name"
|
||||||
:href="`https://github.com/${username}`"
|
:href="`https://github.com/${name}`"
|
||||||
m-0
|
m-0
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
:aria-label="`${username} on GitHub`"
|
:aria-label="`${name} on GitHub`"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
@@ -20,7 +20,7 @@ import { contributors } from '../contributors';
|
|||||||
rounded-full
|
rounded-full
|
||||||
h-12
|
h-12
|
||||||
w-12
|
w-12
|
||||||
:alt="`${username}'s avatar`"
|
:alt="`${name}'s avatar`"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -121,6 +121,7 @@ function sidebarSyntax() {
|
|||||||
{ text: 'C4C Diagram (Context) Diagram 🦺⚠️', link: '/syntax/c4c' },
|
{ text: 'C4C Diagram (Context) Diagram 🦺⚠️', link: '/syntax/c4c' },
|
||||||
{ text: 'Mindmaps 🔥', link: '/syntax/mindmap' },
|
{ text: 'Mindmaps 🔥', link: '/syntax/mindmap' },
|
||||||
{ text: 'Timeline 🔥', link: '/syntax/timeline' },
|
{ text: 'Timeline 🔥', link: '/syntax/timeline' },
|
||||||
|
{ text: 'Zenuml 🔥', link: '/syntax/zenuml' },
|
||||||
{ text: 'Other Examples', link: '/syntax/examples' },
|
{ text: 'Other Examples', link: '/syntax/examples' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable no-console */
|
|
||||||
import { mkdir, writeFile, readFile } from 'node:fs/promises';
|
import { mkdir, writeFile, readFile } from 'node:fs/promises';
|
||||||
import { existsSync } from 'node:fs';
|
import { existsSync } from 'node:fs';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
@@ -13,23 +12,22 @@ async function download(url: string, fileName: URL) {
|
|||||||
if (existsSync(fileName)) {
|
if (existsSync(fileName)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log('downloading', url);
|
// eslint-disable-next-line no-console
|
||||||
|
console.log('downloading', fileName);
|
||||||
try {
|
try {
|
||||||
const image = await fetch(url);
|
const image = await fetch(url);
|
||||||
await writeFile(fileName, Buffer.from(await image.arrayBuffer()));
|
await writeFile(fileName, Buffer.from(await image.arrayBuffer()));
|
||||||
} catch (error) {
|
} catch {}
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchAvatars() {
|
async function fetchAvatars() {
|
||||||
await mkdir(fileURLToPath(new URL(getAvatarPath('none'))).replace('none.png', ''), {
|
await mkdir(fileURLToPath(new URL('..', getAvatarPath('none'))), { recursive: true });
|
||||||
recursive: true,
|
|
||||||
});
|
|
||||||
contributors = JSON.parse(await readFile(pathContributors, { encoding: 'utf-8' }));
|
contributors = JSON.parse(await readFile(pathContributors, { encoding: 'utf-8' }));
|
||||||
for (const name of contributors) {
|
await Promise.allSettled(
|
||||||
await download(`https://github.com/${name}.png?size=100`, getAvatarPath(name));
|
contributors.map((name) =>
|
||||||
}
|
download(`https://github.com/${name}.png?size=100`, getAvatarPath(name))
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchAvatars();
|
fetchAvatars();
|
||||||
|
@@ -23,8 +23,9 @@ async function fetchContributors() {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
data = await response.json();
|
data = await response.json();
|
||||||
|
console.log(response.status, response.statusText);
|
||||||
|
console.log(data);
|
||||||
collaborators.push(...data.map((i) => i.login));
|
collaborators.push(...data.map((i) => i.login));
|
||||||
console.log(`Fetched page ${page}`);
|
|
||||||
page++;
|
page++;
|
||||||
} while (data.length === 100);
|
} while (data.length === 100);
|
||||||
return collaborators.filter((name) => !name.includes('[bot]'));
|
return collaborators.filter((name) => !name.includes('[bot]'));
|
||||||
|
@@ -1,6 +1,10 @@
|
|||||||
import mermaid, { type MermaidConfig } from 'mermaid';
|
import mermaid, { type MermaidConfig } from 'mermaid';
|
||||||
|
import zenuml from '../../../../../mermaid-zenuml/dist/mermaid-zenuml.core.mjs';
|
||||||
|
|
||||||
|
const init = mermaid.registerExternalDiagrams([zenuml]);
|
||||||
|
|
||||||
export const render = async (id: string, code: string, config: MermaidConfig): Promise<string> => {
|
export const render = async (id: string, code: string, config: MermaidConfig): Promise<string> => {
|
||||||
|
await init;
|
||||||
mermaid.initialize(config);
|
mermaid.initialize(config);
|
||||||
const { svg } = await mermaid.render(id, code);
|
const { svg } = await mermaid.render(id, code);
|
||||||
return svg;
|
return svg;
|
||||||
|
@@ -10,6 +10,7 @@ They also serve as proof of concept, for the variety of things that can be built
|
|||||||
- [Using code blocks](https://github.blog/2022-02-14-include-diagrams-markdown-files-mermaid/) (**Native support**)
|
- [Using code blocks](https://github.blog/2022-02-14-include-diagrams-markdown-files-mermaid/) (**Native support**)
|
||||||
- [GitHub action: Compile mermaid to image](https://github.com/neenjaw/compile-mermaid-markdown-action)
|
- [GitHub action: Compile mermaid to image](https://github.com/neenjaw/compile-mermaid-markdown-action)
|
||||||
- [svg-generator](https://github.com/SimonKenyonShepard/mermaidjs-github-svg-generator)
|
- [svg-generator](https://github.com/SimonKenyonShepard/mermaidjs-github-svg-generator)
|
||||||
|
- [GitHub Writer](https://github.com/ckeditor/github-writer)
|
||||||
- [GitLab](https://docs.gitlab.com/ee/user/markdown.html#diagrams-and-flowcharts) (**Native support**)
|
- [GitLab](https://docs.gitlab.com/ee/user/markdown.html#diagrams-and-flowcharts) (**Native support**)
|
||||||
- [Gitea](https://gitea.io) (**Native support**)
|
- [Gitea](https://gitea.io) (**Native support**)
|
||||||
- [Azure Devops](https://docs.microsoft.com/en-us/azure/devops/project/wiki/wiki-markdown-guidance?view=azure-devops#add-mermaid-diagrams-to-a-wiki-page) (**Native support**)
|
- [Azure Devops](https://docs.microsoft.com/en-us/azure/devops/project/wiki/wiki-markdown-guidance?view=azure-devops#add-mermaid-diagrams-to-a-wiki-page) (**Native support**)
|
||||||
@@ -136,6 +137,8 @@ They also serve as proof of concept, for the variety of things that can be built
|
|||||||
- [Named block =Diagram](https://github.com/zag/podlite/tree/main/packages/podlite-diagrams)
|
- [Named block =Diagram](https://github.com/zag/podlite/tree/main/packages/podlite-diagrams)
|
||||||
- [GNU Nano](https://www.nano-editor.org/)
|
- [GNU Nano](https://www.nano-editor.org/)
|
||||||
- [Nano Mermaid](https://github.com/Yash-Singh1/nano-mermaid)
|
- [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)
|
||||||
|
|
||||||
## Document Generation
|
## Document Generation
|
||||||
|
|
||||||
|
@@ -30,7 +30,7 @@
|
|||||||
"unplugin-vue-components": "^0.24.1",
|
"unplugin-vue-components": "^0.24.1",
|
||||||
"vite": "^4.3.3",
|
"vite": "^4.3.3",
|
||||||
"vite-plugin-pwa": "^0.15.0",
|
"vite-plugin-pwa": "^0.15.0",
|
||||||
"vitepress": "1.0.0-alpha.76",
|
"vitepress": "1.0.0-beta.1",
|
||||||
"workbox-window": "^6.5.4"
|
"workbox-window": "^6.5.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 255 KiB |
@@ -23,6 +23,10 @@ quadrantChart
|
|||||||
|
|
||||||
## Syntax
|
## Syntax
|
||||||
|
|
||||||
|
```note
|
||||||
|
In place of `<text>` you can use text like `this is a sample text` or inside **double quotes** like `"This type of text may contain unicode like ❤"`.
|
||||||
|
```
|
||||||
|
|
||||||
```note
|
```note
|
||||||
If there is no points available in the chart both **axis** text and **quadrant** will be rendered in the center of the respective quadrant.
|
If there is no points available in the chart both **axis** text and **quadrant** will be rendered in the center of the respective quadrant.
|
||||||
If there are points **x-axis** labels will rendered from left of the respective quadrant also they will be displayed in bottom of the chart, and **y-axis** lables will be rendered in bottom of the respective quadrant, the quadrant text will render at top of the respective quadrant.
|
If there are points **x-axis** labels will rendered from left of the respective quadrant also they will be displayed in bottom of the chart, and **y-axis** lables will be rendered in bottom of the respective quadrant, the quadrant text will render at top of the respective quadrant.
|
||||||
@@ -130,7 +134,7 @@ Points are used to plot a circle inside the quadrantChart. The syntax is `<text>
|
|||||||
%%{init: {"quadrantChart": {"chartWidth": 400, "chartHeight": 400}, "themeVariables": {"quadrant1TextFill": "#ff0000"} }}%%
|
%%{init: {"quadrantChart": {"chartWidth": 400, "chartHeight": 400}, "themeVariables": {"quadrant1TextFill": "#ff0000"} }}%%
|
||||||
quadrantChart
|
quadrantChart
|
||||||
x-axis Urgent --> Not Urgent
|
x-axis Urgent --> Not Urgent
|
||||||
y-axis Not Important --> "Important ❤"
|
y-axis Not Important --> important
|
||||||
quadrant-1 Plan
|
quadrant-1 Plan
|
||||||
quadrant-2 Do
|
quadrant-2 Do
|
||||||
quadrant-3 Deligate
|
quadrant-3 Deligate
|
||||||
|
314
packages/mermaid/src/docs/syntax/zenuml.md
Normal file
314
packages/mermaid/src/docs/syntax/zenuml.md
Normal file
@@ -0,0 +1,314 @@
|
|||||||
|
# ZenUML
|
||||||
|
|
||||||
|
> A Sequence diagram is an interaction diagram that shows how processes operate with one another and in what order.
|
||||||
|
|
||||||
|
Mermaid can render sequence diagrams with [ZenUML](https://zenuml.com). Note that ZenUML uses a different
|
||||||
|
syntax than the original Sequence Diagram in mermaid.
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
title Demo
|
||||||
|
Alice->John: Hello John, how are you?
|
||||||
|
John->Alice: Great!
|
||||||
|
Alice->John: See you later!
|
||||||
|
```
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
### Participants
|
||||||
|
|
||||||
|
The participants can be defined implicitly as in the first example on this page. The participants or actors are
|
||||||
|
rendered in order of appearance in the diagram source text. Sometimes you might want to show the participants in a
|
||||||
|
different order than how they appear in the first message. It is possible to specify the actor's order of
|
||||||
|
appearance by doing the following:
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
title Declare participant (optional)
|
||||||
|
Bob
|
||||||
|
Alice
|
||||||
|
Alice->Bob: Hi Bob
|
||||||
|
Bob->Alice: Hi Alice
|
||||||
|
```
|
||||||
|
|
||||||
|
### Annotators
|
||||||
|
|
||||||
|
If you specifically want to use symbols instead of just rectangles with text you can do so by using the annotator syntax to declare participants as per below.
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
title Annotators
|
||||||
|
@Actor Alice
|
||||||
|
@Database Bob
|
||||||
|
Alice->Bob: Hi Bob
|
||||||
|
Bob->Alice: Hi Alice
|
||||||
|
```
|
||||||
|
|
||||||
|
Here are the available annotators:
|
||||||
|

|
||||||
|
|
||||||
|
### Aliases
|
||||||
|
|
||||||
|
The participants can have a convenient identifier and a descriptive label.
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
title Aliases
|
||||||
|
A as Alice
|
||||||
|
J as John
|
||||||
|
A->J: Hello John, how are you?
|
||||||
|
J->A: Great!
|
||||||
|
```
|
||||||
|
|
||||||
|
## Messages
|
||||||
|
|
||||||
|
Messages can be one of:
|
||||||
|
|
||||||
|
1. Sync message
|
||||||
|
2. Async message
|
||||||
|
3. Creation message
|
||||||
|
4. Reply message
|
||||||
|
|
||||||
|
### Sync message
|
||||||
|
|
||||||
|
You can think of a sync (blocking) method in a programming language.
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
title Sync message
|
||||||
|
A.SyncMessage
|
||||||
|
A.SyncMessage(with, parameters) {
|
||||||
|
B.nestedSyncMessage()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Async message
|
||||||
|
|
||||||
|
You can think of an async (non-blocking) method in a programming language.
|
||||||
|
Fire an event and forget about it.
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
title Async message
|
||||||
|
Alice->Bob: How are you?
|
||||||
|
```
|
||||||
|
|
||||||
|
### Creation message
|
||||||
|
|
||||||
|
We use `new` keyword to create an object.
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
new A1
|
||||||
|
new A2(with, parameters)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reply message
|
||||||
|
|
||||||
|
There are three ways to express a reply message:
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
// 1. assign a variable from a sync message.
|
||||||
|
a = A.SyncMessage()
|
||||||
|
|
||||||
|
// 1.1. optionally give the variable a type
|
||||||
|
SomeType a = A.SyncMessage()
|
||||||
|
|
||||||
|
// 2. use return keyword
|
||||||
|
A.SyncMessage() {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. use @return or @reply annotator on an async message
|
||||||
|
@return
|
||||||
|
A->B: result
|
||||||
|
```
|
||||||
|
|
||||||
|
The third way `@return` is rarely used, but it is useful when you want to return to one level up.
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
title Reply message
|
||||||
|
Client->A.method() {
|
||||||
|
B.method() {
|
||||||
|
if(condition) {
|
||||||
|
return x1
|
||||||
|
// return early
|
||||||
|
@return
|
||||||
|
A->Client: x11
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return x2
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Nesting
|
||||||
|
|
||||||
|
Sync messages and Creation messages are naturally nestable with `{}`.
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
A.method() {
|
||||||
|
B.nested_sync_method()
|
||||||
|
B->C: nested async message
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Comments
|
||||||
|
|
||||||
|
It is possible to add comments to a sequence diagram with `// comment` syntax.
|
||||||
|
Comments will be rendered above the messages or fragments. Comments on other places
|
||||||
|
are ignored. Markdown is supported.
|
||||||
|
|
||||||
|
See the example below:
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
// a comment on a participant will not be rendered
|
||||||
|
BookService
|
||||||
|
// a comment on a message.
|
||||||
|
// **Markdown** is supported.
|
||||||
|
BookService.getBook()
|
||||||
|
```
|
||||||
|
|
||||||
|
## Loops
|
||||||
|
|
||||||
|
It is possible to express loops in a ZenUML diagram. This is done by any of the
|
||||||
|
following notations:
|
||||||
|
|
||||||
|
1. while
|
||||||
|
2. for
|
||||||
|
3. forEach, foreach
|
||||||
|
4. loop
|
||||||
|
|
||||||
|
```zenuml
|
||||||
|
while(condition) {
|
||||||
|
...statements...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See the example below:
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
Alice->John: Hello John, how are you?
|
||||||
|
while(true) {
|
||||||
|
John->Alice: Great!
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Alt
|
||||||
|
|
||||||
|
It is possible to express alternative paths in a sequence diagram. This is done by the notation
|
||||||
|
|
||||||
|
```zenuml
|
||||||
|
if(condition1) {
|
||||||
|
...statements...
|
||||||
|
} else if(condition2) {
|
||||||
|
...statements...
|
||||||
|
} else {
|
||||||
|
...statements...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See the example below:
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
Alice->Bob: Hello Bob, how are you?
|
||||||
|
if(is_sick) {
|
||||||
|
Bob->Alice: Not so good :(
|
||||||
|
} else {
|
||||||
|
Bob->Alice: Feeling fresh like a daisy
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Opt
|
||||||
|
|
||||||
|
It is possible to render an `opt` fragment. This is done by the notation
|
||||||
|
|
||||||
|
```zenuml
|
||||||
|
opt {
|
||||||
|
...statements...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See the example below:
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
Alice->Bob: Hello Bob, how are you?
|
||||||
|
Bob->Alice: Not so good :(
|
||||||
|
opt {
|
||||||
|
Bob->Alice: Thanks for asking
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Parallel
|
||||||
|
|
||||||
|
It is possible to show actions that are happening in parallel.
|
||||||
|
|
||||||
|
This is done by the notation
|
||||||
|
|
||||||
|
```zenuml
|
||||||
|
par {
|
||||||
|
statement1
|
||||||
|
statement2
|
||||||
|
statement3
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See the example below:
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
par {
|
||||||
|
Alice->Bob: Hello guys!
|
||||||
|
Alice->John: Hello guys!
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Try/Catch/Finally (Break)
|
||||||
|
|
||||||
|
It is possible to indicate a stop of the sequence within the flow (usually used to model exceptions).
|
||||||
|
|
||||||
|
This is done by the notation
|
||||||
|
|
||||||
|
```
|
||||||
|
try {
|
||||||
|
...statements...
|
||||||
|
} catch {
|
||||||
|
...statements...
|
||||||
|
} finally {
|
||||||
|
...statements...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See the example below:
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
zenuml
|
||||||
|
try {
|
||||||
|
Consumer->API: Book something
|
||||||
|
API->BookingService: Start booking process
|
||||||
|
} catch {
|
||||||
|
API->Consumer: show failure
|
||||||
|
} finally {
|
||||||
|
API->BookingService: rollback status
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Integrating with your library/website.
|
||||||
|
|
||||||
|
Zenuml uses the experimental lazy loading & async rendering features which could change in the future.
|
||||||
|
|
||||||
|
You can use this method to add mermaid including the zenuml diagram to a web page:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script type="module">
|
||||||
|
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
|
||||||
|
import zenuml from 'https://cdn.jsdelivr.net/npm/@mermaid-js/mermaid-zenuml@0.1.0/dist/mermaid-zenuml.esm.min.mjs';
|
||||||
|
await mermaid.registerExternalDiagrams([zenuml]);
|
||||||
|
</script>
|
||||||
|
```
|
@@ -2,7 +2,7 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
/* eslint-disable @typescript-eslint/no-empty-function */
|
/* eslint-disable @typescript-eslint/no-empty-function */
|
||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs/esm/index.js';
|
||||||
|
|
||||||
export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';
|
export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';
|
||||||
|
|
||||||
|
@@ -263,10 +263,7 @@ export const cleanUpSvgCode = (
|
|||||||
|
|
||||||
// Replace marker-end urls with just the # anchor (remove the preceding part of the URL)
|
// Replace marker-end urls with just the # anchor (remove the preceding part of the URL)
|
||||||
if (!useArrowMarkerUrls && !inSandboxMode) {
|
if (!useArrowMarkerUrls && !inSandboxMode) {
|
||||||
cleanedUpSvg = cleanedUpSvg.replace(
|
cleanedUpSvg = cleanedUpSvg.replace(/marker-end="url\(.*?#/g, 'marker-end="url(#');
|
||||||
/marker-end="url\([\d+./:=?A-Za-z-]*?#/g,
|
|
||||||
'marker-end="url(#'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanedUpSvg = decodeEntities(cleanedUpSvg);
|
cleanedUpSvg = decodeEntities(cleanedUpSvg);
|
||||||
|
@@ -70,7 +70,6 @@ export const setupGraphViewbox = function (graph, svgElem, padding, useMaxWidth)
|
|||||||
height = sHeight + padding * 2;
|
height = sHeight + padding * 2;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// width =
|
|
||||||
log.info(`Calculated bounds: ${width}x${height}`);
|
log.info(`Calculated bounds: ${width}x${height}`);
|
||||||
configureSvgSize(svgElem, height, width, useMaxWidth);
|
configureSvgSize(svgElem, height, width, useMaxWidth);
|
||||||
|
|
||||||
|
538
pnpm-lock.yaml
generated
538
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user