mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-11-07 06:14:14 +01:00
Merge branch 'develop' of https://github.com/mermaid-js/mermaid into feature/2776_katex_math
This commit is contained in:
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -9,10 +9,10 @@ jobs:
|
||||
matrix:
|
||||
node-version: [16.x]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
cache: yarn
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
8
.github/workflows/check-readme-in-sync.yml
vendored
8
.github/workflows/check-readme-in-sync.yml
vendored
@@ -5,19 +5,17 @@ name: Check if README and docs/README are in sync
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- gh-pages
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- gh-pages
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Check for difference in README.md and docs/README.md
|
||||
run: |
|
||||
|
||||
4
.github/workflows/e2e.yml
vendored
4
.github/workflows/e2e.yml
vendored
@@ -9,10 +9,10 @@ jobs:
|
||||
matrix:
|
||||
node-version: [16.x]
|
||||
steps:
|
||||
- uses: actions/checkout@v2.3.4
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
cache: yarn
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
@@ -6,7 +6,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v2.3.4
|
||||
uses: actions/checkout@v3
|
||||
- name: Validate Configuration
|
||||
uses: Yash-Singh1/pr-labeler-config-validator@releases/v0.0.3
|
||||
with:
|
||||
|
||||
@@ -9,9 +9,9 @@ jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
- name: Install Yarn
|
||||
|
||||
4
.github/workflows/release-publish.yml
vendored
4
.github/workflows/release-publish.yml
vendored
@@ -8,11 +8,11 @@ jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2.3.4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: fregante/setup-git-user@v1
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
- name: Install Yarn
|
||||
|
||||
4
.github/workflows/update-browserlist.yml
vendored
4
.github/workflows/update-browserlist.yml
vendored
@@ -8,10 +8,10 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- run: npx browserslist@latest --update-db
|
||||
- name: Commit changes
|
||||
uses: EndBug/add-and-commit@v8.0.2
|
||||
uses: EndBug/add-and-commit@v9
|
||||
with:
|
||||
author_name: ${{ github.actor }}
|
||||
author_email: ${{ github.actor }}@users.noreply.github.com
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -20,3 +20,6 @@ local/
|
||||
_site
|
||||
Gemfile.lock
|
||||
/.vs
|
||||
|
||||
cypress/screenshots/
|
||||
cypress/snapshots/
|
||||
4
.husky/commit-msg
Executable file → Normal file
4
.husky/commit-msg
Executable file → Normal file
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
# . "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npx --no-install commitlint --edit $1
|
||||
# npx --no-install commitlint --edit $1
|
||||
|
||||
0
.husky/pre-commit
Executable file → Normal file
0
.husky/pre-commit
Executable file → Normal file
@@ -114,7 +114,7 @@ Finally, if it is not in the documentation, no one will know about it and then *
|
||||
|
||||
The docs are located in the docs folder and are ofc written in markdown. Just pick the right section and start typing. If you want to add to the structure as in adding a new section and new file you do that via the _navbar.md.
|
||||
|
||||
The changes in master is reflected in http://mermaid-js.github.io/mermaid/ once released the updates are commited to https://mermaid-js.github.io/#/
|
||||
The changes in master is reflected in http://mermaid-js.github.io/mermaid/ once released the updates are committed to https://mermaid-js.github.io/#/
|
||||
|
||||
## Last words
|
||||
|
||||
|
||||
11
README.md
11
README.md
@@ -1,4 +1,4 @@
|
||||
# mermaid [](https://travis-ci.org/mermaid-js/mermaid) [](https://www.npmjs.com/package/mermaid) [](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [](https://percy.io/Mermaid/mermaid)
|
||||
# mermaid [](https://travis-ci.org/mermaid-js/mermaid) [](https://www.npmjs.com/package/mermaid) [](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE)
|
||||
|
||||
English | [简体中文](./README.zh-CN.md)
|
||||
|
||||
@@ -19,10 +19,9 @@ Mermaid is a Javascript based diagramming and charting tool that uses Markdown-i
|
||||
|
||||
Diagramming and documentation costs precious developer time and gets outdated quickly.
|
||||
But not having diagrams or docs ruins productivity and hurts organizational learning.<br/>
|
||||
Mermaid addresses this problem by cutting the time, effort and tooling that is required to create modifiable diagrams and charts, for smarter and more reusable content.
|
||||
The text definitions for Mermaid diagrams allows for it to be updated easily, it can also be made part of production scripts (and other pieces of code).
|
||||
So less time needs to be spent on documenting, as a separate and laborious task. <br/>
|
||||
Even non-programmers can create diagrams through the [Mermaid Live Editor](https://mermaid-js.github.io/mermaid-live-editor/).<br/>
|
||||
Mermaid addresses this problem by enabling users to create easily modifiable diagrams, it can also be made part of production scripts (and other pieces of code).<br/>
|
||||
<br/>
|
||||
Mermaid allows even non-programmers to easily create detailed and diagrams through the [Mermaid Live Editor](https://mermaid-js.github.io/mermaid-live-editor/).<br/>
|
||||
[Tutorials](./docs/Tutorials.md) has video tutorials.
|
||||
Use Mermaid with your favorite applications, check out the list of [Integrations and Usages of Mermaid](./docs/integrations.md).
|
||||
|
||||
@@ -34,7 +33,7 @@ For a more detailed introduction to Mermaid and some of its more basic uses, loo
|
||||
|
||||
## Examples
|
||||
|
||||
__The following are some examples of the diagrams, charts and graphs that can be made using Mermaid and the Markdown-inspired text specific to it. Click here jump into the [text syntax](https://mermaid-js.github.io/mermaid/#/n00b-syntaxReference).__
|
||||
__The following are some examples of the diagrams, charts and graphs that can be made using Mermaid. Click here jump into the [text syntax](https://mermaid-js.github.io/mermaid/#/n00b-syntaxReference).__
|
||||
<!-- <Flowchart> -->
|
||||
|
||||
## Flowchart [<a href="https://mermaid-js.github.io/mermaid/#/flowchart">docs</a> - <a href="https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoiZ3JhcGggVERcbiAgICBBW0hhcmRdIC0tPnxUZXh0fCBCKFJvdW5kKVxuICAgIEIgLS0-IEN7RGVjaXNpb259XG4gICAgQyAtLT58T25lfCBEW1Jlc3VsdCAxXVxuICAgIEMgLS0-fFR3b3wgRVtSZXN1bHQgMl0iLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9fQ">live editor</a>]
|
||||
|
||||
251
README.zh-CN.md
251
README.zh-CN.md
@@ -1,4 +1,4 @@
|
||||
# mermaid [](https://travis-ci.org/mermaid-js/mermaid) [](https://www.npmjs.com/package/mermaid) [](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [](https://percy.io/Mermaid/mermaid)
|
||||
# mermaid [](https://travis-ci.org/mermaid-js/mermaid) [](https://www.npmjs.com/package/mermaid) [](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE)
|
||||
|
||||
[English](./README.md) | 简体中文
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
<!-- <Main description> -->
|
||||
Mermaid 是一个基于 Javascript 的图表绘制工具,通过解析类 Markdown 的文本语法来实现图表的创建和动态修改。Mermaid 诞生的主要目的是让文档的更新能够及时跟上开发进度。
|
||||
|
||||
> Mermaid 致力于解决 Doc-Rot 这个令人头疼的问题。
|
||||
> Doc-Rot 是 Mermaid 致力于解决的一个难题。
|
||||
|
||||
绘图和编写文档花费了开发者宝贵的开发时间,而且随着业务的变更,它很快就会过期。 但是如果缺少了图表或文档,对于生产力和团队新人的业务学习都会产生巨大的阻碍。 <br/>
|
||||
Mermaid 通过减少创建可修改的图表所需要的时间、精力和工具来解决这一难题,从而提高了内容的智能化和可重用性。 作为一个基于文本的绘图工具, Mermaid 天生就易于维护和更新,它也可以作为生产脚本(或其他代码)的一部分,使得文档编写变得更加简单。 有了它之后,开发者可以从维护文档这个与开发割离且麻烦的任务中解放出来。 <br/>
|
||||
即使是从未接触过编程的非专业人员也可以通过 [Mermaid Live Editor](https://mermaid-js.github.io/mermaid-live-editor/)来创建图表。<br/>
|
||||
你可以访问 [教程](./docs/Tutorials.md) 来查看 Live Editor 的视频教程。
|
||||
U也可以查看 [Mermaid 的集成和使用](./docs/integrations.md) 这个清单来检查你的文档工具是否已经集成了 Mermaid 支持。
|
||||
Mermaid 通过允许用户创建便于修改的图表来解决这一难题,它也可以作为生产脚本(或其他代码)的一部分。<br/>
|
||||
<br/>
|
||||
Mermaid 甚至能让非程序员也能通过 [Mermaid Live Editor](https://mermaid-js.github.io/mermaid-live-editor/) 轻松创建详细的图表。<br/>
|
||||
你可以访问 [教程](./docs/Tutorials.md) 来查看 Live Editor 的视频教程,也可以查看 [Mermaid 的集成和使用](./docs/integrations.md) 这个清单来检查你的文档工具是否已经集成了 Mermaid 支持。
|
||||
|
||||
如果想要查看关于 Mermaid 更详细的介绍及基础使用方式,可以查看 [入门指引](./docs/n00b-overview.md) and [用法](./docs/usage.md).
|
||||
|
||||
@@ -31,33 +31,30 @@ U也可以查看 [Mermaid 的集成和使用](./docs/integrations.md) 这个清
|
||||
|
||||
## 示例
|
||||
|
||||
__下面是一些使用 Mermaid 和类 Markdown 语法创建的图表示例。点击 [语法](https://mermaid-js.github.io/mermaid/#/n00b-syntaxReference) 查看详情__
|
||||
__下面是一些可以使用 Mermaid 创建的图表示例。点击 [语法](https://mermaid-js.github.io/mermaid/#/n00b-syntaxReference) 查看详情。__
|
||||
<table>
|
||||
<!-- <Flowchart> -->
|
||||
<tr><td colspan=2 align="center">
|
||||
<b>流程图</b></br>
|
||||
[<a href="https://mermaid-js.github.io/mermaid/#/flowchart">文档</a> - <a href="https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoiZ3JhcGggVERcbiAgICBBW0hhcmRdIC0tPnxUZXh0fCBCKFJvdW5kKVxuICAgIEIgLS0-IEN7RGVjaXNpb259XG4gICAgQyAtLT58T25lfCBEW1Jlc3VsdCAxXVxuICAgIEMgLS0-fFR3b3wgRVtSZXN1bHQgMl0iLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9fQ">live editor</a>]
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td><pre>
|
||||
flowchart TD
|
||||
|
||||
## 流程图 [<a href="https://mermaid-js.github.io/mermaid/#/flowchart">文档</a> - <a href="https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoiZ3JhcGggVERcbiAgICBBW0hhcmRdIC0tPnxUZXh0fCBCKFJvdW5kKVxuICAgIEIgLS0-IEN7RGVjaXNpb259XG4gICAgQyAtLT58T25lfCBEW1Jlc3VsdCAxXVxuICAgIEMgLS0-fFR3b3wgRVtSZXN1bHQgMl0iLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9fQ">live editor</a>]
|
||||
|
||||
```
|
||||
flowchart LR
|
||||
A[Hard] -->|Text| B(Round)
|
||||
B --> C{Decision}
|
||||
C -->|One| D[Result 1]
|
||||
C -->|Two| E[Result 2]
|
||||
</pre></td>
|
||||
<td align="center">
|
||||
<img src="https://raw.githubusercontent.com/mermaid-js/mermaid/master/img/gray-flow.png" />
|
||||
</td>
|
||||
</tr>
|
||||
<!-- </Flowchart> -->
|
||||
<!-- <Sequence> -->
|
||||
<tr><td colspan=2 align="center">
|
||||
<b>时序图</b><br />
|
||||
[<a href="https://mermaid-js.github.io/mermaid/#/sequenceDiagram">文档</a> - <a href="https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoic2VxdWVuY2VEaWFncmFtXG5BbGljZS0-PkpvaG46IEhlbGxvIEpvaG4sIGhvdyBhcmUgeW91P1xubG9vcCBIZWFsdGhjaGVja1xuICAgIEpvaG4tPj5Kb2huOiBGaWdodCBhZ2FpbnN0IGh5cG9jaG9uZHJpYVxuZW5kXG5Ob3RlIHJpZ2h0IG9mIEpvaG46IFJhdGlvbmFsIHRob3VnaHRzIVxuSm9obi0tPj5BbGljZTogR3JlYXQhXG5Kb2huLT4-Qm9iOiBIb3cgYWJvdXQgeW91P1xuQm9iLS0-PkpvaG46IEpvbGx5IGdvb2QhIiwibWVybWFpZCI6eyJ0aGVtZSI6ImRlZmF1bHQifX0">live editor</a>]
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td><pre>
|
||||
```
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A[Hard] -->|Text| B(Round)
|
||||
B --> C{Decision}
|
||||
C -->|One| D[Result 1]
|
||||
C -->|Two| E[Result 2]
|
||||
```
|
||||
|
||||
## 时序图 [<a href="https://mermaid-js.github.io/mermaid/#/sequenceDiagram">文档</a> - <a href="https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoic2VxdWVuY2VEaWFncmFtXG5BbGljZS0-PkpvaG46IEhlbGxvIEpvaG4sIGhvdyBhcmUgeW91P1xubG9vcCBIZWFsdGhjaGVja1xuICAgIEpvaG4tPj5Kb2huOiBGaWdodCBhZ2FpbnN0IGh5cG9jaG9uZHJpYVxuZW5kXG5Ob3RlIHJpZ2h0IG9mIEpvaG46IFJhdGlvbmFsIHRob3VnaHRzIVxuSm9obi0tPj5BbGljZTogR3JlYXQhXG5Kb2huLT4-Qm9iOiBIb3cgYWJvdXQgeW91P1xuQm9iLS0-PkpvaG46IEpvbGx5IGdvb2QhIiwibWVybWFpZCI6eyJ0aGVtZSI6ImRlZmF1bHQifX0">live editor</a>]
|
||||
|
||||
```
|
||||
sequenceDiagram
|
||||
Alice->>John: Hello John, how are you?
|
||||
loop Healthcheck
|
||||
@@ -67,19 +64,22 @@ Note right of John: Rational thoughts!
|
||||
John-->>Alice: Great!
|
||||
John->>Bob: How about you?
|
||||
Bob-->>John: Jolly good!
|
||||
</pre></td>
|
||||
<td align="center">
|
||||
<img src="https://raw.githubusercontent.com/mermaid-js/mermaid/master/img/gray-sequence.png" />
|
||||
</td>
|
||||
</tr>
|
||||
<!-- </Sequence> -->
|
||||
<!-- <Gantt> -->
|
||||
<tr><td colspan=2 align="center">
|
||||
<b>甘特图</b><br />
|
||||
[<a href="https://mermaid-js.github.io/mermaid/#/gantt">文档</a> - <a href="https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoiZ2FudHRcbnNlY3Rpb24gU2VjdGlvblxuQ29tcGxldGVkIDpkb25lLCAgICBkZXMxLCAyMDE0LTAxLTA2LDIwMTQtMDEtMDhcbkFjdGl2ZSAgICAgICAgOmFjdGl2ZSwgIGRlczIsIDIwMTQtMDEtMDcsIDNkXG5QYXJhbGxlbCAxICAgOiAgICAgICAgIGRlczMsIGFmdGVyIGRlczEsIDFkXG5QYXJhbGxlbCAyICAgOiAgICAgICAgIGRlczQsIGFmdGVyIGRlczEsIDFkXG5QYXJhbGxlbCAzICAgOiAgICAgICAgIGRlczUsIGFmdGVyIGRlczMsIDFkXG5QYXJhbGxlbCA0ICAgOiAgICAgICAgIGRlczYsIGFmdGVyIGRlczQsIDFkIiwibWVybWFpZCI6eyJ0aGVtZSI6ImRlZmF1bHQifX0">live editor</a>]
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td><pre>
|
||||
```
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
Alice->>John: Hello John, how are you?
|
||||
loop Healthcheck
|
||||
John->>John: Fight against hypochondria
|
||||
end
|
||||
Note right of John: Rational thoughts!
|
||||
John-->>Alice: Great!
|
||||
John->>Bob: How about you?
|
||||
Bob-->>John: Jolly good!
|
||||
```
|
||||
|
||||
## 甘特图 [<a href="https://mermaid-js.github.io/mermaid/#/gantt">文档</a> - <a href="https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoiZ2FudHRcbnNlY3Rpb24gU2VjdGlvblxuQ29tcGxldGVkIDpkb25lLCAgICBkZXMxLCAyMDE0LTAxLTA2LDIwMTQtMDEtMDhcbkFjdGl2ZSAgICAgICAgOmFjdGl2ZSwgIGRlczIsIDIwMTQtMDEtMDcsIDNkXG5QYXJhbGxlbCAxICAgOiAgICAgICAgIGRlczMsIGFmdGVyIGRlczEsIDFkXG5QYXJhbGxlbCAyICAgOiAgICAgICAgIGRlczQsIGFmdGVyIGRlczEsIDFkXG5QYXJhbGxlbCAzICAgOiAgICAgICAgIGRlczUsIGFmdGVyIGRlczMsIDFkXG5QYXJhbGxlbCA0ICAgOiAgICAgICAgIGRlczYsIGFmdGVyIGRlczQsIDFkIiwibWVybWFpZCI6eyJ0aGVtZSI6ImRlZmF1bHQifX0">live editor</a>]
|
||||
|
||||
```
|
||||
gantt
|
||||
section Section
|
||||
Completed :done, des1, 2014-01-06,2014-01-08
|
||||
@@ -88,22 +88,24 @@ Parallel 1 : des3, after des1, 1d
|
||||
Parallel 2 : des4, after des1, 1d
|
||||
Parallel 3 : des5, after des3, 1d
|
||||
Parallel 4 : des6, after des4, 1d
|
||||
</pre></td>
|
||||
<td align="center">
|
||||
<img src="https://raw.githubusercontent.com/mermaid-js/mermaid/master/img/gray-gantt.png" />
|
||||
</td>
|
||||
</tr>
|
||||
<!-- </Gantt> -->
|
||||
<!-- <Class> -->
|
||||
<tr><td colspan=2 align="center">
|
||||
<b>类图</b><br />
|
||||
[<a href="https://mermaid-js.github.io/mermaid/#/classDiagram">文档</a> - <a href="https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoiY2xhc3NEaWFncmFtXG5DbGFzczAxIDx8LS0gQXZlcnlMb25nQ2xhc3MgOiBDb29sXG48PGludGVyZmFjZT4-IENsYXNzMDFcbkNsYXNzMDkgLS0-IEMyIDogV2hlcmUgYW0gaT9cbkNsYXNzMDkgLS0qIEMzXG5DbGFzczA5IC0tfD4gQ2xhc3MwN1xuQ2xhc3MwNyA6IGVxdWFscygpXG5DbGFzczA3IDogT2JqZWN0W10gZWxlbWVudERhdGFcbkNsYXNzMDEgOiBzaXplKClcbkNsYXNzMDEgOiBpbnQgY2hpbXBcbkNsYXNzMDEgOiBpbnQgZ29yaWxsYVxuY2xhc3MgQ2xhc3MxMCB7XG4gID4-c2VydmljZT4-XG4gIGludCBpZFxuICBzaXplKClcbn0iLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9fQ">live editor</a>]
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td><pre>
|
||||
```
|
||||
```mermaid
|
||||
gantt
|
||||
section Section
|
||||
Completed :done, des1, 2014-01-06,2014-01-08
|
||||
Active :active, des2, 2014-01-07, 3d
|
||||
Parallel 1 : des3, after des1, 1d
|
||||
Parallel 2 : des4, after des1, 1d
|
||||
Parallel 3 : des5, after des3, 1d
|
||||
Parallel 4 : des6, after des4, 1d
|
||||
```
|
||||
|
||||
## 类图 [<a href="https://mermaid-js.github.io/mermaid/#/classDiagram">文档</a> - <a href="https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoiY2xhc3NEaWFncmFtXG5DbGFzczAxIDx8LS0gQXZlcnlMb25nQ2xhc3MgOiBDb29sXG48PGludGVyZmFjZT4-IENsYXNzMDFcbkNsYXNzMDkgLS0-IEMyIDogV2hlcmUgYW0gaT9cbkNsYXNzMDkgLS0qIEMzXG5DbGFzczA5IC0tfD4gQ2xhc3MwN1xuQ2xhc3MwNyA6IGVxdWFscygpXG5DbGFzczA3IDogT2JqZWN0W10gZWxlbWVudERhdGFcbkNsYXNzMDEgOiBzaXplKClcbkNsYXNzMDEgOiBpbnQgY2hpbXBcbkNsYXNzMDEgOiBpbnQgZ29yaWxsYVxuY2xhc3MgQ2xhc3MxMCB7XG4gID4-c2VydmljZT4-XG4gIGludCBpZFxuICBzaXplKClcbn0iLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9fQ">live editor</a>]
|
||||
|
||||
```
|
||||
classDiagram
|
||||
Class01 <|-- AveryLongClass : Cool
|
||||
<<interface>> Class01
|
||||
Class01 <|-- AveryLongClass : Cool
|
||||
<<Interface>> Class01
|
||||
Class09 --> C2 : Where am i?
|
||||
Class09 --* C3
|
||||
Class09 --|> Class07
|
||||
@@ -113,23 +115,33 @@ Class01 : size()
|
||||
Class01 : int chimp
|
||||
Class01 : int gorilla
|
||||
class Class10 {
|
||||
<<service>>
|
||||
<<service>>
|
||||
int id
|
||||
size()
|
||||
}
|
||||
</pre></td>
|
||||
<td align="center">
|
||||
<img src="https://raw.githubusercontent.com/mermaid-js/mermaid/master/img/gray-class.png" />
|
||||
</td>
|
||||
</tr>
|
||||
<!-- </Class> -->
|
||||
<!-- <State> -->
|
||||
<tr><td colspan=2 align="center">
|
||||
<b>状态图</b><br />
|
||||
[<a href="https://mermaid-js.github.io/mermaid/#/stateDiagram">文档</a> - <a href="https://mermaid-js.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoic3RhdGVEaWFncmFtLXYyXG4gICAgWypdIC0tPiBTdGlsbFxuICAgIFN0aWxsIC0tPiBbKl1cbiAgICBTdGlsbCAtLT4gTW92aW5nXG4gICAgTW92aW5nIC0tPiBTdGlsbFxuICAgIE1vdmluZyAtLT4gQ3Jhc2hcbiAgICBDcmFzaCAtLT4gWypdIiwibWVybWFpZCI6eyJ0aGVtZSI6ImRlZmF1bHQiLCJ0aGVtZVZhcmlhYmxlcyI6eyJiYWNrZ3JvdW5kIjoid2hpdGUiLCJwcmltYXJ5Q29sb3IiOiIjRUNFQ0ZGIiwic2Vjb25kYXJ5Q29sb3IiOiIjZmZmZmRlIiwidGVydGlhcnlDb2xvciI6ImhzbCg4MCwgMTAwJSwgOTYuMjc0NTA5ODAzOSUpIiwicHJpbWFyeUJvcmRlckNvbG9yIjoiaHNsKDI0MCwgNjAlLCA4Ni4yNzQ1MDk4MDM5JSkiLCJzZWNvbmRhcnlCb3JkZXJDb2xvciI6ImhzbCg2MCwgNjAlLCA4My41Mjk0MTE3NjQ3JSkiLCJ0ZXJ0aWFyeUJvcmRlckNvbG9yIjoiaHNsKDgwLCA2MCUsIDg2LjI3NDUwOTgwMzklKSIsInByaW1hcnlUZXh0Q29sb3IiOiIjMTMxMzAwIiwic2Vjb25kYXJ5VGV4dENvbG9yIjoiIzAwMDAyMSIsInRlcnRpYXJ5VGV4dENvbG9yIjoicmdiKDkuNTAwMDAwMDAwMSwgOS41MDAwMDAwMDAxLCA5LjUwMDAwMDAwMDEpIiwibGluZUNvbG9yIjoiIzMzMzMzMyIsInRleHRDb2xvciI6IiMzMzMiLCJtYWluQmtnIjoiI0VDRUNGRiIsInNlY29uZEJrZyI6IiNmZmZmZGUiLCJib3JkZXIxIjoiIzkzNzBEQiIsImJvcmRlcjIiOiIjYWFhYTMzIiwiYXJyb3doZWFkQ29sb3IiOiIjMzMzMzMzIiwiZm9udEZhbWlseSI6IlwidHJlYnVjaGV0IG1zXCIsIHZlcmRhbmEsIGFyaWFsIiwiZm9udFNpemUiOiIxNnB4IiwibGFiZWxCYWNrZ3JvdW5kIjoiI2U4ZThlOCIsIm5vZGVCa2ciOiIjRUNFQ0ZGIiwibm9kZUJvcmRlciI6IiM5MzcwREIiLCJjbHVzdGVyQmtnIjoiI2ZmZmZkZSIsImNsdXN0ZXJCb3JkZXIiOiIjYWFhYTMzIiwiZGVmYXVsdExpbmtDb2xvciI6IiMzMzMzMzMiLCJ0aXRsZUNvbG9yIjoiIzMzMyIsImVkZ2VMYWJlbEJhY2tncm91bmQiOiIjZThlOGU4IiwiYWN0b3JCb3JkZXIiOiJoc2woMjU5LjYyNjE2ODIyNDMsIDU5Ljc3NjUzNjMxMjglLCA4Ny45MDE5NjA3ODQzJSkiLCJhY3RvckJrZyI6IiNFQ0VDRkYiLCJhY3RvclRleHRDb2xvciI6ImJsYWNrIiwiYWN0b3JMaW5lQ29sb3IiOiJncmV5Iiwic2lnbmFsQ29sb3IiOiIjMzMzIiwic2lnbmFsVGV4dENvbG9yIjoiIzMzMyIsImxhYmVsQm94QmtnQ29sb3IiOiIjRUNFQ0ZGIiwibGFiZWxCb3hCb3JkZXJDb2xvciI6ImhzbCgyNTkuNjI2MTY4MjI0MywgNTkuNzc2NTM2MzEyOCUsIDg3LjkwMTk2MDc4NDMlKSIsImxhYmVsVGV4dENvbG9yIjoiYmxhY2siLCJsb29wVGV4dENvbG9yIjoiYmxhY2siLCJub3RlQm9yZGVyQ29sb3IiOiIjYWFhYTMzIiwibm90ZUJrZ0NvbG9yIjoiI2ZmZjVhZCIsIm5vdGVUZXh0Q29sb3IiOiJibGFjayIsImFjdGl2YXRpb25Cb3JkZXJDb2xvciI6IiM2NjYiLCJhY3RpdmF0aW9uQmtnQ29sb3IiOiIjZjRmNGY0Iiwic2VxdWVuY2VOdW1iZXJDb2xvciI6IndoaXRlIiwic2VjdGlvbkJrZ0NvbG9yIjoicmdiYSgxMDIsIDEwMiwgMjU1LCAwLjQ5KSIsImFsdFNlY3Rpb25Ca2dDb2xvciI6IndoaXRlIiwic2VjdGlvbkJrZ0NvbG9yMiI6IiNmZmY0MDAiLCJ0YXNrQm9yZGVyQ29sb3IiOiIjNTM0ZmJjIiwidGFza0JrZ0NvbG9yIjoiIzhhOTBkZCIsInRhc2tUZXh0TGlnaHRDb2xvciI6IndoaXRlIiwidGFza1RleHRDb2xvciI6IndoaXRlIiwidGFza1RleHREYXJrQ29sb3IiOiJibGFjayIsInRhc2tUZXh0T3V0c2lkZUNvbG9yIjoiYmxhY2siLCJ0YXNrVGV4dENsaWNrYWJsZUNvbG9yIjoiIzAwMzE2MyIsImFjdGl2ZVRhc2tCb3JkZXJDb2xvciI6IiM1MzRmYmMiLCJhY3RpdmVUYXNrQmtnQ29sb3IiOiIjYmZjN2ZmIiwiZ3JpZENvbG9yIjoibGlnaHRncmV5IiwiZG9uZVRhc2tCa2dDb2xvciI6ImxpZ2h0Z3JleSIsImRvbmVUYXNrQm9yZGVyQ29sb3IiOiJncmV5IiwiY3JpdEJvcmRlckNvbG9yIjoiI2ZmODg4OCIsImNyaXRCa2dDb2xvciI6InJlZCIsInRvZGF5TGluZUNvbG9yIjoicmVkIiwibGFiZWxDb2xvciI6ImJsYWNrIiwiZXJyb3JCa2dDb2xvciI6IiM1NTIyMjIiLCJlcnJvclRleHRDb2xvciI6IiM1NTIyMjIiLCJjbGFzc1RleHQiOiIjMTMxMzAwIiwiZmlsbFR5cGUwIjoiI0VDRUNGRiIsImZpbGxUeXBlMSI6IiNmZmZmZGUiLCJmaWxsVHlwZTIiOiJoc2woMzA0LCAxMDAlLCA5Ni4yNzQ1MDk4MDM5JSkiLCJmaWxsVHlwZTMiOiJoc2woMTI0LCAxMDAlLCA5My41Mjk0MTE3NjQ3JSkiLCJmaWxsVHlwZTQiOiJoc2woMTc2LCAxMDAlLCA5Ni4yNzQ1MDk4MDM5JSkiLCJmaWxsVHlwZTUiOiJoc2woLTQsIDEwMCUsIDkzLjUyOTQxMTc2NDclKSIsImZpbGxUeXBlNiI6ImhzbCg4LCAxMDAlLCA5Ni4yNzQ1MDk4MDM5JSkiLCJmaWxsVHlwZTciOiJoc2woMTg4LCAxMDAlLCA5My41Mjk0MTE3NjQ3JSkifX0sInVwZGF0ZUVkaXRvciI6ZmFsc2V9">live editor</a>]
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td><pre>
|
||||
```
|
||||
```mermaid
|
||||
classDiagram
|
||||
Class01 <|-- AveryLongClass : Cool
|
||||
<<Interface>> Class01
|
||||
Class09 --> C2 : Where am i?
|
||||
Class09 --* C3
|
||||
Class09 --|> Class07
|
||||
Class07 : equals()
|
||||
Class07 : Object[] elementData
|
||||
Class01 : size()
|
||||
Class01 : int chimp
|
||||
Class01 : int gorilla
|
||||
class Class10 {
|
||||
<<service>>
|
||||
int id
|
||||
size()
|
||||
}
|
||||
```
|
||||
|
||||
## 状态图 [<a href="https://mermaid-js.github.io/mermaid/#/stateDiagram">文档</a> - <a href="https://mermaid-js.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoic3RhdGVEaWFncmFtLXYyXG4gICAgWypdIC0tPiBTdGlsbFxuICAgIFN0aWxsIC0tPiBbKl1cbiAgICBTdGlsbCAtLT4gTW92aW5nXG4gICAgTW92aW5nIC0tPiBTdGlsbFxuICAgIE1vdmluZyAtLT4gQ3Jhc2hcbiAgICBDcmFzaCAtLT4gWypdIiwibWVybWFpZCI6eyJ0aGVtZSI6ImRlZmF1bHQiLCJ0aGVtZVZhcmlhYmxlcyI6eyJiYWNrZ3JvdW5kIjoid2hpdGUiLCJwcmltYXJ5Q29sb3IiOiIjRUNFQ0ZGIiwic2Vjb25kYXJ5Q29sb3IiOiIjZmZmZmRlIiwidGVydGlhcnlDb2xvciI6ImhzbCg4MCwgMTAwJSwgOTYuMjc0NTA5ODAzOSUpIiwicHJpbWFyeUJvcmRlckNvbG9yIjoiaHNsKDI0MCwgNjAlLCA4Ni4yNzQ1MDk4MDM5JSkiLCJzZWNvbmRhcnlCb3JkZXJDb2xvciI6ImhzbCg2MCwgNjAlLCA4My41Mjk0MTE3NjQ3JSkiLCJ0ZXJ0aWFyeUJvcmRlckNvbG9yIjoiaHNsKDgwLCA2MCUsIDg2LjI3NDUwOTgwMzklKSIsInByaW1hcnlUZXh0Q29sb3IiOiIjMTMxMzAwIiwic2Vjb25kYXJ5VGV4dENvbG9yIjoiIzAwMDAyMSIsInRlcnRpYXJ5VGV4dENvbG9yIjoicmdiKDkuNTAwMDAwMDAwMSwgOS41MDAwMDAwMDAxLCA5LjUwMDAwMDAwMDEpIiwibGluZUNvbG9yIjoiIzMzMzMzMyIsInRleHRDb2xvciI6IiMzMzMiLCJtYWluQmtnIjoiI0VDRUNGRiIsInNlY29uZEJrZyI6IiNmZmZmZGUiLCJib3JkZXIxIjoiIzkzNzBEQiIsImJvcmRlcjIiOiIjYWFhYTMzIiwiYXJyb3doZWFkQ29sb3IiOiIjMzMzMzMzIiwiZm9udEZhbWlseSI6IlwidHJlYnVjaGV0IG1zXCIsIHZlcmRhbmEsIGFyaWFsIiwiZm9udFNpemUiOiIxNnB4IiwibGFiZWxCYWNrZ3JvdW5kIjoiI2U4ZThlOCIsIm5vZGVCa2ciOiIjRUNFQ0ZGIiwibm9kZUJvcmRlciI6IiM5MzcwREIiLCJjbHVzdGVyQmtnIjoiI2ZmZmZkZSIsImNsdXN0ZXJCb3JkZXIiOiIjYWFhYTMzIiwiZGVmYXVsdExpbmtDb2xvciI6IiMzMzMzMzMiLCJ0aXRsZUNvbG9yIjoiIzMzMyIsImVkZ2VMYWJlbEJhY2tncm91bmQiOiIjZThlOGU4IiwiYWN0b3JCb3JkZXIiOiJoc2woMjU5LjYyNjE2ODIyNDMsIDU5Ljc3NjUzNjMxMjglLCA4Ny45MDE5NjA3ODQzJSkiLCJhY3RvckJrZyI6IiNFQ0VDRkYiLCJhY3RvclRleHRDb2xvciI6ImJsYWNrIiwiYWN0b3JMaW5lQ29sb3IiOiJncmV5Iiwic2lnbmFsQ29sb3IiOiIjMzMzIiwic2lnbmFsVGV4dENvbG9yIjoiIzMzMyIsImxhYmVsQm94QmtnQ29sb3IiOiIjRUNFQ0ZGIiwibGFiZWxCb3hCb3JkZXJDb2xvciI6ImhzbCgyNTkuNjI2MTY4MjI0MywgNTkuNzc2NTM2MzEyOCUsIDg3LjkwMTk2MDc4NDMlKSIsImxhYmVsVGV4dENvbG9yIjoiYmxhY2siLCJsb29wVGV4dENvbG9yIjoiYmxhY2siLCJub3RlQm9yZGVyQ29sb3IiOiIjYWFhYTMzIiwibm90ZUJrZ0NvbG9yIjoiI2ZmZjVhZCIsIm5vdGVUZXh0Q29sb3IiOiJibGFjayIsImFjdGl2YXRpb25Cb3JkZXJDb2xvciI6IiM2NjYiLCJhY3RpdmF0aW9uQmtnQ29sb3IiOiIjZjRmNGY0Iiwic2VxdWVuY2VOdW1iZXJDb2xvciI6IndoaXRlIiwic2VjdGlvbkJrZ0NvbG9yIjoicmdiYSgxMDIsIDEwMiwgMjU1LCAwLjQ5KSIsImFsdFNlY3Rpb25Ca2dDb2xvciI6IndoaXRlIiwic2VjdGlvbkJrZ0NvbG9yMiI6IiNmZmY0MDAiLCJ0YXNrQm9yZGVyQ29sb3IiOiIjNTM0ZmJjIiwidGFza0JrZ0NvbG9yIjoiIzhhOTBkZCIsInRhc2tUZXh0TGlnaHRDb2xvciI6IndoaXRlIiwidGFza1RleHRDb2xvciI6IndoaXRlIiwidGFza1RleHREYXJrQ29sb3IiOiJibGFjayIsInRhc2tUZXh0T3V0c2lkZUNvbG9yIjoiYmxhY2siLCJ0YXNrVGV4dENsaWNrYWJsZUNvbG9yIjoiIzAwMzE2MyIsImFjdGl2ZVRhc2tCb3JkZXJDb2xvciI6IiM1MzRmYmMiLCJhY3RpdmVUYXNrQmtnQ29sb3IiOiIjYmZjN2ZmIiwiZ3JpZENvbG9yIjoibGlnaHRncmV5IiwiZG9uZVRhc2tCa2dDb2xvciI6ImxpZ2h0Z3JleSIsImRvbmVUYXNrQm9yZGVyQ29sb3IiOiJncmV5IiwiY3JpdEJvcmRlckNvbG9yIjoiI2ZmODg4OCIsImNyaXRCa2dDb2xvciI6InJlZCIsInRvZGF5TGluZUNvbG9yIjoicmVkIiwibGFiZWxDb2xvciI6ImJsYWNrIiwiZXJyb3JCa2dDb2xvciI6IiM1NTIyMjIiLCJlcnJvclRleHRDb2xvciI6IiM1NTIyMjIiLCJjbGFzc1RleHQiOiIjMTMxMzAwIiwiZmlsbFR5cGUwIjoiI0VDRUNGRiIsImZpbGxUeXBlMSI6IiNmZmZmZGUiLCJmaWxsVHlwZTIiOiJoc2woMzA0LCAxMDAlLCA5Ni4yNzQ1MDk4MDM5JSkiLCJmaWxsVHlwZTMiOiJoc2woMTI0LCAxMDAlLCA5My41Mjk0MTE3NjQ3JSkiLCJmaWxsVHlwZTQiOiJoc2woMTc2LCAxMDAlLCA5Ni4yNzQ1MDk4MDM5JSkiLCJmaWxsVHlwZTUiOiJoc2woLTQsIDEwMCUsIDkzLjUyOTQxMTc2NDclKSIsImZpbGxUeXBlNiI6ImhzbCg4LCAxMDAlLCA5Ni4yNzQ1MDk4MDM5JSkiLCJmaWxsVHlwZTciOiJoc2woMTg4LCAxMDAlLCA5My41Mjk0MTE3NjQ3JSkifX0sInVwZGF0ZUVkaXRvciI6ZmFsc2V9">live editor</a>]
|
||||
|
||||
```
|
||||
stateDiagram-v2
|
||||
[*] --> Still
|
||||
Still --> [*]
|
||||
@@ -137,46 +149,37 @@ Still --> Moving
|
||||
Moving --> Still
|
||||
Moving --> Crash
|
||||
Crash --> [*]
|
||||
</pre></td>
|
||||
<td align="center">
|
||||
<img src="https://raw.githubusercontent.com/mermaid-js/mermaid/master/img/gray-state.png" />
|
||||
</td>
|
||||
</tr>
|
||||
<!-- </State> -->
|
||||
<!-- <Pie> -->
|
||||
<tr><td colspan=2 align="center">
|
||||
<b>饼图</b><br />
|
||||
[<a href="https://mermaid-js.github.io/mermaid/#/pie">文档</a> - <a href="https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoicGllXG5cIkRvZ3NcIiA6IDQyLjk2XG5cIkNhdHNcIiA6IDUwLjA1XG5cIlJhdHNcIiA6IDEwLjAxIiwibWVybWFpZCI6eyJ0aGVtZSI6ImRlZmF1bHQifX0">live editor</a>]
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td><pre>
|
||||
```
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Still
|
||||
Still --> [*]
|
||||
Still --> Moving
|
||||
Moving --> Still
|
||||
Moving --> Crash
|
||||
Crash --> [*]
|
||||
```
|
||||
|
||||
## 饼图 [<a href="https://mermaid-js.github.io/mermaid/#/pie">文档</a> - <a href="https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoicGllXG5cIkRvZ3NcIiA6IDQyLjk2XG5cIkNhdHNcIiA6IDUwLjA1XG5cIlJhdHNcIiA6IDEwLjAxIiwibWVybWFpZCI6eyJ0aGVtZSI6ImRlZmF1bHQifX0">live editor</a>]
|
||||
|
||||
```
|
||||
pie
|
||||
"Dogs" : 386
|
||||
"Cats" : 85
|
||||
"Rats" : 15
|
||||
</pre></td>
|
||||
<td align="center">
|
||||
<img src="https://raw.githubusercontent.com/mermaid-js/mermaid/master/img/gray-pie.png" />
|
||||
</td>
|
||||
</tr>
|
||||
<!-- </Pie> -->
|
||||
<!-- <Git> -->
|
||||
<tr><td colspan=2 align="center">
|
||||
<b>Git图</b><br />
|
||||
[实验特性 - <a href="https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoiZ2l0R3JhcGg6XG5vcHRpb25zXG57XG4gICAgXCJub2RlU3BhY2luZ1wiOiAxNTAsXG4gICAgXCJub2RlUmFkaXVzXCI6IDEwXG59XG5lbmRcbmNvbW1pdFxuYnJhbmNoIG5ld2JyYW5jaFxuY2hlY2tvdXQgbmV3YnJhbmNoXG5jb21taXRcbmNvbW1pdFxuY2hlY2tvdXQgbWFzdGVyXG5jb21taXRcbmNvbW1pdFxubWVyZ2UgbmV3YnJhbmNoXG4iLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9fQ">live editor</a>]
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td colspan="2" align="center"><i>敬请期待!</i></td>
|
||||
</tr>
|
||||
<!-- </Git> -->
|
||||
<!-- <Journey> -->
|
||||
<tr><td colspan=2 align="center">
|
||||
<b>用户体验旅程图</b><br />
|
||||
[<a href="https://mermaid-js.github.io/mermaid/#/user-journey">文档</a> - <a href="https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoic3RhdGVEaWFncmFtXG4gICAgWypdIC0tPiBTdGlsbFxuICAgIFN0aWxsIC0tPiBbKl1cbiAgICBTdGlsbCAtLT4gTW92aW5nXG4gICAgTW92aW5nIC0tPiBTdGlsbFxuICAgIE1vdmluZyAtLT4gQ3Jhc2hcbiAgICBDcmFzaCAtLT4gWypdIiwibWVybWFpZCI6eyJ0aGVtZSI6ImRlZmF1bHQifX0">live editor</a>]
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td>
|
||||
<pre>
|
||||
```
|
||||
```mermaid
|
||||
pie
|
||||
"Dogs" : 386
|
||||
"Cats" : 85
|
||||
"Rats" : 15
|
||||
```
|
||||
|
||||
## Git图 [实验特性 - <a href="https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoiZ2l0R3JhcGg6XG5vcHRpb25zXG57XG4gICAgXCJub2RlU3BhY2luZ1wiOiAxNTAsXG4gICAgXCJub2RlUmFkaXVzXCI6IDEwXG59XG5lbmRcbmNvbW1pdFxuYnJhbmNoIG5ld2JyYW5jaFxuY2hlY2tvdXQgbmV3YnJhbmNoXG5jb21taXRcbmNvbW1pdFxuY2hlY2tvdXQgbWFzdGVyXG5jb21taXRcbmNvbW1pdFxubWVyZ2UgbmV3YnJhbmNoXG4iLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9fQ">live editor</a>]
|
||||
|
||||
## 用户体验旅程图 [<a href="https://mermaid-js.github.io/mermaid/#/user-journey">文档</a> - <a href="https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoic3RhdGVEaWFncmFtXG4gICAgWypdIC0tPiBTdGlsbFxuICAgIFN0aWxsIC0tPiBbKl1cbiAgICBTdGlsbCAtLT4gTW92aW5nXG4gICAgTW92aW5nIC0tPiBTdGlsbFxuICAgIE1vdmluZyAtLT4gQ3Jhc2hcbiAgICBDcmFzaCAtLT4gWypdIiwibWVybWFpZCI6eyJ0aGVtZSI6ImRlZmF1bHQifX0">live editor</a>]
|
||||
|
||||
```
|
||||
journey
|
||||
title My working day
|
||||
section Go to work
|
||||
@@ -186,14 +189,30 @@ pie
|
||||
section Go home
|
||||
Go downstairs: 5: Me
|
||||
Sit down: 3: Me
|
||||
</pre></td>
|
||||
<td align="center">
|
||||
<img alt="User Journey Diagram" src="img/gray-user-journey.png" />
|
||||
</td>
|
||||
</tr>
|
||||
<!-- </Journey> -->
|
||||
```
|
||||
```mermaid
|
||||
journey
|
||||
title My working day
|
||||
section Go to work
|
||||
Make tea: 5: Me
|
||||
Go upstairs: 3: Me
|
||||
Do work: 1: Me, Cat
|
||||
section Go home
|
||||
Go downstairs: 5: Me
|
||||
Sit down: 3: Me
|
||||
```
|
||||
|
||||
</table>
|
||||
### 发布
|
||||
|
||||
对于有权限的同学来说,你可以通过以下步骤来完成发布操作:
|
||||
|
||||
更新 `package.json` 中的版本号,然后执行如下命令:
|
||||
|
||||
```sh
|
||||
npm publish
|
||||
```
|
||||
|
||||
以上的命令会将文件打包到 `dist` 目录并发布至 npmjs.org.
|
||||
|
||||
## 相关项目
|
||||
|
||||
@@ -207,6 +226,14 @@ Mermaid 是一个不断发展中的社区,并且还在接收新的贡献者。
|
||||
|
||||
关于如何贡献的详细信息可以在 [贡献指南](CONTRIBUTING.md) 中找到。
|
||||
|
||||
## 安全
|
||||
|
||||
对于公开网站来说,从互联网上的用户处检索文本、存储供后续在浏览器中展示的内容可能是不安全的,理由是用户的内容可能嵌入一些数据加载完成之后就会运行的恶意脚本,这些对于 Mermaid 来说毫无疑问是一个风险,尤其是 mermaid 图表还包含了许多在 html 中使用的字符,这意味着我们难以使用常规的手段来过滤不安全代码,因为这些常规手段会造成图表损坏。我们仍然在努力对获取到的代码进行安全过滤并不断完善我们的程序,但很难保证没有漏洞。
|
||||
|
||||
作为拥有外部用户的网站的额外安全级别,我们很高兴推出一个新的安全级别,其中的图表在沙盒 iframe 中渲染,防止代码中的 javascript 被执行,这是在安全性方面迈出的一大步。
|
||||
|
||||
*很不幸的是,鱼与熊掌不可兼得,在这个场景下它意味着在可能的恶意代码被阻止时,也会损失部分交互能力*。
|
||||
|
||||
## 报告漏洞
|
||||
|
||||
如果想要报告漏洞,请发送邮件到 security@mermaid.live, 并附上问题的描述、复现问题的步骤、受影响的版本,以及解决问题的方案(如果有的话)。
|
||||
|
||||
@@ -47,7 +47,11 @@ export const imgSnapshotTest = (graphStr, _options, api) => {
|
||||
|
||||
cy.visit(url);
|
||||
cy.get('svg');
|
||||
cy.percySnapshot();
|
||||
// cy.percySnapshot();
|
||||
// Default name to test title
|
||||
const name = (options.name || cy.state('runnable').fullTitle()).replace(/\s+/g, '-');
|
||||
|
||||
cy.matchImageSnapshot(name);
|
||||
};
|
||||
|
||||
export const renderGraph = (graphStr, options, api) => {
|
||||
|
||||
@@ -111,7 +111,9 @@ describe('Configuration', () => {
|
||||
cy.visit(url);
|
||||
|
||||
cy.get('svg');
|
||||
cy.percySnapshot();
|
||||
cy.matchImageSnapshot(
|
||||
'configuration.spec-should-not-taint-initial-configuration-when-using-multiple-directives'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -134,7 +134,7 @@ graph TD
|
||||
const url = 'http://localhost:9000/theme-directives.html';
|
||||
cy.visit(url);
|
||||
cy.get('svg');
|
||||
cy.percySnapshot();
|
||||
cy.matchImageSnapshot('conf-and-directives.spec-when-rendering-several-diagrams-diagram-1');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,20 +1,105 @@
|
||||
import { imgSnapshotTest } from '../../helpers/util.js';
|
||||
|
||||
describe('Sequencediagram', () => {
|
||||
// it('should render a simple git graph', () => {
|
||||
// imgSnapshotTest(
|
||||
// `
|
||||
// gitGraph:
|
||||
// commit
|
||||
// branch newbranch
|
||||
// checkout newbranch
|
||||
// commit
|
||||
// commit
|
||||
// checkout master
|
||||
// commit
|
||||
// commit
|
||||
// merge newbranch`,
|
||||
// { logLevel: 0 }
|
||||
// );
|
||||
// });
|
||||
describe('Git Graph diagram', () => {
|
||||
it('1: should render a simple gitgraph with commit on main branch', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph
|
||||
commit id: "1"
|
||||
commit id: "2"
|
||||
commit id: "3"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('2: should render a simple gitgraph with commit on main branch with Id', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph
|
||||
commit id: "One"
|
||||
commit id: "Two"
|
||||
commit id: "Three"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('3: should render a simple gitgraph with different commitTypes on main branch ', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph
|
||||
commit id: "Normal Commit"
|
||||
commit id: "Reverse Commit" type: REVERSE
|
||||
commit id: "Hightlight Commit" type: HIGHLIGHT
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('4: should render a simple gitgraph with tags commitTypes on main branch ', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph
|
||||
commit id: "Normal Commit with tag" tag: "v1.0.0"
|
||||
commit id: "Reverse Commit with tag" type: REVERSE tag: "RC_1"
|
||||
commit id: "Hightlight Commit" type: HIGHLIGHT tag: "8.8.4"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('5: should render a simple gitgraph with two branches', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph
|
||||
commit id: "1"
|
||||
commit id: "2"
|
||||
branch develop
|
||||
checkout develop
|
||||
commit id: "3"
|
||||
commit id: "4"
|
||||
checkout main
|
||||
commit id: "5"
|
||||
commit id: "6"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('6: should render a simple gitgraph with two branches and merge commit', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph
|
||||
commit id: "1"
|
||||
commit id: "2"
|
||||
branch develop
|
||||
checkout develop
|
||||
commit id: "3"
|
||||
commit id: "4"
|
||||
checkout main
|
||||
merge develop
|
||||
commit id: "5"
|
||||
commit id: "6"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('7: should render a simple gitgraph with three branches and merge commit', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph
|
||||
commit id: "1"
|
||||
commit id: "2"
|
||||
branch nice_feature
|
||||
checkout nice_feature
|
||||
commit id: "3"
|
||||
checkout main
|
||||
commit id: "4"
|
||||
checkout nice_feature
|
||||
branch very_nice_feature
|
||||
checkout very_nice_feature
|
||||
commit id: "5"
|
||||
checkout main
|
||||
commit id: "6"
|
||||
checkout nice_feature
|
||||
commit id: "7"
|
||||
checkout main
|
||||
merge nice_feature
|
||||
checkout very_nice_feature
|
||||
commit id: "8"
|
||||
checkout main
|
||||
commit id: "9"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -552,7 +552,7 @@ context('Sequence diagram', () => {
|
||||
}
|
||||
);
|
||||
});
|
||||
it('should override config with directive settings', () => {
|
||||
it('should override config with directive settings 2', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
%%{init: { "config": { "mirrorActors": false, "wrap": true }}}%%
|
||||
|
||||
@@ -158,7 +158,7 @@ describe('State diagram', () => {
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a simple state diagrams', () => {
|
||||
it('v2 should render a simple state diagrams 2', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
stateDiagram-v2
|
||||
|
||||
@@ -148,7 +148,7 @@ describe('State diagram', () => {
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a simple state diagrams', () => {
|
||||
it('should render a simple state diagrams 2', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
stateDiagram
|
||||
|
||||
67
cypress/platform/git-graph.html
Normal file
67
cypress/platform/git-graph.html
Normal file
@@ -0,0 +1,67 @@
|
||||
<html>
|
||||
<head>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
|
||||
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';
|
||||
}
|
||||
h1 { color: white;}
|
||||
.mermaid2 {
|
||||
display: none;
|
||||
}
|
||||
.customCss > rect, .customCss{
|
||||
fill:#FF0000 !important;
|
||||
stroke:#FFFF00 !important;
|
||||
stroke-width:4px !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>info below</h1>
|
||||
<div class="mermaid" style="width: 100%; height: 20%;">
|
||||
|
||||
gitGraph
|
||||
class BankAccount{
|
||||
+String owner
|
||||
+BigDecimal balance
|
||||
+deposit(amount) bool
|
||||
+withdrawl(amount) int
|
||||
}
|
||||
cssClass "BankAccount" customCss
|
||||
|
||||
</div>
|
||||
|
||||
<script src="./mermaid.js"></script>
|
||||
<script>
|
||||
mermaid.parseError = function (err, hash) {
|
||||
// console.error('Mermaid error: ', err);
|
||||
};
|
||||
mermaid.initialize({
|
||||
theme: 'default',
|
||||
// arrowMarkerAbsolute: true,
|
||||
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
|
||||
logLevel: 0,
|
||||
flowchart: { curve: 'linear', htmlLabels: true },
|
||||
// gantt: { axisFormat: '%m/%d/%Y' },
|
||||
sequence: { actorMargin: 50, showSequenceNumbers: true },
|
||||
// sequenceDiagram: { actorMargin: 300 } // deprecated
|
||||
// fontFamily: '"arial", sans-serif',
|
||||
// themeVariables: {
|
||||
// fontFamily: '"arial", sans-serif',
|
||||
// },
|
||||
curve: 'linear',
|
||||
securityLevel: 'loose',
|
||||
});
|
||||
function callback() {
|
||||
alert('It worked');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
138
cypress/platform/gitgraph.html
Normal file
138
cypress/platform/gitgraph.html
Normal file
@@ -0,0 +1,138 @@
|
||||
<html>
|
||||
<head>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
|
||||
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:#111;
|
||||
/* background:#333; */
|
||||
font-family: 'Arial';
|
||||
}
|
||||
/* h1 { color: white;} */
|
||||
.mermaid2 {
|
||||
display: none;
|
||||
}
|
||||
.customCss > rect, .customCss{
|
||||
fill:#FF0000 !important;
|
||||
stroke:#FFFF00 !important;
|
||||
stroke-width:4px !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>info below</h1>
|
||||
<div class="mermaid2" style="width: 100%; height: 20%;">
|
||||
%%{init: { 'logLevel': 'debug', 'theme': 'neutral' } }%%
|
||||
gitGraph
|
||||
commit "Ashish"
|
||||
branch newbranch
|
||||
checkout newbranch
|
||||
commit id:"1111"
|
||||
commit tag:"test"
|
||||
checkout main
|
||||
commit type: HIGHLIGHT
|
||||
commit
|
||||
merge newbranch
|
||||
commit
|
||||
branch b2
|
||||
commit
|
||||
|
||||
</div>
|
||||
<div class="mermaid" style="width: 100%; height: 20%;">
|
||||
gitGraph
|
||||
commit type:HIGHLIGHT
|
||||
branch hotfix
|
||||
checkout hotfix
|
||||
commit type:HIGHLIGHT
|
||||
branch develop
|
||||
checkout develop
|
||||
commit id:"ash" tag:"abc" type:HIGHLIGHT
|
||||
branch featureB
|
||||
checkout featureB
|
||||
commit type:HIGHLIGHT
|
||||
checkout main
|
||||
checkout hotfix
|
||||
commit type:HIGHLIGHT
|
||||
checkout develop
|
||||
commit type:REVERSE
|
||||
checkout featureB
|
||||
commit type:HIGHLIGHT
|
||||
checkout main
|
||||
merge hotfix
|
||||
checkout featureB
|
||||
commit type:HIGHLIGHT
|
||||
checkout develop
|
||||
branch featureA
|
||||
commit type:HIGHLIGHT
|
||||
checkout develop
|
||||
checkout featureA
|
||||
commit
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
merge featureA
|
||||
branch release
|
||||
checkout release
|
||||
commit type:HIGHLIGHT
|
||||
checkout main
|
||||
commit
|
||||
checkout release
|
||||
merge main
|
||||
checkout develop
|
||||
merge release
|
||||
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 100%; height: 20%;">
|
||||
gitGraph:
|
||||
commit
|
||||
commit
|
||||
branch newbranch
|
||||
commit
|
||||
merge main
|
||||
</div>
|
||||
<script src="./mermaid.js"></script>
|
||||
<script>
|
||||
mermaid.parseError = function (err, hash) {
|
||||
// console.error('Mermaid error: ', err);
|
||||
};
|
||||
mermaid.initialize({
|
||||
theme: 'dark',
|
||||
// themeVariables: {
|
||||
// primaryColor: '#9400D3',
|
||||
// darkMode: true,
|
||||
// background: '#222',
|
||||
// // textColor: 'white',
|
||||
// // primaryTextColor: '#f4f4f4',
|
||||
|
||||
// // // nodeBkg: '#ff0000',
|
||||
// // // mainBkg: '#0000ff',
|
||||
// // // tertiaryColor: '#ffffcc',
|
||||
// },
|
||||
// theme: 'forest',
|
||||
// theme: 'neutral',
|
||||
// theme: 'dark',
|
||||
// arrowMarkerAbsolute: true,
|
||||
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
|
||||
logLevel: 1,
|
||||
flowchart: { curve: 'linear', htmlLabels: true },
|
||||
// gantt: { axisFormat: '%m/%d/%Y' },
|
||||
sequence: { actorMargin: 50, showSequenceNumbers: true },
|
||||
// sequenceDiagram: { actorMargin: 300 } // deprecated
|
||||
// fontFamily: '"arial", sans-serif',
|
||||
// themeVariables: {
|
||||
// fontFamily: '"arial", sans-serif',
|
||||
// },
|
||||
curve: 'linear',
|
||||
securityLevel: 'loose',
|
||||
});
|
||||
function callback() {
|
||||
alert('It worked');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
137
cypress/platform/gitgraph2.html
Normal file
137
cypress/platform/gitgraph2.html
Normal file
@@ -0,0 +1,137 @@
|
||||
<html>
|
||||
<head>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
|
||||
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:#111;
|
||||
/* background:#333; */
|
||||
font-family: 'Arial';
|
||||
}
|
||||
/* h1 { color: white;} */
|
||||
.mermaid2 {
|
||||
display: none;
|
||||
}
|
||||
.customCss > rect, .customCss{
|
||||
fill:#FF0000 !important;
|
||||
stroke:#FFFF00 !important;
|
||||
stroke-width:4px !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>info below</h1>
|
||||
<div class="mermaid2" style="width: 100%; height: 20%;">
|
||||
gitGraph:
|
||||
commit "Ashish"
|
||||
branch newbranch
|
||||
checkout newbranch
|
||||
commit id:"1111"
|
||||
commit tag:"test"
|
||||
checkout main
|
||||
commit type: HIGHLIGHT
|
||||
commit
|
||||
merge newbranch
|
||||
commit
|
||||
branch b2
|
||||
commit
|
||||
|
||||
</div>
|
||||
<div class="mermaid" style="width: 100%; height: 20%;">
|
||||
gitGraph
|
||||
commit
|
||||
branch hotfix
|
||||
checkout hotfix
|
||||
commit
|
||||
branch develop
|
||||
checkout develop
|
||||
commit id:"An id" tag:"A tag"
|
||||
branch featureB
|
||||
checkout featureB
|
||||
commit type:HIGHLIGHT
|
||||
checkout main
|
||||
checkout hotfix
|
||||
commit type:NORMAL
|
||||
checkout develop
|
||||
commit type:REVERSE
|
||||
checkout featureB
|
||||
commit
|
||||
checkout main
|
||||
merge hotfix
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
branch featureA
|
||||
commit
|
||||
checkout develop
|
||||
merge hotfix
|
||||
checkout featureA
|
||||
commit
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
merge featureA
|
||||
branch release
|
||||
checkout release
|
||||
commit
|
||||
checkout main
|
||||
commit
|
||||
checkout release
|
||||
merge main
|
||||
checkout develop
|
||||
merge release
|
||||
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 100%; height: 20%;">
|
||||
gitGraph:
|
||||
commit
|
||||
commit
|
||||
branch newbranch
|
||||
commit
|
||||
merge main
|
||||
</div>
|
||||
<script src="./mermaid.js"></script>
|
||||
<script>
|
||||
mermaid.parseError = function (err, hash) {
|
||||
// console.error('Mermaid error: ', err);
|
||||
};
|
||||
mermaid.initialize({
|
||||
theme: 'dark',
|
||||
themeVariables: {
|
||||
// primaryColor: '#9400D3',
|
||||
// darkMode: false,
|
||||
// background: '#222',
|
||||
// textColor: 'white',
|
||||
// primaryTextColor: '#f4f4f4',
|
||||
// nodeBkg: '#ff0000',
|
||||
// mainBkg: '#0000ff',
|
||||
// tertiaryColor: '#ffffcc',
|
||||
},
|
||||
// theme: 'forest',
|
||||
// theme: 'neutral',
|
||||
// theme: 'dark',
|
||||
// arrowMarkerAbsolute: true,
|
||||
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
|
||||
logLevel: 1,
|
||||
flowchart: { curve: 'linear', htmlLabels: true },
|
||||
// gantt: { axisFormat: '%m/%d/%Y' },
|
||||
sequence: { actorMargin: 50, showSequenceNumbers: true },
|
||||
// sequenceDiagram: { actorMargin: 300 } // deprecated
|
||||
// fontFamily: '"arial", sans-serif',
|
||||
// themeVariables: {
|
||||
// fontFamily: '"arial", sans-serif',
|
||||
// },
|
||||
curve: 'linear',
|
||||
securityLevel: 'loose',
|
||||
});
|
||||
function callback() {
|
||||
alert('It worked');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -66,6 +66,7 @@ merge newbranch
|
||||
</div>
|
||||
<div class="mermaid" style="width: 50%;">
|
||||
sequenceDiagram
|
||||
title: with colon:
|
||||
participant a as Alice
|
||||
participant j as John
|
||||
note right of a: Hello world!
|
||||
|
||||
@@ -264,6 +264,50 @@ requirementDiagram
|
||||
test_req - contains -> test_req3
|
||||
test_req <- copies - test_entity2
|
||||
</div>
|
||||
<div class="mermaid" style="width: 100%; height: 20%;">
|
||||
gitGraph:
|
||||
commit
|
||||
branch hotfix
|
||||
checkout hotfix
|
||||
commit
|
||||
branch develop
|
||||
checkout develop
|
||||
commit id:"An id" tag:"A tag"
|
||||
branch featureB
|
||||
checkout featureB
|
||||
commit type:HIGHLIGHT
|
||||
checkout main
|
||||
checkout hotfix
|
||||
commit type:NORMAL
|
||||
checkout develop
|
||||
commit type:REVERSE
|
||||
checkout featureB
|
||||
commit
|
||||
checkout main
|
||||
merge hotfix
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
branch featureA
|
||||
commit
|
||||
checkout develop
|
||||
merge hotfix
|
||||
checkout featureA
|
||||
commit
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
merge featureA
|
||||
branch release
|
||||
checkout release
|
||||
commit
|
||||
checkout main
|
||||
commit
|
||||
checkout release
|
||||
merge main
|
||||
checkout develop
|
||||
merge release
|
||||
</div>
|
||||
<script src="./mermaid.js"></script>
|
||||
<script>
|
||||
mermaid.parseError = function (err, hash) {
|
||||
|
||||
@@ -258,7 +258,50 @@ requirementDiagram
|
||||
test_req - contains -> test_req3
|
||||
test_req <- copies - test_entity2
|
||||
</div>
|
||||
|
||||
<div class="mermaid" class="width height">
|
||||
gitGraph
|
||||
commit
|
||||
branch hotfix
|
||||
checkout hotfix
|
||||
commit
|
||||
branch develop
|
||||
checkout develop
|
||||
commit id:"An id" tag:"A tag"
|
||||
branch featureB
|
||||
checkout featureB
|
||||
commit type:HIGHLIGHT
|
||||
checkout main
|
||||
checkout hotfix
|
||||
commit type:NORMAL
|
||||
checkout develop
|
||||
commit type:REVERSE
|
||||
checkout featureB
|
||||
commit
|
||||
checkout main
|
||||
merge hotfix
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
branch featureA
|
||||
commit
|
||||
checkout develop
|
||||
merge hotfix
|
||||
checkout featureA
|
||||
commit
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
merge featureA
|
||||
branch release
|
||||
checkout release
|
||||
commit
|
||||
checkout main
|
||||
commit
|
||||
checkout release
|
||||
merge main
|
||||
checkout develop
|
||||
merge release
|
||||
</div>
|
||||
<script src="./mermaid.js"></script>
|
||||
<script>
|
||||
mermaid.parseError = function (err, hash) {
|
||||
|
||||
@@ -256,6 +256,50 @@ requirementDiagram
|
||||
test_req - contains -> test_req3
|
||||
test_req <- copies - test_entity2
|
||||
</div>
|
||||
<div class="mermaid" class="width height">
|
||||
gitGraph
|
||||
commit
|
||||
branch hotfix
|
||||
checkout hotfix
|
||||
commit
|
||||
branch develop
|
||||
checkout develop
|
||||
commit id:"An id" tag:"A tag"
|
||||
branch featureB
|
||||
checkout featureB
|
||||
commit type:HIGHLIGHT
|
||||
checkout main
|
||||
checkout hotfix
|
||||
commit type:NORMAL
|
||||
checkout develop
|
||||
commit type:REVERSE
|
||||
checkout featureB
|
||||
commit
|
||||
checkout main
|
||||
merge hotfix
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
branch featureA
|
||||
commit
|
||||
checkout develop
|
||||
merge hotfix
|
||||
checkout featureA
|
||||
commit
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
merge featureA
|
||||
branch release
|
||||
checkout release
|
||||
commit
|
||||
checkout main
|
||||
commit
|
||||
checkout release
|
||||
merge main
|
||||
checkout develop
|
||||
merge release
|
||||
</div>
|
||||
<script src="./mermaid.js"></script>
|
||||
<script>
|
||||
mermaid.parseError = function (err, hash) {
|
||||
|
||||
@@ -251,6 +251,50 @@ requirementDiagram
|
||||
test_req - contains -> test_req3
|
||||
test_req <- copies - test_entity2
|
||||
</div>
|
||||
<div class="mermaid" style="width: 100%; height: 20%;">
|
||||
gitGraph
|
||||
commit
|
||||
branch hotfix
|
||||
checkout hotfix
|
||||
commit
|
||||
branch develop
|
||||
checkout develop
|
||||
commit id:"An id" tag:"A tag"
|
||||
branch featureB
|
||||
checkout featureB
|
||||
commit type:HIGHLIGHT
|
||||
checkout main
|
||||
checkout hotfix
|
||||
commit type:NORMAL
|
||||
checkout develop
|
||||
commit type:REVERSE
|
||||
checkout featureB
|
||||
commit
|
||||
checkout main
|
||||
merge hotfix
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
branch featureA
|
||||
commit
|
||||
checkout develop
|
||||
merge hotfix
|
||||
checkout featureA
|
||||
commit
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
merge featureA
|
||||
branch release
|
||||
checkout release
|
||||
commit
|
||||
checkout main
|
||||
commit
|
||||
checkout release
|
||||
merge main
|
||||
checkout develop
|
||||
merge release
|
||||
</div>
|
||||
<script src="./mermaid.js"></script>
|
||||
<script>
|
||||
mermaid.parseError = function (err, hash) {
|
||||
|
||||
@@ -255,6 +255,50 @@ requirementDiagram
|
||||
test_req - contains -> test_req3
|
||||
test_req <- copies - test_entity2
|
||||
</div>
|
||||
<div class="mermaid" class="width height">
|
||||
gitGraph:
|
||||
commit
|
||||
branch hotfix
|
||||
checkout hotfix
|
||||
commit
|
||||
branch develop
|
||||
checkout develop
|
||||
commit id:"An id" tag:"A tag"
|
||||
branch featureB
|
||||
checkout featureB
|
||||
commit type:HIGHLIGHT
|
||||
checkout main
|
||||
checkout hotfix
|
||||
commit type:NORMAL
|
||||
checkout develop
|
||||
commit type:REVERSE
|
||||
checkout featureB
|
||||
commit
|
||||
checkout main
|
||||
merge hotfix
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
branch featureA
|
||||
commit
|
||||
checkout develop
|
||||
merge hotfix
|
||||
checkout featureA
|
||||
commit
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
merge featureA
|
||||
branch release
|
||||
checkout release
|
||||
commit
|
||||
checkout main
|
||||
commit
|
||||
checkout release
|
||||
merge main
|
||||
checkout develop
|
||||
merge release
|
||||
</div>
|
||||
<script src="./mermaid.js"></script>
|
||||
<script>
|
||||
mermaid.parseError = function (err, hash) {
|
||||
|
||||
@@ -254,6 +254,52 @@ requirementDiagram
|
||||
test_req - contains -> test_req3
|
||||
test_req <- copies - test_entity2
|
||||
</div>
|
||||
|
||||
<div class="mermaid" class="width height">
|
||||
gitGraph:
|
||||
commit
|
||||
branch hotfix
|
||||
checkout hotfix
|
||||
commit
|
||||
branch develop
|
||||
checkout develop
|
||||
commit id:"An id" tag:"A tag"
|
||||
branch featureB
|
||||
checkout featureB
|
||||
commit type:HIGHLIGHT
|
||||
checkout main
|
||||
checkout hotfix
|
||||
commit type:NORMAL
|
||||
checkout develop
|
||||
commit type:REVERSE
|
||||
checkout featureB
|
||||
commit
|
||||
checkout main
|
||||
merge hotfix
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
branch featureA
|
||||
commit
|
||||
checkout develop
|
||||
merge hotfix
|
||||
checkout featureA
|
||||
commit
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
merge featureA
|
||||
branch release
|
||||
checkout release
|
||||
commit
|
||||
checkout main
|
||||
commit
|
||||
checkout release
|
||||
merge main
|
||||
checkout develop
|
||||
merge release
|
||||
</div>
|
||||
|
||||
<script src="./mermaid.js"></script>
|
||||
<script>
|
||||
mermaid.parseError = function (err, hash) {
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
// // `config` is the resolved Cypress config
|
||||
// }
|
||||
|
||||
const { addMatchImageSnapshotPlugin } = require('cypress-image-snapshot/plugin');
|
||||
|
||||
module.exports = (on, config) => {
|
||||
// `on` is used to hook into various events Cypress emits
|
||||
// `config` is the resolved Cypress config
|
||||
addMatchImageSnapshotPlugin(on, config);
|
||||
};
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 166 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 162 KiB |
@@ -24,4 +24,8 @@
|
||||
// -- This is will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
|
||||
|
||||
import '@percy/cypress';
|
||||
// import '@percy/cypress';
|
||||
|
||||
import { addMatchImageSnapshotCommand } from 'cypress-image-snapshot/command';
|
||||
|
||||
addMatchImageSnapshotCommand();
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands';
|
||||
import '@percy/cypress';
|
||||
// import '@percy/cypress';
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
|
||||
45
demos/er.html
Normal file
45
demos/er.html
Normal file
@@ -0,0 +1,45 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<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: 'trebuchet ms', verdana, arial; */
|
||||
font-family: 'Courier New', Courier, monospace !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
|
||||
<div class="mermaid">
|
||||
erDiagram
|
||||
title This is a title
|
||||
accDescription Test a description
|
||||
CUSTOMER ||--o{ ORDER : places
|
||||
ORDER ||--|{ LINE-ITEM : contains
|
||||
CUSTOMER }|..|{ DELIVERY-ADDRESS : uses
|
||||
</div>
|
||||
|
||||
<script src="./mermaid.js"></script>
|
||||
<script>
|
||||
mermaid.initialize({
|
||||
theme: 'forest',
|
||||
// themeCSS: '.node rect { fill: red; }',
|
||||
logLevel: 3,
|
||||
securityLevel: 'loose',
|
||||
flowchart: { curve: 'basis' },
|
||||
gantt: { axisFormat: '%m/%d/%Y' },
|
||||
sequence: { actorMargin: 50 },
|
||||
// sequenceDiagram: { actorMargin: 300 } // deprecated
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -230,6 +230,8 @@
|
||||
<h3>flowchart</h3>
|
||||
<div class="mermaid">
|
||||
flowchart TD
|
||||
title Christmas
|
||||
accDescription Get money
|
||||
A[Christmas] -->|Get money| B(Go shopping)
|
||||
B --> C{Let me thinksssssx<br/>sssssssssssssssssssuuu<br />tttsssssssssssssssssssssss}
|
||||
C -->|One| D[Laptop]
|
||||
|
||||
@@ -467,6 +467,7 @@
|
||||
|
||||
<div class="mermaid">
|
||||
sequenceDiagram
|
||||
accDescription Hello friends
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant John as John<br />Second Line
|
||||
@@ -786,6 +787,43 @@
|
||||
|
||||
<script src="./mermaid.js"></script>
|
||||
<script>
|
||||
const ALLOWED_TAGS = [
|
||||
'a',
|
||||
'b',
|
||||
'blockquote',
|
||||
'br',
|
||||
'dd',
|
||||
'div',
|
||||
'dl',
|
||||
'dt',
|
||||
'em',
|
||||
'foreignObject',
|
||||
'h1',
|
||||
'h2',
|
||||
'h3',
|
||||
'h4',
|
||||
'h5',
|
||||
'h6',
|
||||
'h7',
|
||||
'h8',
|
||||
'hr',
|
||||
'i',
|
||||
'li',
|
||||
'ul',
|
||||
'ol',
|
||||
'p',
|
||||
'pre',
|
||||
'span',
|
||||
'strike',
|
||||
'strong',
|
||||
'table',
|
||||
'tbody',
|
||||
'td',
|
||||
'tfoot',
|
||||
'th',
|
||||
'thead',
|
||||
'tr',
|
||||
];
|
||||
mermaid.initialize({
|
||||
theme: 'forest',
|
||||
// themeCSS: '.node rect { fill: red; }',
|
||||
@@ -794,6 +832,13 @@
|
||||
flowchart: { curve: 'basis' },
|
||||
gantt: { axisFormat: '%m/%d/%Y' },
|
||||
sequence: { actorMargin: 50 },
|
||||
dompurifyConfig: {
|
||||
USE_PROFILES: {
|
||||
svg: true,
|
||||
},
|
||||
ADD_TAGS: ALLOWED_TAGS,
|
||||
ADD_ATTR: ['transform-origin'],
|
||||
},
|
||||
// sequenceDiagram: { actorMargin: 300 } // deprecated
|
||||
});
|
||||
</script>
|
||||
|
||||
72
demos/sequence.html
Normal file
72
demos/sequence.html
Normal file
@@ -0,0 +1,72 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<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: 'trebuchet ms', verdana, arial; */
|
||||
font-family: 'Courier New', Courier, monospace !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
|
||||
<div class="mermaid">
|
||||
sequenceDiagram
|
||||
title: FancySequenceDiagram
|
||||
accDescription Test a description
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant John as John<br />Second Line
|
||||
rect rgb(200, 220, 100)
|
||||
rect rgb(200, 255, 200)
|
||||
Alice ->> Bob: Hello Bob, how are you?
|
||||
Bob-->>John: How about you John?
|
||||
end
|
||||
Bob--x Alice: I am good thanks!
|
||||
Bob-x John: I am good thanks!
|
||||
Note right of John: John thinks a long<br />long time, so long<br />that the text does<br />not fit on a row.
|
||||
Bob-->Alice: Checking with John...
|
||||
Note over John:wrap: John looks like he's still thinking, so Bob prods him a bit.
|
||||
Bob-x John: Hey John - we're still waiting to know<br />how you're doing
|
||||
Note over John:nowrap: John's trying hard not to break his train of thought.
|
||||
Bob-x John:wrap: John! Are you still debating about how you're doing? How long does it take??
|
||||
Note over John: After a few more moments, John<br />finally snaps out of it.
|
||||
end
|
||||
alt either this
|
||||
Alice->>John: Yes
|
||||
else or this
|
||||
Alice->>John: No
|
||||
else or this will happen
|
||||
Alice->John: Maybe
|
||||
end
|
||||
par this happens in parallel
|
||||
Alice -->> Bob: Parallel message 1
|
||||
and
|
||||
Alice -->> John: Parallel message 2
|
||||
end
|
||||
</div>
|
||||
|
||||
<script src="./mermaid.js"></script>
|
||||
<script>
|
||||
mermaid.initialize({
|
||||
theme: 'forest',
|
||||
// themeCSS: '.node rect { fill: red; }',
|
||||
logLevel: 3,
|
||||
securityLevel: 'loose',
|
||||
flowchart: { curve: 'basis' },
|
||||
gantt: { axisFormat: '%m/%d/%Y' },
|
||||
sequence: { actorMargin: 50 },
|
||||
// sequenceDiagram: { actorMargin: 300 } // deprecated
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
31406
dist/mermaid.core.js
vendored
Normal file
31406
dist/mermaid.core.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/mermaid.core.js.map
vendored
Normal file
1
dist/mermaid.core.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
129122
dist/mermaid.js
vendored
Normal file
129122
dist/mermaid.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/mermaid.js.map
vendored
Normal file
1
dist/mermaid.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -11,29 +11,26 @@ It is a Javascript based diagramming and charting tool that renders Markdown-ins
|
||||
|
||||
<!-- **Edit this Page** [](https://github.com/mermaid-js/mermaid/blob/develop/docs/README.md) -->
|
||||
|
||||
[](https://travis-ci.org/mermaid-js/mermaid) [](https://www.npmjs.com/package/mermaid) [](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [](https://percy.io/Mermaid/mermaid)
|
||||
[](https://travis-ci.org/mermaid-js/mermaid) [](https://www.npmjs.com/package/mermaid) [](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE)
|
||||
|
||||
<!-- Mermaidn book banner -->
|
||||
[](https://mermaid-js.github.io/mermaid/landing/)
|
||||
|
||||
|
||||
<!-- <Main description> -->
|
||||
The main purpose of Mermaid is to help with Visualizing Documentation, and helping it catch up with Development.
|
||||
> Documentation-Rot is a Catch-22 that Mermaid helps to solve.
|
||||
Mermaid is a Javascript based diagramming and charting tool that uses Markdown-inspired text definitions and a renderer to create and modify complex diagrams. The main purpose of Mermaid is to help documentation catch up with development.
|
||||
|
||||
Diagramming and Documentation cost precious developer time and get outdated quickly.
|
||||
However, not having diagrams or documentation ruins productivity and hampers organizational learning.
|
||||
> Doc-Rot is a Catch-22 that Mermaid helps to solve.
|
||||
|
||||
Mermaid addresses this Catch-22 situation by reducing the time, effort and tooling that is required to create modifiable diagrams and charts which in turn results in smarter and more reusable content.
|
||||
Mermaid, as a text-based diagramming tool allows for quick and easy updates and makes documentation much easier. It can also be included in production scripts and other pieces of code as per requirement.
|
||||
Diagramming and documentation costs precious developer time and gets outdated quickly.
|
||||
But not having diagrams or docs ruins productivity and hurts organizational learning.<br/>
|
||||
Mermaid addresses this problem by enabling users to create easily modifiable diagrams, it can also be made part of production scripts (and other pieces of code).<br/>
|
||||
<br/>
|
||||
Mermaid allows even non-programmers to easily create detailed and diagrams through the [Mermaid Live Editor](https://mermaid-js.github.io/mermaid-live-editor/).<br/>
|
||||
[Tutorials](./docs/Tutorials.md) has video tutorials.
|
||||
Use Mermaid with your favorite applications, check out the list of [Integrations and Usages of Mermaid](./docs/integrations.md).
|
||||
|
||||
> Mermaid is a Diagramming tool for everyone.
|
||||
|
||||
Even non-programmers can create diagrams through the [Mermaid Live Editor](https://github.com/mermaid-js/mermaid-live-editor), Visit the [Tutorials Page](./Tutorials.md) for the Live Editor video tutorials.
|
||||
|
||||
Many editors, wikis and other tools also have mermaid integrations and plugins, making it easy to start using mermaid. A few of those are described in [Simple start to write diagrams](./n00b-gettingStarted.md).
|
||||
|
||||
For a more detailed introduction to Mermaid and some of it's basic uses, refer to [Overview for Beginners](./n00b-overview.md) and [Usage](./usage.md).
|
||||
For a more detailed introduction to Mermaid and some of its more basic uses, look to the [Beginner's Guide](./docs/n00b-overview.md) and [Usage](./docs/usage.md).
|
||||
|
||||
🌐 [CDN](https://unpkg.com/mermaid/) | 📖 [Documentation](https://mermaidjs.github.io) | 🙌 [Contribution](https://github.com/mermaid-js/mermaid/blob/develop/docs/development.md) | 📜 [Version Log](./CHANGELOG.md) | 🔌 [Plug-Ins](./integrations.md)
|
||||
|
||||
|
||||
@@ -926,7 +926,7 @@ Default value: true
|
||||
**Notes:** Sets the siteConfig. The siteConfig is a protected configuration for repeat use. Calls
|
||||
to reset() will reset the currentConfig to siteConfig. Calls to reset(configApi.defaultConfig)
|
||||
will reset siteConfig and currentConfig to the defaultConfig Note: currentConfig is set in this
|
||||
function \*Default value: At default, will mirror Global Config\*\*
|
||||
function _Default value: At default, will mirror Global Config_
|
||||
|
||||
### Parameters
|
||||
|
||||
@@ -1073,16 +1073,61 @@ To be removed
|
||||
|
||||
```html
|
||||
<script>
|
||||
var config = { theme: 'default', logLevel: 'fatal', securityLevel: 'strict', startOnLoad: true,
|
||||
arrowMarkerAbsolute: false, er: { diagramPadding: 20, layoutDirection: 'TB', minEntityWidth: 100,
|
||||
minEntityHeight: 75, entityPadding: 15, stroke: 'gray', fill: 'honeydew', fontSize: 12, useMaxWidth:
|
||||
true, }, flowchart: { diagramPadding: 8, htmlLabels: true, curve: 'basis', }, sequence: {
|
||||
diagramMarginX: 50, diagramMarginY: 10, actorMargin: 50, width: 150, height: 65, boxMargin: 10,
|
||||
boxTextMargin: 5, noteMargin: 10, messageMargin: 35, messageAlign: 'center', mirrorActors: true,
|
||||
bottomMarginAdj: 1, useMaxWidth: true, rightAngles: false, showSequenceNumbers: false, }, gantt: {
|
||||
titleTopMargin: 25, barHeight: 20, barGap: 4, topPadding: 50, leftPadding: 75, gridLineStartPadding:
|
||||
35, fontSize: 11, fontFamily: '"Open Sans", sans-serif', numberSectionStyles: 4, axisFormat:
|
||||
'%Y-%m-%d', topAxis: false, }, }; mermaid.initialize(config);
|
||||
var config = {
|
||||
theme: 'default',
|
||||
logLevel: 'fatal',
|
||||
securityLevel: 'strict',
|
||||
startOnLoad: true,
|
||||
arrowMarkerAbsolute: false,
|
||||
|
||||
er: {
|
||||
diagramPadding: 20,
|
||||
layoutDirection: 'TB',
|
||||
minEntityWidth: 100,
|
||||
minEntityHeight: 75,
|
||||
entityPadding: 15,
|
||||
stroke: 'gray',
|
||||
fill: 'honeydew',
|
||||
fontSize: 12,
|
||||
useMaxWidth: true,
|
||||
},
|
||||
flowchart: {
|
||||
diagramPadding: 8,
|
||||
htmlLabels: true,
|
||||
curve: 'basis',
|
||||
},
|
||||
sequence: {
|
||||
diagramMarginX: 50,
|
||||
diagramMarginY: 10,
|
||||
actorMargin: 50,
|
||||
width: 150,
|
||||
height: 65,
|
||||
boxMargin: 10,
|
||||
boxTextMargin: 5,
|
||||
noteMargin: 10,
|
||||
messageMargin: 35,
|
||||
messageAlign: 'center',
|
||||
mirrorActors: true,
|
||||
bottomMarginAdj: 1,
|
||||
useMaxWidth: true,
|
||||
rightAngles: false,
|
||||
showSequenceNumbers: false,
|
||||
},
|
||||
gantt: {
|
||||
titleTopMargin: 25,
|
||||
barHeight: 20,
|
||||
barGap: 4,
|
||||
topPadding: 50,
|
||||
leftPadding: 75,
|
||||
gridLineStartPadding: 35,
|
||||
fontSize: 11,
|
||||
fontFamily: '"Open Sans", sans-serif',
|
||||
numberSectionStyles: 4,
|
||||
axisFormat: '%Y-%m-%d',
|
||||
topAxis: false,
|
||||
},
|
||||
};
|
||||
mermaid.initialize(config);
|
||||
</script>
|
||||
```
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ or
|
||||
<link rel="stylesheet" href="mermaid.forest.min.css">
|
||||
```
|
||||
|
||||
Now it is not needed to do so. And there are no more CSS files in distrubtion files.
|
||||
Now it is not needed to do so. And there are no more CSS files in distribution files.
|
||||
|
||||
You just
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ sequenceDiagram
|
||||
|
||||
## Initialize
|
||||
|
||||
Intialize call is calloed **only once**. It is called by the site integrator in order to override the default configuration on a site level.
|
||||
Initialize call is called **only once**. It is called by the site integrator in order to override the default configuration on a site level.
|
||||
|
||||
## configApi.reset
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ The docs are located in the `docs` folder and are written in Markdown. Just pick
|
||||
|
||||
> **All the documents displayed in the github.io page are listed in [sidebar.md](https://github.com/mermaid-js/mermaid/edit/develop/docs/_sidebar.md)**.
|
||||
|
||||
The contents of [https://mermaid-js.github.io/mermaid/](https://mermaid-js.github.io/mermaid/) are based on the docs from the `master` branch. Updates commited to the `master` branch are reflected in the [Mermaid Docs](https://mermaid-js.github.io/mermaid/) once released.
|
||||
The contents of [https://mermaid-js.github.io/mermaid/](https://mermaid-js.github.io/mermaid/) are based on the docs from the `master` branch. Updates committed to the `master` branch are reflected in the [Mermaid Docs](https://mermaid-js.github.io/mermaid/) once released.
|
||||
|
||||
## How to Contribute to Documentation
|
||||
|
||||
@@ -98,6 +98,7 @@ it('should render forks and joins', () => {
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
### Any Questions or Suggestions?
|
||||
|
||||
@@ -505,7 +505,7 @@ defined in the linkStyle statement will belong to the fourth link in the graph:
|
||||
linkStyle 3 stroke:#ff3,stroke-width:4px,color:red;
|
||||
```
|
||||
|
||||
You can specify default to apply to all links, or you can give a list of link order numbers seperated by a comma.
|
||||
You can specify default to apply to all links, or you can give a list of link order numbers separated by a comma.
|
||||
|
||||
Instead of giving a styles option, you can also use custom d3 curve types with the following syntax:
|
||||
|
||||
|
||||
@@ -105,3 +105,54 @@ sequenceDiagram
|
||||
John->>Bob: How about you?
|
||||
Bob-->>John: Jolly good!
|
||||
```
|
||||
|
||||
## Sequence Diagram: Blogging app service communication
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
participant web as Web Browser
|
||||
participant blog as Blog Service
|
||||
participant account as Account Service
|
||||
participant mail as Mail Service
|
||||
participant db as Storage
|
||||
|
||||
Note over web,db: The user must be logged in to submit blog posts
|
||||
web->>+account: Logs in using credentials
|
||||
account->>db: Query stored accounts
|
||||
db->>account: Respond with query result
|
||||
|
||||
alt Credentials not found
|
||||
account->>web: Invalid credentials
|
||||
else Credentials found
|
||||
account->>-web: Successfully logged in
|
||||
|
||||
Note over web,db: When the user is authenticated, they can now submit new posts
|
||||
web->>+blog: Submit new post
|
||||
blog->>db: Store post data
|
||||
|
||||
par Notifications
|
||||
blog--)mail: Send mail to blog subscribers
|
||||
blog--)db: Store in-site notifications
|
||||
and Response
|
||||
blog-->>-web: Successfully posted
|
||||
end
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
A commit flow diagram.
|
||||
```mermaid
|
||||
gitGraph:
|
||||
commit "Ashish"
|
||||
branch newbranch
|
||||
checkout newbranch
|
||||
commit id:"1111"
|
||||
commit tag:"test"
|
||||
checkout main
|
||||
commit type: HIGHLIGHT
|
||||
commit
|
||||
merge newbranch
|
||||
commit
|
||||
branch b2
|
||||
commit
|
||||
```
|
||||
@@ -6,7 +6,7 @@
|
||||
Gantt Charts will record each scheduled task as one continuous bar that extends from the left to the right. The x axis represents time and the y records the different tasks and the order in which they are to be completed.
|
||||
|
||||
|
||||
It is important to remember that when a date, day, or collection of dates specific to a task are "excluded", the Gantt Chart will accomodate those changes by extending an equal number of days, towards the right, not by creating a gap inside the task.
|
||||
It is important to remember that when a date, day, or collection of dates specific to a task are "excluded", the Gantt Chart will accommodate those changes by extending an equal number of days, towards the right, not by creating a gap inside the task.
|
||||
As shown here 
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ The default input date format is `YYYY-MM-DD`. You can define your custom ``date
|
||||
dateFormat YYYY-MM-DD
|
||||
```
|
||||
|
||||
The following formating options are supported:
|
||||
The following formatting options are supported:
|
||||
|
||||
```
|
||||
Input Example Description:
|
||||
@@ -146,7 +146,7 @@ The default output date format is YYYY-MM-DD. You can define your custom ``axisF
|
||||
axisFormat %Y-%m-%d
|
||||
```
|
||||
|
||||
The following formating strings are supported:
|
||||
The following formatting strings are supported:
|
||||
|
||||
```
|
||||
%a - abbreviated weekday name.
|
||||
|
||||
437
docs/gitgraph.md
Normal file
437
docs/gitgraph.md
Normal file
@@ -0,0 +1,437 @@
|
||||
# Gitgraph Diagrams
|
||||
|
||||
**Edit this Page** [](https://github.com/mermaid-js/mermaid/blob/develop/docs/gitgraph.md)
|
||||
> A Git Graph is a pictorial representation of git commits and git actions(commands) on various branches.
|
||||
|
||||
These kind of diagram are particularyly helpful to developers and devops teams to share their Git branching strategies. For example, it makes it easier to visualize how git flow works.
|
||||
|
||||
Mermaid can render Git diagrams
|
||||
|
||||
```mermaid-example
|
||||
gitGraph
|
||||
commit
|
||||
commit
|
||||
branch develop
|
||||
checkout develop
|
||||
commit
|
||||
commit
|
||||
checkout main
|
||||
merge develop
|
||||
commit
|
||||
commit
|
||||
```
|
||||
|
||||
In Mermaid, we support the basic git operations like:
|
||||
- *commit* : Representing a new commit on the current branch.
|
||||
- *branch* : To create & switch to a new branch, setting it as the current branch.
|
||||
- *checkout* : To checking out an existing branch and setting it as the current branch.
|
||||
- *merge* : To merge an existing branch onto the current branch.
|
||||
|
||||
With the help of these key git commands, you will be able to draw a gitgraph in Mermaid very easily and quickly.
|
||||
Entity names are often capitalised, although there is no accepted standard on this, and it is not required in Mermaid.
|
||||
|
||||
|
||||
## Syntax
|
||||
Mermaid syntax for Gitgraph is very straigth-forward and simple. It follows a declarative-approach, where each commit is drawn on the timeline in the diagram, in order of its occurance/presence in code. Basically, it follows the insertion order for each command.
|
||||
|
||||
First thing you do is to declare your diagram type using the **gitgraph** keyword. This `gitgraph` keyword, tells Mermaid that you wish to draw a gitgraph, and parse the diagram code accordingly.
|
||||
|
||||
Each gitgraph, is initialized with ***main*** branch. So unless you create a different branch, by-default the commits will go to the main branch. This is driven with how git works, where in the begging you always start with the main branch (formerly called as ***master*** branch). And by-default, `main` branch is set as your ***current branch***.
|
||||
|
||||
|
||||
You make use of ***commit*** keyword to register a commit on the current branch. Let see how this works:
|
||||
|
||||
A simple gitgraph showing three commits on the default (***main***) branch:
|
||||
```mermaid-example
|
||||
gitGraph
|
||||
commit
|
||||
commit
|
||||
commit
|
||||
```
|
||||
If you look closely at the previous example, you can see the default branch `main` along with three commits. Also, notice, the by-default each commit has been given a unique & random Id. What if you would want to give your own custom ID to a commit? Yes, it is possible to do that with Mermaid.
|
||||
|
||||
### Adding custom commit id
|
||||
|
||||
For a given commit you may specify a custom id at the time of declaring it using the `id` attribute, followed by `:` and your custom value within `""` quote. For example: `commit id: "your_custom_id"`
|
||||
|
||||
Let us see how this works with the help of the following diagram:
|
||||
|
||||
```mermaid-example
|
||||
gitGraph
|
||||
commit id: "Alpha"
|
||||
commit id: "Beta"
|
||||
commit id: "Gamma"
|
||||
```
|
||||
|
||||
In this example, we have given our custom id's to the commits.
|
||||
|
||||
### Modifying commit type
|
||||
|
||||
In Mermaid, a commit can be of three type, which render a bit different in the diagram. These types are:
|
||||
- `NORMAL` : Default commit type. Represented by a solid circle in the diagram
|
||||
- `REVERSE` : To emphasize a commit as a reverse commit. Represented by a crossed solid circle in the diagram.
|
||||
- `HIGHLIGHT` : To highlight a particular commit in the diagram. Represented by a filled rectangle in the diagram.
|
||||
|
||||
For a given commit you may specify its type at the time of declaring it using the `type` attribute, followed by `:` and the required type option discussed above. For example: `commit type: HIGHLIGHT`
|
||||
|
||||
NOTE: If no commit type is specified, `NORMAL` is picked as default.
|
||||
|
||||
Let us see how these different commit type look with the help of the following diagram:
|
||||
|
||||
```mermaid-example
|
||||
gitGraph
|
||||
commit id: "Normal"
|
||||
commit
|
||||
commit id: "Reverse" type: REVERSE
|
||||
commit
|
||||
commit id: "Hightlight" type: HIGHLIGHT
|
||||
commit
|
||||
```
|
||||
|
||||
In this example, we have specified different types to each commit. Also, see how we have clubbed both `id` and `type` together at the time of declaring our commits.
|
||||
|
||||
### Adding Tags
|
||||
|
||||
For a given commit you may decorate it as a **tag**, similar to the concept of tags or release version in git world.
|
||||
You can attach a custom tag at the time of declaring a commit using the `tag` attribute, followed by `:` and your custom value within `""` quote. For example: `commit tag: "your_custom_tag"`
|
||||
|
||||
Let us see how this works with the help of the following diagram:
|
||||
|
||||
```mermaid-example
|
||||
gitGraph
|
||||
commit
|
||||
commit id: "Normal" tag: "v1.0.0"
|
||||
commit
|
||||
commit id: "Reverse" type: REVERSE tag: "RC_1"
|
||||
commit
|
||||
commit id: "Hightlight" type: HIGHLIGHT tag: "8.8.4"
|
||||
commit
|
||||
```
|
||||
|
||||
In this example, we have given custom tags to the commits. Also, see how we have combined all these attributes in a single commit declaration. You can mix-match these attributes as you like.
|
||||
|
||||
### Create a new branch
|
||||
In Mermaid, in-order to create a new branch, you make use of the `branch` keyword. You also need to provide a name of the new branch. The name has to be unique and cannot be that of an existing branch. Usage example: `branch develop`
|
||||
|
||||
When Mermaid, reads the `branch` keyword, it creates a new branch and sets it as the current branch. Equivalent to you creating a new branch and checking it out in Git world.
|
||||
|
||||
Let see this in an example:
|
||||
|
||||
```mermaid-example
|
||||
gitGraph
|
||||
commit
|
||||
commit
|
||||
branch develop
|
||||
commit
|
||||
commit
|
||||
commit
|
||||
```
|
||||
In this example, see how we started with default `main` branch, and pushed to commits on that.
|
||||
Then we created the `develop` branch, and all commits afterwards are put on the `develop` branch as it became the current branch.
|
||||
|
||||
### Checking out an existing branch
|
||||
In Mermaid, in-order to switch to an existing branch, you make use of the `checkout` keyword. You also need to provide a name of an existing branch. If no branch is found with the given name, it will result in console error. Usage example: `checkout develop`
|
||||
|
||||
When Mermaid, reads the `checkout` keyword, it finds the given branch and sets it as the current branch. Equivalent to checking out a branch in Git world.
|
||||
|
||||
Let see modify our previous example:
|
||||
|
||||
```mermaid-example
|
||||
gitGraph
|
||||
commit
|
||||
commit
|
||||
branch develop
|
||||
commit
|
||||
commit
|
||||
commit
|
||||
checkout main
|
||||
commit
|
||||
commit
|
||||
```
|
||||
In this example, see how we started with default `main` branch, and pushed to commits on that.
|
||||
Then we created the `develop` branch, and all three commits afterwards are put on the `develop` branch as it became the current branch.
|
||||
After this we made use of the `checkout` keyword to set the current branch as `main`, and all commit that follow are registered against the current branch, i.e. `main`.
|
||||
|
||||
### Merging two branches
|
||||
In Mermaid, in-order to merge or join to an existing branch, you make use of the `merge` keyword. You also need to provide a name of an existing branch to merge from. If no branch is found with the given name, it will result in console error. Also, if you can only merge two separate branches, and cannot merge a branch with itself. In such case an error is throw.
|
||||
|
||||
Usage example: `merge develop`
|
||||
|
||||
When Mermaid, reads the `merge` keyword, it finds the given branch and its head commit (the last commit on that branch), and joins it with the head commit on the **current branch**. Each merge result in a ***merge commit***, represented in the diagram with **filled double circle**.
|
||||
|
||||
Let see modify our previous example to merge our two branches:
|
||||
|
||||
```mermaid-example
|
||||
gitGraph
|
||||
commit
|
||||
commit
|
||||
branch develop
|
||||
commit
|
||||
commit
|
||||
commit
|
||||
checkout main
|
||||
commit
|
||||
commit
|
||||
merge develop
|
||||
commit
|
||||
commit
|
||||
```
|
||||
In this example, see how we started with default `main` branch, and pushed to commits on that.
|
||||
Then we created the `develop` branch, and all three commits afterwards are put on the `develop` branch as it became the current branch.
|
||||
After this we made use of the `checkout` keyword to set the current branch as `main`, and all commit that follow are registered against the current branch, i.e. `main`.
|
||||
After this we merge the `develop` branch onto the current branch `main`, resulting in a merge commit.
|
||||
Since the current branch at this point is still `main`, the last two commits are registered against that.
|
||||
|
||||
|
||||
## Themes
|
||||
Mermaid supports a bunch of pre-defined themes which you can use to find the right one for you. PS: you can actually override an existing theme's variable to get your own custom theme going. Learn more about themeing your diagram [here](./theming.md).
|
||||
|
||||
Following are the different pre-defined theme options:
|
||||
- `base`
|
||||
- `forest`
|
||||
- `dark`
|
||||
- `default`
|
||||
- `neutral`
|
||||
|
||||
**NOTE**: To change theme you can either use the `initialize` call or *directives*. Learn more about [directives](./directives.md)
|
||||
Let's put them to use, add see how our sample diagram looks like in different themes:
|
||||
|
||||
### Base Theme
|
||||
|
||||
```mermaid-example
|
||||
%%{init: { 'logLevel': 'debug', 'theme': 'base' } }%%
|
||||
gitGraph
|
||||
commit
|
||||
branch hotfix
|
||||
checkout hotfix
|
||||
commit
|
||||
branch develop
|
||||
checkout develop
|
||||
commit id:"ash" tag:"abc"
|
||||
branch featureB
|
||||
checkout featureB
|
||||
commit type:HIGHLIGHT
|
||||
checkout main
|
||||
checkout hotfix
|
||||
commit type:NORMAL
|
||||
checkout develop
|
||||
commit type:REVERSE
|
||||
checkout featureB
|
||||
commit
|
||||
checkout main
|
||||
merge hotfix
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
branch featureA
|
||||
commit
|
||||
checkout develop
|
||||
merge hotfix
|
||||
checkout featureA
|
||||
commit
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
merge featureA
|
||||
branch release
|
||||
checkout release
|
||||
commit
|
||||
checkout main
|
||||
commit
|
||||
checkout release
|
||||
merge main
|
||||
checkout develop
|
||||
merge release
|
||||
```
|
||||
|
||||
### Forest Theme
|
||||
|
||||
```mermaid-example
|
||||
%%{init: { 'logLevel': 'debug', 'theme': 'forest' } }%%
|
||||
gitGraph
|
||||
commit
|
||||
branch hotfix
|
||||
checkout hotfix
|
||||
commit
|
||||
branch develop
|
||||
checkout develop
|
||||
commit id:"ash" tag:"abc"
|
||||
branch featureB
|
||||
checkout featureB
|
||||
commit type:HIGHLIGHT
|
||||
checkout main
|
||||
checkout hotfix
|
||||
commit type:NORMAL
|
||||
checkout develop
|
||||
commit type:REVERSE
|
||||
checkout featureB
|
||||
commit
|
||||
checkout main
|
||||
merge hotfix
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
branch featureA
|
||||
commit
|
||||
checkout develop
|
||||
merge hotfix
|
||||
checkout featureA
|
||||
commit
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
merge featureA
|
||||
branch release
|
||||
checkout release
|
||||
commit
|
||||
checkout main
|
||||
commit
|
||||
checkout release
|
||||
merge main
|
||||
checkout develop
|
||||
merge release
|
||||
```
|
||||
### Default Theme
|
||||
|
||||
```mermaid-example
|
||||
%%{init: { 'logLevel': 'debug', 'theme': 'default' } }%%
|
||||
gitGraph
|
||||
commit type:HIGHLIGHT
|
||||
branch hotfix
|
||||
checkout hotfix
|
||||
commit
|
||||
branch develop
|
||||
checkout develop
|
||||
commit id:"ash" tag:"abc"
|
||||
branch featureB
|
||||
checkout featureB
|
||||
commit type:HIGHLIGHT
|
||||
checkout main
|
||||
checkout hotfix
|
||||
commit type:NORMAL
|
||||
checkout develop
|
||||
commit type:REVERSE
|
||||
checkout featureB
|
||||
commit
|
||||
checkout main
|
||||
merge hotfix
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
branch featureA
|
||||
commit
|
||||
checkout develop
|
||||
merge hotfix
|
||||
checkout featureA
|
||||
commit
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
merge featureA
|
||||
branch release
|
||||
checkout release
|
||||
commit
|
||||
checkout main
|
||||
commit
|
||||
checkout release
|
||||
merge main
|
||||
checkout develop
|
||||
merge release
|
||||
```
|
||||
### Dark Theme
|
||||
|
||||
```mermaid-example
|
||||
%%{init: { 'logLevel': 'debug', 'theme': 'dark' } }%%
|
||||
gitGraph
|
||||
commit
|
||||
branch hotfix
|
||||
checkout hotfix
|
||||
commit
|
||||
branch develop
|
||||
checkout develop
|
||||
commit id:"ash" tag:"abc"
|
||||
branch featureB
|
||||
checkout featureB
|
||||
commit type:HIGHLIGHT
|
||||
checkout main
|
||||
checkout hotfix
|
||||
commit type:NORMAL
|
||||
checkout develop
|
||||
commit type:REVERSE
|
||||
checkout featureB
|
||||
commit
|
||||
checkout main
|
||||
merge hotfix
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
branch featureA
|
||||
commit
|
||||
checkout develop
|
||||
merge hotfix
|
||||
checkout featureA
|
||||
commit
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
merge featureA
|
||||
branch release
|
||||
checkout release
|
||||
commit
|
||||
checkout main
|
||||
commit
|
||||
checkout release
|
||||
merge main
|
||||
checkout develop
|
||||
merge release
|
||||
```
|
||||
|
||||
### Neutral Theme
|
||||
|
||||
```mermaid-example
|
||||
%%{init: { 'logLevel': 'debug', 'theme': 'neutral' } }%%
|
||||
gitGraph
|
||||
commit
|
||||
branch hotfix
|
||||
checkout hotfix
|
||||
commit
|
||||
branch develop
|
||||
checkout develop
|
||||
commit id:"ash" tag:"abc"
|
||||
branch featureB
|
||||
checkout featureB
|
||||
commit type:HIGHLIGHT
|
||||
checkout main
|
||||
checkout hotfix
|
||||
commit type:NORMAL
|
||||
checkout develop
|
||||
commit type:REVERSE
|
||||
checkout featureB
|
||||
commit
|
||||
checkout main
|
||||
merge hotfix
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
branch featureA
|
||||
commit
|
||||
checkout develop
|
||||
merge hotfix
|
||||
checkout featureA
|
||||
commit
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
merge featureA
|
||||
branch release
|
||||
checkout release
|
||||
commit
|
||||
checkout main
|
||||
commit
|
||||
checkout release
|
||||
merge main
|
||||
checkout develop
|
||||
merge release
|
||||
```
|
||||
|
||||
## Customize using Theme Variables
|
||||
@@ -17,8 +17,8 @@
|
||||
/>
|
||||
<!-- <link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css"> -->
|
||||
<link rel="stylesheet" href="theme.css" />
|
||||
<script src="//cdn.jsdelivr.net/npm/mermaid@8.13.0/dist/mermaid.min.js"></script>
|
||||
<!-- <script src="http://localhost:9000/mermaid.js"></script> -->
|
||||
<!-- <script src="//cdn.jsdelivr.net/npm/mermaid@8.14.0/dist/mermaid.min.js"></script> -->
|
||||
<script src="http://localhost:9000/mermaid.js"></script>
|
||||
<script>
|
||||
// prettier-ignore
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
|
||||
@@ -136,11 +136,14 @@ They also serve as proof of concept, for the variety of things that can be built
|
||||
- [jsdoc-mermaid](https://github.com/Jellyvision/jsdoc-mermaid)
|
||||
- [MkDocs](https://mkdocs.org)
|
||||
- [mkdocs-mermaid2-plugin](https://github.com/fralau/mkdocs-mermaid2-plugin)
|
||||
- [mkdocs-material](https://github.com/squidfunk/mkdocs-material), check the [docs](https://squidfunk.github.io/mkdocs-material/reference/diagrams/)
|
||||
- [Type Doc](https://typedoc.org/)
|
||||
- [typedoc-plugin-mermaid](https://www.npmjs.com/package/typedoc-plugin-mermaid)
|
||||
- [Docsy Hugo Theme](https://www.docsy.dev/docs/adding-content/lookandfeel/#diagrams-with-mermaid) (Native support in theme)
|
||||
- [Codedoc](https://codedoc.cc/)
|
||||
- [codedoc-mermaid-plugin](https://www.npmjs.com/package/codedoc-mermaid-plugin)
|
||||
- [mdbook](https://rust-lang.github.io/mdBook/index.html)
|
||||
- [mdbook-mermaid](https://github.com/badboy/mdbook-mermaid)
|
||||
|
||||
## Browser Extensions
|
||||
|
||||
|
||||
169
docs/integrations.md~HEAD
Normal file
169
docs/integrations.md~HEAD
Normal file
@@ -0,0 +1,169 @@
|
||||
# Integrations
|
||||
|
||||
The following list is a compilation of different integrations and plugins that allow the rendering of mermaid definitions within other applications.
|
||||
|
||||
They also serve as proof of concept, for the variety of things that can be built with mermaid.
|
||||
|
||||
|
||||
## Productivity
|
||||
|
||||
- [GitLab](https://docs.gitlab.com/ee/user/markdown.html#diagrams-and-flowcharts) (**Native support**)
|
||||
- [Azure Devops](https://docs.microsoft.com/en-us/azure/devops/project/wiki/wiki-markdown-guidance?view=azure-devops#add-mermaid-diagrams-to-a-wiki-page) (**Native support**)
|
||||
- [Tuleap](https://docs.tuleap.org/user-guide/writing-in-tuleap.html#graphs) (**Native support**)
|
||||
- [Joplin](https://joplinapp.org) (**Native support**)
|
||||
- [Notion](https://notion.so) (**Native support**)
|
||||
- [GitHub](https://github.com)
|
||||
- [GitHub action: Compile mermaid to image](https://github.com/neenjaw/compile-mermaid-markdown-action)
|
||||
- [svg-generator](https://github.com/SimonKenyonShepard/mermaidjs-github-svg-generator)
|
||||
- [GitBook](http://gitbook.com)
|
||||
- [Mermaid Plugin](https://github.com/JozoVilcek/gitbook-plugin-mermaid)
|
||||
- [Markdown with Mermaid CLI](https://github.com/miao1007/gitbook-plugin-mermaid-cli)
|
||||
- [Mermaid plugin for GitBook](https://github.com/wwformat/gitbook-plugin-mermaid-pdf)
|
||||
- [Atlassian Products](https://www.atlassian.com)
|
||||
- [Mermaid Plugin for Confluence](https://marketplace.atlassian.com/apps/1214124/mermaid-plugin-for-confluence?hosting=server&tab=overview)
|
||||
- [CloudScript.io Addon](https://marketplace.atlassian.com/apps/1219878/cloudscript-io-mermaid-addon?hosting=cloud&tab=overview)
|
||||
- [Auto convert diagrams in Jira](https://github.com/coddingtonbear/jirafs-mermaid)
|
||||
- [Redmine](https://redmine.org)
|
||||
- [Mermaid Macro](https://www.redmine.org/plugins/redmine_mermaid_macro)
|
||||
- [redmine-mermaid](https://github.com/styz/redmine_mermaid)
|
||||
- [markdown-for-mermaid-plugin](https://github.com/jamieh-mongolian/markdown-for-mermaid-plugin)
|
||||
|
||||
## CRM/ERP/Similar
|
||||
|
||||
- [coreBOS](http://blog.corebos.org/blog/december2019)
|
||||
|
||||
## Blogs
|
||||
|
||||
- [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)
|
||||
- [hexo-filter-mermaid-diagrams](https://github.com/webappdevelp/hexo-filter-mermaid-diagrams)
|
||||
- [hexo-tag-mermaid](https://github.com/JameChou/hexo-tag-mermaid)
|
||||
- [hexo-mermaid-diagrams](https://github.com/mslxl/hexo-mermaid-diagrams)
|
||||
|
||||
## CMS
|
||||
|
||||
- [VuePress](https://vuepress.vuejs.org/)
|
||||
- [Plugin for Mermaid.js](https://github.com/eFrane/vuepress-plugin-mermaidjs)
|
||||
- [vuepress-plugin-mermaidjs-cli](https://github.com/gwleclerc/vuepress-plugin-mermaidjs-cli)
|
||||
- [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)
|
||||
|
||||
## Communication
|
||||
|
||||
- [Discourse](https://discourse.org)
|
||||
- [Mermaid Plugin](https://github.com/pnewell/discourse-mermaid), [And](https://github.com/unfoldingWord-dev/discourse-mermaid)
|
||||
- [Mattermost](https://mattermost.com/)
|
||||
- [Mermaid Plugin](https://github.com/SpikeTings/Mermaid)
|
||||
- [phpBB](https://phpbb.com)
|
||||
- [phpbb-ext-mermaid](https://github.com/AlfredoRamos/phpbb-ext-mermaid)
|
||||
- [NodeBB](https://nodebb.org)
|
||||
- [Mermaid Plugin](https://www.npmjs.com/package/nodebb-plugin-mermaid)
|
||||
|
||||
## Wikis
|
||||
|
||||
- [MediaWiki](https://www.mediawiki.org)
|
||||
- [Mermaid Extension](https://www.mediawiki.org/wiki/Extension:Mermaid)
|
||||
- [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)
|
||||
- [Mermaid Plugin](https://foswiki.org/Extensions/MermaidPlugin)
|
||||
- [DokuWiki](https://dokuwiki.org)
|
||||
- [Flowcharts](https://www.dokuwiki.org/plugin:flowcharts?s[]=mermaid)
|
||||
- [ComboStrap](https://combostrap.com/mermaid)
|
||||
- [TiddlyWiki](https://tiddlywiki.com/)
|
||||
- [mermaid-tw5: full js library](https://github.com/efurlanm/mermaid-tw5)
|
||||
- [tw5-mermaid: wrapper for Mermaid Live](https://github.com/jasonmhoule/tw5-mermaid)
|
||||
|
||||
## Editor Plugins
|
||||
|
||||
- [Vs Code](https://code.visualstudio.com/)
|
||||
- [Markdown Preview Mermaid Support](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid)
|
||||
- [Mermaid Preview](https://marketplace.visualstudio.com/items?itemName=vstirbu.vscode-mermaid-preview)
|
||||
- [Mermaid Markdown Syntax Highlighting](https://marketplace.visualstudio.com/items?itemName=bpruitt-goddard.mermaid-markdown-syntax-highlighting)
|
||||
- [Mermaid Editor](https://marketplace.visualstudio.com/items?itemName=tomoyukim.vscode-mermaid-editor)
|
||||
- [Mermaid Export](https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.mermaid-export)
|
||||
- [Markdown PDF](https://marketplace.visualstudio.com/items?itemName=yzane.markdown-pdf)
|
||||
- [Preview](https://marketplace.visualstudio.com/items?itemName=searKing.preview-vscode)
|
||||
- [Preview Sequence Diagrams](https://marketplace.visualstudio.com/items?itemName=arichika.previewseqdiag-vscode)
|
||||
- [Markdown-It](https://github.com/markdown-it/markdown-it)
|
||||
- [Textual UML Parser](https://github.com/manastalukdar/markdown-it-textual-uml)
|
||||
- [Mermaid Plugin](https://github.com/tylingsoft/markdown-it-mermaid)
|
||||
- [md-it-mermaid](https://github.com/iamcco/md-it-mermaid)
|
||||
- [markdown-it-mermaid-fence-new](https://github.com/Revomatico/markdown-it-mermaid-fence-new)
|
||||
- [markdown-it-mermaid-less](https://github.com/searKing/markdown-it-mermaid-less)
|
||||
- [Atom](https://atom.io)
|
||||
- [Markdown Preview Enhanced](https://atom.io/packages/markdown-preview-enhanced)
|
||||
- [Atom Mermaid](https://atom.io/packages/atom-mermaid)
|
||||
- [Language Mermaid Syntax Highlighter](https://atom.io/packages/language-mermaid)
|
||||
- [Sublime Text 3](https://sublimetext.com)
|
||||
- [Mermaid Package](https://packagecontrol.io/packages/Mermaid)
|
||||
- [Astah](http://astah.net)
|
||||
- [Export to Mermaid](https://github.com/Avens666/Astah_Jude_UML_export_to_Markdown-mermaid-Plantuml-)
|
||||
- [Light Table](http://lighttable.com/)
|
||||
- [Mermaid Plugin](https://github.com/cldwalker/Mermaid)
|
||||
- [Draw.io](http://draw.io) - [Plugin](https://github.com/nopeslide/drawio_mermaid_plugin)
|
||||
- [Inkdrop](http://inkdrop.app) - [Plugin](https://github.com/inkdropapp/inkdrop-mermaid)
|
||||
- [Vim](https://vim.org)
|
||||
- [Vim Diagram Syntax](https://github.com/zhaozg/vim-diagram)
|
||||
- [GNU Emacs](https://www.gnu.org/software/emacs/)
|
||||
- [Major mode for .mmd files](https://github.com/abrochard/mermaid-mode)
|
||||
- [Org-Mode integration](https://github.com/arnm/ob-mermaid)
|
||||
- [Brackets](http://brackets.io/)
|
||||
- [Mermaid Preview](https://s3.amazonaws.com/extend.brackets/alanhohn.mermaid-preview/alanhohn.mermaid-preview-1.0.2.zip)
|
||||
- [Iodide](https://github.com/iodide-project/iodide)
|
||||
- [iodide-mermaid-plugin](https://github.com/iodide-project/iodide-mermaid-plugin)
|
||||
- [Google docs](https://docs.google.com/)
|
||||
- [Mermaid plugin for google docs](https://workspace.google.com/marketplace/app/mermaid/636321283856)
|
||||
- [Podlite](https://github.com/zag/podlite-desktop)
|
||||
- [Named block =Diagram](https://github.com/zag/podlite/tree/main/packages/podlite-diagrams)
|
||||
- [GNU Nano](https://www.nano-editor.org/)
|
||||
- [Nano Mermaid](https://github.com/Yash-Singh1/nano-mermaid)
|
||||
|
||||
## Document Generation
|
||||
|
||||
- [Sphinx](https://www.sphinx-doc.org/en/master/)
|
||||
- [sphinxcontrib-mermaid](https://github.com/mgaitan/sphinxcontrib-mermaid)
|
||||
- [remark.js](https://remark.js.org/)
|
||||
- [remark-mermaid](https://github.com/temando/remark-mermaid)
|
||||
- [jSDoc](https://jsdoc.app/)
|
||||
- [jsdoc-mermaid](https://github.com/Jellyvision/jsdoc-mermaid)
|
||||
- [MkDocs](https://mkdocs.org)
|
||||
- [mkdocs-mermaid2-plugin](https://github.com/fralau/mkdocs-mermaid2-plugin)
|
||||
- [Type Doc](https://typedoc.org/)
|
||||
- [typedoc-plugin-mermaid](https://www.npmjs.com/package/typedoc-plugin-mermaid)
|
||||
- [Docsy Hugo Theme](https://www.docsy.dev/docs/adding-content/lookandfeel/#diagrams-with-mermaid) (Native support in theme)
|
||||
- [Codedoc](https://codedoc.cc/)
|
||||
- [codedoc-mermaid-plugin](https://www.npmjs.com/package/codedoc-mermaid-plugin)
|
||||
|
||||
## Browser Extensions
|
||||
|
||||
| Name | Chrome Web Store | Firefox Add-ons | Opera | Edge | Source/Repository |
|
||||
| -- | -- | -- | -- | -- | -- |
|
||||
| GitHub + Mermaid | [🎡🔗](https://chrome.google.com/webstore/detail/github-%20-mermaid/goiiopgdnkogdbjmncgedmgpoajilohe) | [🦊🔗](https://addons.mozilla.org/firefox/addon/github-mermaid/) | - | - | [🐙🔗](https://github.com/BackMarket/github-mermaid-extension)
|
||||
| Asciidoctor Live Preview | [🎡🔗](https://chrome.google.com/webstore/detail/asciidoctorjs-live-previe/iaalpfgpbocpdfblpnhhgllgbdbchmia) | - | - | [🌀🔗](https://microsoftedge.microsoft.com/addons/detail/asciidoctorjs-live-previ/pefkelkanablhjdekgdahplkccnbdggd?hl=en-US) | -|
|
||||
| Diagram Tab| -| - | - | - | [🐙🔗](https://github.com/khafast/diagramtab) |
|
||||
| Markdown Diagrams| [🎡🔗](https://chrome.google.com/webstore/detail/markdown-diagrams/pmoglnmodacnbbofbgcagndelmgaclel/) | [🦊🔗](https://addons.mozilla.org/en-US/firefox/addon/markdown-diagrams/) | [🔴🔗](https://addons.opera.com/en/extensions/details/markdown-diagrams/) | [🌀🔗](https://microsoftedge.microsoft.com/addons/detail/markdown-diagrams/hceenoomhhdkjjijnmlclkpenkapfihe) | [🐙🔗](https://github.com/marcozaccari/markdown-diagrams-browser-extension/tree/master/doc/examples) |
|
||||
| Markdown Viewer| - | [🦊🔗](https://addons.mozilla.org/en-US/firefox/addon/markdown-viewer-chrome/) | - | - | [🐙🔗](https://github.com/simov/markdown-viewer)|
|
||||
| Extensions for Mermaid| - | [🦊🔗](https://addons.mozilla.org/en-US/firefox/addon/markdown-viewer-chrome/) | [🔴🔗](https://addons.opera.com/en/extensions/details/extensions-for-mermaid/)| - | [🐙🔗](https://github.com/Stefan-S/mermaid-extension) |
|
||||
| Chrome Diagrammer| [🎡🔗](https://chrome.google.com/webstore/detail/chrome-diagrammer/bkpbgjmkomfoakfklcjeoegkklgjnnpk) | - |- | - | - |
|
||||
| Mermaid Diagrams | [🎡🔗](https://chrome.google.com/webstore/detail/mermaid-diagrams/phfcghedmopjadpojhmmaffjmfiakfil) | - | - | - | - |
|
||||
|Mermaid Markdown | [🎡🔗](https://chrome.google.com/webstore/detail/mermaid-markdown/mboeoikjijmjcjgpccghbcoegikliijg) | - | - | - | - |
|
||||
| Monkeys | [🎡🔗](https://chrome.google.com/webstore/detail/monkeys-mermaid-for-githu/cplfdpoajbclbgphaphphcldamfkjlgi) | - | - | - | - |
|
||||
| Mermaid Previewer | [🎡🔗](https://chrome.google.com/webstore/detail/mermaid-previewer/oidjnlhbegipkcklbdfnbkikplpghfdl) | - | - | - | - |
|
||||
|
||||
|
||||
## Other
|
||||
- [Jekyll](https://jekyllrb.com/)
|
||||
- [jekyll-mermaid](https://rubygems.org/gems/jekyll-mermaid)
|
||||
- [jekyll-mermaid-diagrams](https://github.com/fuzhibo/jekyll-mermaid-diagrams)
|
||||
- [Reveal.js](https://github.com/hakimel/reveal.js)
|
||||
- [reveal.js-mermaid-plugin](https://github.com/ludwick/reveal.js-mermaid-plugin)
|
||||
- [Bisheng](https://www.npmjs.com/package/bisheng)
|
||||
- [bisheng-plugin-mermaid](https://github.com/yct21/bisheng-plugin-mermaid)
|
||||
- [Reveal CK](https://github.com/jedcn/reveal-ck)
|
||||
- [reveal-ck-mermaid-plugin](https://github.com/tmtm/reveal-ck-mermaid-plugin)
|
||||
- [mermaid-server: Generate diagrams using a HTTP request](https://github.com/TomWright/mermaid-server)
|
||||
@@ -118,7 +118,7 @@ c. The `mermaid.initialize()` call, which dictates the appearance of diagrams an
|
||||
```
|
||||
|
||||
**Notes**:
|
||||
Rendering in Mermaid is initalized by `mermaid.initialize()` call. You can place `mermaid.initialize()` inside `mermaid.min.js` for brevity. However, doing the opposite lets you control when it starts looking for `<div>`tags inside the web page with `mermaid.initialize()`. This is useful when you think that not all `<div>` tags may have loaded on the execution of `mermaid.min.js` file.
|
||||
Rendering in Mermaid is initialized by `mermaid.initialize()` call. You can place `mermaid.initialize()` inside `mermaid.min.js` for brevity. However, doing the opposite lets you control when it starts looking for `<div>`tags inside the web page with `mermaid.initialize()`. This is useful when you think that not all `<div>` tags may have loaded on the execution of `mermaid.min.js` file.
|
||||
|
||||
`startOnLoad` is one of the parameters that can be defined by `mermaid.initialize()`
|
||||
|
||||
|
||||
@@ -15,3 +15,8 @@ You may also reach out to the team via our public Slack chat channels; however,
|
||||
Keep current with the latest Mermaid releases. We regularly update Mermaid, and these updates may fix security defects discovered in previous versions. Check the Mermaid release notes for security-related updates.
|
||||
|
||||
Keep your application’s dependencies up to date. Make sure you upgrade your package dependencies to keep the dependencies up to date. Avoid pinning to specific versions for your dependencies and, if you do, make sure you check periodically to see if your dependencies have had security updates, and update the pin accordingly.
|
||||
|
||||
|
||||
## Configuring DomPurify
|
||||
|
||||
By default Mermaid uses a baseline [DOMPurify](https://github.com/cure53/DOMPurify) config. It is possible to override the options passed to DOMPurify by adding a `dompurifyConfig` key to the Mermaid options. This could potentially break the output of Mermaid so use this with caution.
|
||||
@@ -351,7 +351,7 @@ links <actor>: <json-formatted link-name link-url pairs>
|
||||
|
||||
An example is below:
|
||||
|
||||
```mmd
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
participant Alice
|
||||
participant John
|
||||
|
||||
504
docs/sequenceDiagram.md~HEAD
Normal file
504
docs/sequenceDiagram.md~HEAD
Normal file
@@ -0,0 +1,504 @@
|
||||
# Sequence diagrams
|
||||
|
||||
**Edit this Page** [](https://github.com/mermaid-js/mermaid/blob/develop/docs/sequenceDiagram.md)
|
||||
> A Sequence diagram is an interaction diagram that shows how processes operate with one another and in what order.
|
||||
|
||||
Mermaid can render sequence diagrams.
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
Alice->>John: Hello John, how are you?
|
||||
John-->>Alice: Great!
|
||||
Alice-)John: See you later!
|
||||
```
|
||||
|
||||
```note
|
||||
A note on nodes, the word "end" could potentially break the diagram, due to the way that the mermaid language is scripted.
|
||||
|
||||
If unavoidable, one must use parentheses(), quotation marks "", or brackets {},[], to enclose the word "end". i.e : (end), [end], {end}.
|
||||
```
|
||||
|
||||
## 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
|
||||
sequenceDiagram
|
||||
participant Alice
|
||||
participant Bob
|
||||
Alice->>Bob: Hi Bob
|
||||
Bob->>Alice: Hi Alice
|
||||
```
|
||||
|
||||
### Actors
|
||||
|
||||
If you specifically want to use the actor symbol instead of a rectangle with text you can do so by using actor statements as per below.
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
actor Alice
|
||||
actor Bob
|
||||
Alice->>Bob: Hi Bob
|
||||
Bob->>Alice: Hi Alice
|
||||
```
|
||||
|
||||
### Aliases
|
||||
|
||||
The actor can have a convenient identifier and a descriptive label.
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
participant A as Alice
|
||||
participant J as John
|
||||
A->>J: Hello John, how are you?
|
||||
J->>A: Great!
|
||||
```
|
||||
|
||||
## Messages
|
||||
|
||||
Messages can be of two displayed either solid or with a dotted line.
|
||||
|
||||
```
|
||||
[Actor][Arrow][Actor]:Message text
|
||||
```
|
||||
|
||||
There are six types of arrows currently supported:
|
||||
|
||||
| Type | Description |
|
||||
| ---- | ------------------------------------------- |
|
||||
| -> | Solid line without arrow |
|
||||
| --> | Dotted line without arrow |
|
||||
| ->> | Solid line with arrowhead |
|
||||
| -->> | Dotted line with arrowhead |
|
||||
| -x | Solid line with a cross at the end |
|
||||
| --x | Dotted line with a cross at the end. |
|
||||
| -) | Solid line with an open arrow at the end (async) |
|
||||
| --) | Dotted line with a open arrow at the end (async) |
|
||||
|
||||
## Activations
|
||||
|
||||
It is possible to activate and deactivate an actor. (de)activation can be dedicated declarations:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
Alice->>John: Hello John, how are you?
|
||||
activate John
|
||||
John-->>Alice: Great!
|
||||
deactivate John
|
||||
```
|
||||
|
||||
There is also a shortcut notation by appending `+`/`-` suffix to the message arrow:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
Alice->>+John: Hello John, how are you?
|
||||
John-->>-Alice: Great!
|
||||
```
|
||||
|
||||
Activations can be stacked for same actor:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
Alice->>+John: Hello John, how are you?
|
||||
Alice->>+John: John, can you hear me?
|
||||
John-->>-Alice: Hi Alice, I can hear you!
|
||||
John-->>-Alice: I feel great!
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
It is possible to add notes to a sequence diagram. This is done by the notation
|
||||
Note [ right of | left of | over ] [Actor]: Text in note content
|
||||
|
||||
See the example below:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
participant John
|
||||
Note right of John: Text in note
|
||||
```
|
||||
|
||||
It is also possible to create notes spanning two participants:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
Alice->John: Hello John, how are you?
|
||||
Note over Alice,John: A typical interaction
|
||||
```
|
||||
|
||||
## Loops
|
||||
|
||||
It is possible to express loops in a sequence diagram. This is done by the notation
|
||||
|
||||
```
|
||||
loop Loop text
|
||||
... statements ...
|
||||
end
|
||||
```
|
||||
|
||||
See the example below:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
Alice->John: Hello John, how are you?
|
||||
loop Every minute
|
||||
John-->Alice: Great!
|
||||
end
|
||||
```
|
||||
|
||||
## Alt
|
||||
|
||||
It is possible to express alternative paths in a sequence diagram. This is done by the notation
|
||||
|
||||
```
|
||||
alt Describing text
|
||||
... statements ...
|
||||
else
|
||||
... statements ...
|
||||
end
|
||||
```
|
||||
|
||||
or if there is sequence that is optional (if without else).
|
||||
|
||||
```
|
||||
opt Describing text
|
||||
... statements ...
|
||||
end
|
||||
```
|
||||
|
||||
See the example below:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
Alice->>Bob: Hello Bob, how are you?
|
||||
alt is sick
|
||||
Bob->>Alice: Not so good :(
|
||||
else is well
|
||||
Bob->>Alice: Feeling fresh like a daisy
|
||||
end
|
||||
opt Extra response
|
||||
Bob->>Alice: Thanks for asking
|
||||
end
|
||||
```
|
||||
|
||||
## Parallel
|
||||
|
||||
It is possible to show actions that are happening in parallel.
|
||||
|
||||
This is done by the notation
|
||||
|
||||
```
|
||||
par [Action 1]
|
||||
... statements ...
|
||||
and [Action 2]
|
||||
... statements ...
|
||||
and [Action N]
|
||||
... statements ...
|
||||
end
|
||||
```
|
||||
|
||||
See the example below:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
par Alice to Bob
|
||||
Alice->>Bob: Hello guys!
|
||||
and Alice to John
|
||||
Alice->>John: Hello guys!
|
||||
end
|
||||
Bob-->>Alice: Hi Alice!
|
||||
John-->>Alice: Hi Alice!
|
||||
```
|
||||
|
||||
It is also possible to nest parallel blocks.
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
par Alice to Bob
|
||||
Alice->>Bob: Go help John
|
||||
and Alice to John
|
||||
Alice->>John: I want this done today
|
||||
par John to Charlie
|
||||
John->>Charlie: Can we do this today?
|
||||
and John to Diana
|
||||
John->>Diana: Can you help us today?
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
## Background Highlighting
|
||||
|
||||
It is possible to highlight flows by providing colored background rects. This is done by the notation
|
||||
|
||||
The colors are defined using rgb and rgba syntax.
|
||||
|
||||
```
|
||||
rect rgb(0, 255, 0)
|
||||
... content ...
|
||||
end
|
||||
```
|
||||
|
||||
```
|
||||
rect rgba(0, 0, 255, .1)
|
||||
... content ...
|
||||
end
|
||||
```
|
||||
|
||||
See the examples below:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
participant Alice
|
||||
participant John
|
||||
|
||||
rect rgb(191, 223, 255)
|
||||
note right of Alice: Alice calls John.
|
||||
Alice->>+John: Hello John, how are you?
|
||||
rect rgb(200, 150, 255)
|
||||
Alice->>+John: John, can you hear me?
|
||||
John-->>-Alice: Hi Alice, I can hear you!
|
||||
end
|
||||
John-->>-Alice: I feel great!
|
||||
end
|
||||
Alice ->>+ John: Did you want to go to the game tonight?
|
||||
John -->>- Alice: Yeah! See you there.
|
||||
|
||||
```
|
||||
|
||||
## Comments
|
||||
|
||||
Comments can be entered within a sequence diagram, which will be ignored by the parser. Comments need to be on their own line, and must be prefaced with `%%` (double percent signs). Any text after the start of the comment to the next newline will be treated as a comment, including any diagram syntax
|
||||
|
||||
```mmd
|
||||
sequenceDiagram
|
||||
Alice->>John: Hello John, how are you?
|
||||
%% this is a comment
|
||||
John-->>Alice: Great!
|
||||
```
|
||||
|
||||
## Entity codes to escape characters
|
||||
|
||||
It is possible to escape characters using the syntax exemplified here.
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
A->>B: I #9829; you!
|
||||
B->>A: I #9829; you #infin; times more!
|
||||
```
|
||||
|
||||
Numbers given are base 10, so `#` can be encoded as `#35;`. It is also supported to use HTML character names.
|
||||
|
||||
Because semicolons can be used instead of line breaks to define the markup, you need to use `#59;` to include a semicolon in message text.
|
||||
|
||||
## sequenceNumbers
|
||||
|
||||
It is possible to get a sequence number attached to each arrow in a sequence diagram. This can be configured when adding mermaid to the website as shown below:
|
||||
|
||||
```html
|
||||
<script>
|
||||
mermaid.initialize({
|
||||
sequence: { showSequenceNumbers: true },
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
It can also be be turned on via the diagram code as in the diagram:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
Alice->>John: Hello John, how are you?
|
||||
loop Healthcheck
|
||||
John->>John: Fight against hypochondria
|
||||
end
|
||||
Note right of John: Rational thoughts!
|
||||
John-->>Alice: Great!
|
||||
John->>Bob: How about you?
|
||||
Bob-->>John: Jolly good!
|
||||
```
|
||||
|
||||
## Actor Menus
|
||||
|
||||
Actors can have popup-menus containing individualized links to external pages. For example, if an actor represented a web service, useful links might include a link to the service health dashboard, repo containing the code for the service, or a wiki page describing the service.
|
||||
|
||||
This can be configured by adding one or more link lines with the format:
|
||||
```
|
||||
link <actor>: <link-label> @ <link-url>
|
||||
```
|
||||
```mmd
|
||||
sequenceDiagram
|
||||
participant Alice
|
||||
participant John
|
||||
link Alice: Dashboard @ https://dashboard.contoso.com/alice
|
||||
link Alice: Wiki @ https://wiki.contoso.com/alice
|
||||
link John: Dashboard @ https://dashboard.contoso.com/john
|
||||
link John: Wiki @ https://wiki.contoso.com/john
|
||||
Alice->>John: Hello John, how are you?
|
||||
John-->>Alice: Great!
|
||||
Alice-)John: See you later!
|
||||
```
|
||||
|
||||
#### Advanced Menu Syntax
|
||||
There is an advanced syntax that relies on JSON formatting. If you are comfortable with JSON format, then this exists as well.
|
||||
|
||||
This can be configured by adding the links lines with the format:
|
||||
|
||||
```
|
||||
links <actor>: <json-formatted link-name link-url pairs>
|
||||
```
|
||||
|
||||
An example is below:
|
||||
|
||||
```mmd
|
||||
sequenceDiagram
|
||||
participant Alice
|
||||
participant John
|
||||
links Alice: {"Dashboard": "https://dashboard.contoso.com/alice", "Wiki": "https://wiki.contoso.com/alice"}
|
||||
links John: {"Dashboard": "https://dashboard.contoso.com/john", "Wiki": "https://wiki.contoso.com/john"}
|
||||
Alice->>John: Hello John, how are you?
|
||||
John-->>Alice: Great!
|
||||
Alice-)John: See you later!
|
||||
```
|
||||
|
||||
## Styling
|
||||
|
||||
Styling of a sequence diagram is done by defining a number of css classes. During rendering these classes are extracted from the file located at src/themes/sequence.scss
|
||||
|
||||
### Classes used
|
||||
|
||||
| Class | Description |
|
||||
| ------------ | ----------------------------------------------------------- |
|
||||
| actor | Style for the actor box at the top of the diagram. |
|
||||
| text.actor | Styles for text in the actor box at the top of the diagram. |
|
||||
| actor-line | The vertical line for an actor. |
|
||||
| messageLine0 | Styles for the solid message line. |
|
||||
| messageLine1 | Styles for the dotted message line. |
|
||||
| messageText | Defines styles for the text on the message arrows. |
|
||||
| labelBox | Defines styles label to left in a loop. |
|
||||
| labelText | Styles for the text in label for loops. |
|
||||
| loopText | Styles for the text in the loop box. |
|
||||
| loopLine | Defines styles for the lines in the loop box. |
|
||||
| note | Styles for the note box. |
|
||||
| noteText | Styles for the text on in the note boxes. |
|
||||
|
||||
### Sample stylesheet
|
||||
|
||||
```css
|
||||
body {
|
||||
background: white;
|
||||
}
|
||||
|
||||
.actor {
|
||||
stroke: #ccccff;
|
||||
fill: #ececff;
|
||||
}
|
||||
text.actor {
|
||||
fill: black;
|
||||
stroke: none;
|
||||
font-family: Helvetica;
|
||||
}
|
||||
|
||||
.actor-line {
|
||||
stroke: grey;
|
||||
}
|
||||
|
||||
.messageLine0 {
|
||||
stroke-width: 1.5;
|
||||
stroke-dasharray: '2 2';
|
||||
marker-end: 'url(#arrowhead)';
|
||||
stroke: black;
|
||||
}
|
||||
|
||||
.messageLine1 {
|
||||
stroke-width: 1.5;
|
||||
stroke-dasharray: '2 2';
|
||||
stroke: black;
|
||||
}
|
||||
|
||||
#arrowhead {
|
||||
fill: black;
|
||||
}
|
||||
|
||||
.messageText {
|
||||
fill: black;
|
||||
stroke: none;
|
||||
font-family: 'trebuchet ms', verdana, arial;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.labelBox {
|
||||
stroke: #ccccff;
|
||||
fill: #ececff;
|
||||
}
|
||||
|
||||
.labelText {
|
||||
fill: black;
|
||||
stroke: none;
|
||||
font-family: 'trebuchet ms', verdana, arial;
|
||||
}
|
||||
|
||||
.loopText {
|
||||
fill: black;
|
||||
stroke: none;
|
||||
font-family: 'trebuchet ms', verdana, arial;
|
||||
}
|
||||
|
||||
.loopLine {
|
||||
stroke-width: 2;
|
||||
stroke-dasharray: '2 2';
|
||||
marker-end: 'url(#arrowhead)';
|
||||
stroke: #ccccff;
|
||||
}
|
||||
|
||||
.note {
|
||||
stroke: #decc93;
|
||||
fill: #fff5ad;
|
||||
}
|
||||
|
||||
.noteText {
|
||||
fill: black;
|
||||
stroke: none;
|
||||
font-family: 'trebuchet ms', verdana, arial;
|
||||
font-size: 14px;
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Is it possible to adjust the margins for rendering the sequence diagram.
|
||||
|
||||
This is done by defining `mermaid.sequenceConfig` or by the CLI to use a json file with the configuration.
|
||||
How to use the CLI is described in the [mermaidCLI](mermaidCLI) page.
|
||||
`mermaid.sequenceConfig` can be set to a JSON string with config parameters or the corresponding object.
|
||||
|
||||
```javascript
|
||||
mermaid.sequenceConfig = {
|
||||
diagramMarginX: 50,
|
||||
diagramMarginY: 10,
|
||||
boxTextMargin: 5,
|
||||
noteMargin: 10,
|
||||
messageMargin: 35,
|
||||
mirrorActors: true
|
||||
};
|
||||
```
|
||||
|
||||
### Possible configuration parameters:
|
||||
|
||||
| Parameter | Description | Default value |
|
||||
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------ |
|
||||
| mirrorActors | Turns on/off the rendering of actors below the diagram as well as above it | false |
|
||||
| bottomMarginAdj | Adjusts how far down the graph ended. Wide borders styles with css could generate unwanted clipping which is why this config param exists. | 1 |
|
||||
| actorFontSize | Sets the font size for the actor's description | 14 |
|
||||
| actorFontFamily | Sets the font family for the actor's description | "Open-Sans", "sans-serif" |
|
||||
| actorFontWeight | Sets the font weight for the actor's description | "Open-Sans", "sans-serif" |
|
||||
| noteFontSize | Sets the font size for actor-attached notes | 14 |
|
||||
| noteFontFamily | Sets the font family for actor-attached notes | "trebuchet ms", verdana, arial |
|
||||
| noteFontWeight | Sets the font weight for actor-attached notes | "trebuchet ms", verdana, arial |
|
||||
| noteAlign | Sets the text alignment for text in actor-attached notes | center |
|
||||
| messageFontSize | Sets the font size for actor<->actor messages | 16 |
|
||||
| messageFontFamily | Sets the font family for actor<->actor messages | "trebuchet ms", verdana, arial |
|
||||
| messageFontWeight | Sets the font weight for actor<->actor messages | "trebuchet ms", verdana, arial |
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
**Edit this Page** [](https://github.com/mermaid-js/mermaid/blob/develop/docs/theming.md)
|
||||
|
||||
With Version 8.7.0 Mermaid comes out with a system for dynamic and integrated configuration of themes. The intent is to increase the customizability and ease of Styling for mermaid diagrams.
|
||||
With Version 8.7.0 Mermaid comes out with a system for dynamic and integrated configuration of themes. The intent is to increase the customizability and ease of styling for mermaid diagrams.
|
||||
|
||||
The theme can be altered by changing the root level variable `theme` variable in the configuration. To change it for the whole site you must use the `initialize` call. To do it for just for a single diagram you can use the `%%init%%` directive
|
||||
|
||||
@@ -24,7 +24,7 @@ The following are a list of **Deployable themes**, sample `%%init%%` directives
|
||||
## Site-wide Themes
|
||||
Site-wide themes are declared via `initialize` by site owners.
|
||||
|
||||
Example of `Initalize` call setting `theme` to `base`:
|
||||
Example of `Initialize` call setting `theme` to `base`:
|
||||
```javascript
|
||||
mermaidAPI.initialize({
|
||||
'securityLevel': 'loose', 'theme': 'base'
|
||||
@@ -99,7 +99,7 @@ Leaving it empty will set all variable values to default.
|
||||
|
||||
## Color and Color Calculation:
|
||||
|
||||
Color definitions have certain interactions in mermaid, this is in order to ensure visibility for diagrams. mermaid will adjust some variables automatically, when colors are changed in order to compensate and maintain readability.
|
||||
Color definitions have certain interactions in mermaid, this is in order to ensure visibility for diagrams. Mermaid will adjust some variables automatically, when colors are changed in order to compensate and maintain readability.
|
||||
|
||||
**The Default Value Column** to the right of the Variable column will denote the Variable paired/associated with the Variable on the left and the nature of this pairing or association. If it for instance says primaryColor it means that it gets primaryColor as default value. If it says "based on primaryColor" it means that it is calculated/ derived from primaryColor. This calculation can be primary color inversion, a change of hue, darkening or lightening by 10%, etc.
|
||||
|
||||
|
||||
11
launch.json
Normal file
11
launch.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "attach",
|
||||
"name": "Attach",
|
||||
"port": 9229
|
||||
}
|
||||
]
|
||||
}
|
||||
12
package.json
12
package.json
@@ -30,7 +30,7 @@
|
||||
"lint": "eslint ./ --ext js,html",
|
||||
"lint:fix": "yarn lint --fix",
|
||||
"e2e:depr": "yarn lint && jest e2e --config e2e/jest.config.js",
|
||||
"cypress": "percy exec -- cypress run",
|
||||
"cypress": "cypress run",
|
||||
"e2e": "start-server-and-test dev http://localhost:9000/ cypress",
|
||||
"e2e-upd": "yarn lint && jest e2e -u --config e2e/jest.config.js",
|
||||
"dev": "webpack serve --config ./.webpack/webpack.config.e2e.babel.js",
|
||||
@@ -57,7 +57,8 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@braintree/sanitize-url": "^3.1.0",
|
||||
"@braintree/sanitize-url": "^6.0.0",
|
||||
"cypress-image-snapshot": "^4.0.1",
|
||||
"d3": "^7.0.0",
|
||||
"dagre": "^0.8.5",
|
||||
"dagre-d3": "^0.6.4",
|
||||
@@ -76,23 +77,20 @@
|
||||
"@babel/register": "^7.14.5",
|
||||
"@commitlint/cli": "^16.0.0",
|
||||
"@commitlint/config-conventional": "^16.0.0",
|
||||
"@percy/cli": "^1.0.0-beta.58",
|
||||
"@percy/cypress": "^3.1.0",
|
||||
"@percy/migrate": "^0.11.0",
|
||||
"babel-jest": "^27.0.6",
|
||||
"babel-loader": "^8.2.2",
|
||||
"concurrently": "^7.0.0",
|
||||
"coveralls": "^3.0.2",
|
||||
"css-loader": "^6.6.0",
|
||||
"css-to-string-loader": "^0.1.3",
|
||||
"cypress": "9.5.0",
|
||||
"cypress": "9.5.2",
|
||||
"documentation": "13.2.0",
|
||||
"eslint": "^8.2.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-cypress": "^2.12.1",
|
||||
"eslint-plugin-html": "^6.2.0",
|
||||
"eslint-plugin-jest": "^26.0.0",
|
||||
"eslint-plugin-jsdoc": "^37.0.3",
|
||||
"eslint-plugin-jsdoc": "^38.0.3",
|
||||
"eslint-plugin-markdown": "^2.2.1",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"husky": "^7.0.1",
|
||||
|
||||
@@ -9,15 +9,16 @@
|
||||
* @param id
|
||||
*/
|
||||
export default function addSVGAccessibilityFields(yy_parser, svg, id) {
|
||||
if (typeof svg.insert == 'undefined') {
|
||||
return;
|
||||
}
|
||||
let title_string = yy_parser.getTitle();
|
||||
let description = yy_parser.getAccDescription();
|
||||
svg.attr('role', 'img').attr('aria-labelledby', 'chart-title-' + id + ' chart-desc-' + id);
|
||||
|
||||
svg
|
||||
.insert('desc', ':first-child')
|
||||
.attr('id', 'chart-desc-' + id)
|
||||
.text(description);
|
||||
|
||||
svg
|
||||
.insert('title', ':first-child')
|
||||
.attr('id', 'chart-title-' + id)
|
||||
|
||||
@@ -52,7 +52,7 @@ export const updateCurrentConfig = (siteCfg, _directives) => {
|
||||
* **Notes:** Sets the siteConfig. The siteConfig is a protected configuration for repeat use. Calls
|
||||
* to reset() will reset the currentConfig to siteConfig. Calls to reset(configApi.defaultConfig)
|
||||
* will reset siteConfig and currentConfig to the defaultConfig Note: currentConfig is set in this
|
||||
* function *Default value: At default, will mirror Global Config**
|
||||
* function _Default value: At default, will mirror Global Config_
|
||||
*
|
||||
* @param conf - The base currentConfig to use as siteConfig
|
||||
* @returns {object} - The siteConfig
|
||||
|
||||
@@ -100,7 +100,7 @@ const config = {
|
||||
arrowMarkerAbsolute: false,
|
||||
|
||||
/**
|
||||
* This option controls which currentConfig keys are considered *secure* and can only be changed
|
||||
* This option controls which currentConfig keys are considered _secure_ and can only be changed
|
||||
* via call to mermaidAPI.initialize. Calls to mermaidAPI.reinitialize cannot make changes to the
|
||||
* `secure` keys in the current currentConfig. This prevents malicious graph directives from
|
||||
* overriding a site's default security.
|
||||
@@ -1064,6 +1064,25 @@ const config = {
|
||||
rect_padding: 10,
|
||||
line_height: 20,
|
||||
},
|
||||
gitGraph: {
|
||||
diagramPadding: 8,
|
||||
nodeSpacing: 150,
|
||||
nodeFillColor: 'yellow',
|
||||
nodeStrokeWidth: 2,
|
||||
nodeStrokeColor: 'grey',
|
||||
lineStrokeWidth: 4,
|
||||
branchOffset: 50,
|
||||
lineColor: 'grey',
|
||||
leftMargin: 50,
|
||||
branchColors: ['#442f74', '#983351', '#609732', '#AA9A39'],
|
||||
nodeRadius: 10,
|
||||
nodeLabel: {
|
||||
width: 75,
|
||||
height: 100,
|
||||
x: -25,
|
||||
y: 0,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
config.class.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||||
|
||||
@@ -746,7 +746,7 @@ foo()
|
||||
parser.parse(str);
|
||||
|
||||
const testClass = parser.yy.getClass('Class1');
|
||||
expect(testClass.link).toBe('about:blank'); //('google.com'); security needs to be set to 'loose' for this to work right
|
||||
expect(testClass.link).toBe('google.com');
|
||||
expect(testClass.cssClasses.length).toBe(1);
|
||||
expect(testClass.cssClasses[0]).toBe('clickable');
|
||||
});
|
||||
@@ -760,7 +760,7 @@ foo()
|
||||
parser.parse(str);
|
||||
|
||||
const testClass = parser.yy.getClass('Class1');
|
||||
expect(testClass.link).toBe('about:blank'); //('google.com'); security needs to be set to 'loose' for this to work right
|
||||
expect(testClass.link).toBe('google.com');
|
||||
expect(testClass.cssClasses.length).toBe(1);
|
||||
expect(testClass.cssClasses[0]).toBe('clickable');
|
||||
});
|
||||
@@ -774,7 +774,7 @@ foo()
|
||||
parser.parse(str);
|
||||
|
||||
const testClass = parser.yy.getClass('Class1');
|
||||
expect(testClass.link).toBe('about:blank'); //('google.com'); security needs to be set to 'loose' for this to work right
|
||||
expect(testClass.link).toBe('google.com');
|
||||
expect(testClass.tooltip).toBe('A tooltip');
|
||||
expect(testClass.cssClasses.length).toBe(1);
|
||||
expect(testClass.cssClasses[0]).toBe('clickable');
|
||||
@@ -789,7 +789,7 @@ foo()
|
||||
parser.parse(str);
|
||||
|
||||
const testClass = parser.yy.getClass('Class1');
|
||||
expect(testClass.link).toBe('about:blank'); //('google.com'); security needs to be set to 'loose' for this to work right
|
||||
expect(testClass.link).toBe('google.com');
|
||||
expect(testClass.tooltip).toBe('A tooltip');
|
||||
expect(testClass.cssClasses.length).toBe(1);
|
||||
expect(testClass.cssClasses[0]).toBe('clickable');
|
||||
|
||||
@@ -93,7 +93,12 @@ const sanitizeMore = (text, config) => {
|
||||
|
||||
export const sanitizeText = (text, config) => {
|
||||
if (!text) return text;
|
||||
const txt = DOMPurify.sanitize(sanitizeMore(text, config));
|
||||
let txt = '';
|
||||
if (config['dompurifyConfig']) {
|
||||
txt = DOMPurify.sanitize(sanitizeMore(text, config), config['dompurifyConfig']);
|
||||
} else {
|
||||
txt = DOMPurify.sanitize(sanitizeMore(text, config));
|
||||
}
|
||||
return txt;
|
||||
};
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import * as configApi from '../../config';
|
||||
let entities = {};
|
||||
let relationships = [];
|
||||
let title = '';
|
||||
let description = '';
|
||||
|
||||
const Cardinality = {
|
||||
ZERO_OR_ONE: 'ZERO_OR_ONE',
|
||||
@@ -75,6 +76,14 @@ const getTitle = function () {
|
||||
return title;
|
||||
};
|
||||
|
||||
const setAccDescription = function (txt) {
|
||||
description = txt;
|
||||
};
|
||||
|
||||
const getAccDescription = function () {
|
||||
return description;
|
||||
};
|
||||
|
||||
const clear = function () {
|
||||
entities = {};
|
||||
relationships = [];
|
||||
@@ -94,4 +103,6 @@ export default {
|
||||
clear,
|
||||
setTitle,
|
||||
getTitle,
|
||||
setAccDescription,
|
||||
getAccDescription,
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@ import { getConfig } from '../../config';
|
||||
import { log } from '../../logger';
|
||||
import erMarkers from './erMarkers';
|
||||
import { configureSvgSize } from '../../utils';
|
||||
import addSVGAccessibilityFields from '../../accessibility';
|
||||
|
||||
const conf = {};
|
||||
|
||||
@@ -637,6 +638,8 @@ export const draw = function (text, id) {
|
||||
configureSvgSize(svg, height, width, conf.useMaxWidth);
|
||||
|
||||
svg.attr('viewBox', `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`);
|
||||
|
||||
addSVGAccessibilityFields(parser.yy, svg, id);
|
||||
}; // draw
|
||||
|
||||
export default {
|
||||
|
||||
@@ -2,8 +2,14 @@
|
||||
|
||||
%options case-insensitive
|
||||
%x open_directive type_directive arg_directive block
|
||||
%x title
|
||||
%x accDescription
|
||||
|
||||
%%
|
||||
title { this.begin("title");return 'title'; }
|
||||
<title>(?!\n|;|#)*[^\n]* { this.popState(); return "title_value"; }
|
||||
accDescription { this.begin("accDescription");return 'accDescription'; }
|
||||
<accDescription>(?!\n|;|#)*[^\n]* { this.popState(); return "description_value"; }
|
||||
\%\%\{ { this.begin('open_directive'); return 'open_directive'; }
|
||||
<open_directive>((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; }
|
||||
<type_directive>":" { this.popState(); this.begin('arg_directive'); return ':'; }
|
||||
@@ -84,6 +90,8 @@ statement
|
||||
}
|
||||
| entityName BLOCK_START BLOCK_STOP { yy.addEntity($1); }
|
||||
| entityName { yy.addEntity($1); }
|
||||
| title title_value { $$=$2.trim();yy.setTitle($$); }
|
||||
| accDescription description_value { $$=$2.trim();yy.setAccDescription($$); }
|
||||
;
|
||||
|
||||
entityName
|
||||
|
||||
@@ -181,6 +181,17 @@ describe('when parsing ER diagram it...', function () {
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(1);
|
||||
});
|
||||
|
||||
it('should allow for a title and acc description', function () {
|
||||
const teacherRole = 'is teacher of';
|
||||
const line1 = `TEACHER }o--o{ STUDENT : "${teacherRole}"`;
|
||||
|
||||
erDiagram.parser.parse(
|
||||
`erDiagram\ntitle graph title\n accDescription this graph is about stuff\n${line1}`
|
||||
);
|
||||
expect(erDb.getTitle()).toBe('graph title');
|
||||
expect(erDb.getAccDescription()).toBe('this graph is about stuff');
|
||||
});
|
||||
|
||||
it('should allow more than one relationship between the same two entities', function () {
|
||||
const line1 = 'CAR ||--o{ PERSON : "insured for"';
|
||||
const line2 = 'CAR }o--|| PERSON : "owned by"';
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { log } from '../../logger';
|
||||
import { random } from '../../utils';
|
||||
import mermaidAPI from '../../mermaidAPI';
|
||||
import * as configApi from '../../config';
|
||||
import common from '../common/common';
|
||||
let commits = {};
|
||||
let head = null;
|
||||
let branches = { master: head };
|
||||
let curBranch = 'master';
|
||||
let branches = { main: head };
|
||||
let curBranch = 'main';
|
||||
let direction = 'LR';
|
||||
let seq = 0;
|
||||
|
||||
@@ -11,41 +14,45 @@ function getId() {
|
||||
return random({ length: 7 });
|
||||
}
|
||||
|
||||
/**
|
||||
* @param currentCommit
|
||||
* @param otherCommit
|
||||
*/
|
||||
function isfastforwardable(currentCommit, otherCommit) {
|
||||
log.debug('Entering isfastforwardable:', currentCommit.id, otherCommit.id);
|
||||
let cnt = 0;
|
||||
while (currentCommit.seq <= otherCommit.seq && currentCommit !== otherCommit && cnt < 1000) {
|
||||
cnt++;
|
||||
// only if other branch has more commits
|
||||
if (otherCommit.parent == null) break;
|
||||
if (Array.isArray(otherCommit.parent)) {
|
||||
log.debug('In merge commit:', otherCommit.parent);
|
||||
return (
|
||||
isfastforwardable(currentCommit, commits[otherCommit.parent[0]]) ||
|
||||
isfastforwardable(currentCommit, commits[otherCommit.parent[1]])
|
||||
);
|
||||
} else {
|
||||
otherCommit = commits[otherCommit.parent];
|
||||
}
|
||||
}
|
||||
log.debug(currentCommit.id, otherCommit.id);
|
||||
return currentCommit.id === otherCommit.id;
|
||||
}
|
||||
export const parseDirective = function (statement, context, type) {
|
||||
mermaidAPI.parseDirective(this, statement, context, type);
|
||||
};
|
||||
|
||||
// /**
|
||||
// * @param currentCommit
|
||||
// * @param otherCommit
|
||||
// */
|
||||
// function isfastforwardable(currentCommit, otherCommit) {
|
||||
// log.debug('Entering isfastforwardable:', currentCommit.id, otherCommit.id);
|
||||
// let cnt = 0;
|
||||
// while (currentCommit.seq <= otherCommit.seq && currentCommit !== otherCommit && cnt < 1000) {
|
||||
// cnt++;
|
||||
// // only if other branch has more commits
|
||||
// if (otherCommit.parent == null) break;
|
||||
// if (Array.isArray(otherCommit.parent)) {
|
||||
// log.debug('In merge commit:', otherCommit.parent);
|
||||
// return (
|
||||
// isfastforwardable(currentCommit, commits[otherCommit.parent[0]]) ||
|
||||
// isfastforwardable(currentCommit, commits[otherCommit.parent[1]])
|
||||
// );
|
||||
// } else {
|
||||
// otherCommit = commits[otherCommit.parent];
|
||||
// }
|
||||
// }
|
||||
// log.debug(currentCommit.id, otherCommit.id);
|
||||
// return currentCommit.id === otherCommit.id;
|
||||
// }
|
||||
|
||||
/**
|
||||
* @param currentCommit
|
||||
* @param otherCommit
|
||||
*/
|
||||
function isReachableFrom(currentCommit, otherCommit) {
|
||||
const currentSeq = currentCommit.seq;
|
||||
const otherSeq = otherCommit.seq;
|
||||
if (currentSeq > otherSeq) return isfastforwardable(otherCommit, currentCommit);
|
||||
return false;
|
||||
}
|
||||
// function isReachableFrom(currentCommit, otherCommit) {
|
||||
// const currentSeq = currentCommit.seq;
|
||||
// const otherSeq = otherCommit.seq;
|
||||
// if (currentSeq > otherSeq) return isfastforwardable(otherCommit, currentCommit);
|
||||
// return false;
|
||||
// }
|
||||
|
||||
/**
|
||||
* @param list
|
||||
@@ -82,12 +89,19 @@ export const getOptions = function () {
|
||||
return options;
|
||||
};
|
||||
|
||||
export const commit = function (msg) {
|
||||
export const commit = function (msg, id, type, tag) {
|
||||
log.debug('Entering commit:', msg, id, type, tag);
|
||||
id = common.sanitizeText(id, configApi.getConfig());
|
||||
msg = common.sanitizeText(msg, configApi.getConfig());
|
||||
tag = common.sanitizeText(tag, configApi.getConfig());
|
||||
const commit = {
|
||||
id: getId(),
|
||||
id: id ? id : seq + '-' + getId(),
|
||||
message: msg,
|
||||
seq: seq++,
|
||||
parent: head == null ? null : head.id,
|
||||
type: type ? type : commitType.NORMAL,
|
||||
tag: tag ? tag : '',
|
||||
parents: head == null ? [] : [head.id],
|
||||
branch: curBranch,
|
||||
};
|
||||
head = commit;
|
||||
commits[commit.id] = commit;
|
||||
@@ -96,61 +110,159 @@ export const commit = function (msg) {
|
||||
};
|
||||
|
||||
export const branch = function (name) {
|
||||
name = common.sanitizeText(name, configApi.getConfig());
|
||||
if (typeof branches[name] === 'undefined') {
|
||||
branches[name] = head != null ? head.id : null;
|
||||
checkout(name);
|
||||
log.debug('in createBranch');
|
||||
} else {
|
||||
let error = new Error(
|
||||
'Trying to create an existing branch. (Help: Either use a new name if you want create a new branch or try using "checkout ' +
|
||||
name +
|
||||
'")'
|
||||
);
|
||||
error.hash = {
|
||||
text: 'branch ' + name,
|
||||
token: 'branch ' + name,
|
||||
line: '1',
|
||||
loc: { first_line: 1, last_line: 1, first_column: 1, last_column: 1 },
|
||||
expected: ['"checkout ' + name + '"'],
|
||||
};
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const merge = function (otherBranch) {
|
||||
otherBranch = common.sanitizeText(otherBranch, configApi.getConfig());
|
||||
const currentCommit = commits[branches[curBranch]];
|
||||
const otherCommit = commits[branches[otherBranch]];
|
||||
if (isReachableFrom(currentCommit, otherCommit)) {
|
||||
log.debug('Already merged');
|
||||
return;
|
||||
if (curBranch === otherBranch) {
|
||||
let error = new Error('Incorrect usage of "merge". Cannot merge a branch to itself');
|
||||
error.hash = {
|
||||
text: 'merge ' + otherBranch,
|
||||
token: 'merge ' + otherBranch,
|
||||
line: '1',
|
||||
loc: { first_line: 1, last_line: 1, first_column: 1, last_column: 1 },
|
||||
expected: ['branch abc'],
|
||||
};
|
||||
throw error;
|
||||
} else if (typeof currentCommit === 'undefined' || !currentCommit) {
|
||||
let error = new Error(
|
||||
'Incorrect usage of "merge". Current branch (' + curBranch + ')has no commits'
|
||||
);
|
||||
error.hash = {
|
||||
text: 'merge ' + otherBranch,
|
||||
token: 'merge ' + otherBranch,
|
||||
line: '1',
|
||||
loc: { first_line: 1, last_line: 1, first_column: 1, last_column: 1 },
|
||||
expected: ['commit'],
|
||||
};
|
||||
throw error;
|
||||
} else if (typeof branches[otherBranch] === 'undefined') {
|
||||
let error = new Error(
|
||||
'Incorrect usage of "merge". Branch to be merged (' + otherBranch + ') does not exist'
|
||||
);
|
||||
error.hash = {
|
||||
text: 'merge ' + otherBranch,
|
||||
token: 'merge ' + otherBranch,
|
||||
line: '1',
|
||||
loc: { first_line: 1, last_line: 1, first_column: 1, last_column: 1 },
|
||||
expected: ['branch ' + otherBranch],
|
||||
};
|
||||
throw error;
|
||||
} else if (typeof otherCommit === 'undefined' || !otherCommit) {
|
||||
let error = new Error(
|
||||
'Incorrect usage of "merge". Branch to be merged (' + otherBranch + ') has no commits'
|
||||
);
|
||||
error.hash = {
|
||||
text: 'merge ' + otherBranch,
|
||||
token: 'merge ' + otherBranch,
|
||||
line: '1',
|
||||
loc: { first_line: 1, last_line: 1, first_column: 1, last_column: 1 },
|
||||
expected: ['"commit"'],
|
||||
};
|
||||
throw error;
|
||||
} else if (currentCommit === otherCommit) {
|
||||
let error = new Error('Incorrect usage of "merge". Both branches have same head');
|
||||
error.hash = {
|
||||
text: 'merge ' + otherBranch,
|
||||
token: 'merge ' + otherBranch,
|
||||
line: '1',
|
||||
loc: { first_line: 1, last_line: 1, first_column: 1, last_column: 1 },
|
||||
expected: ['branch abc'],
|
||||
};
|
||||
throw error;
|
||||
}
|
||||
if (isfastforwardable(currentCommit, otherCommit)) {
|
||||
branches[curBranch] = branches[otherBranch];
|
||||
head = commits[branches[curBranch]];
|
||||
} else {
|
||||
// if (isReachableFrom(currentCommit, otherCommit)) {
|
||||
// log.debug('Already merged');
|
||||
// return;
|
||||
// }
|
||||
// if (isfastforwardable(currentCommit, otherCommit)) {
|
||||
// branches[curBranch] = branches[otherBranch];
|
||||
// head = commits[branches[curBranch]];
|
||||
// } else {
|
||||
// create merge commit
|
||||
const commit = {
|
||||
id: getId(),
|
||||
id: seq + '-' + getId(),
|
||||
message: 'merged branch ' + otherBranch + ' into ' + curBranch,
|
||||
seq: seq++,
|
||||
parent: [head == null ? null : head.id, branches[otherBranch]],
|
||||
parents: [head == null ? null : head.id, branches[otherBranch]],
|
||||
branch: curBranch,
|
||||
type: commitType.MERGE,
|
||||
};
|
||||
head = commit;
|
||||
commits[commit.id] = commit;
|
||||
branches[curBranch] = commit.id;
|
||||
}
|
||||
// }
|
||||
log.debug(branches);
|
||||
log.debug('in mergeBranch');
|
||||
};
|
||||
|
||||
export const checkout = function (branch) {
|
||||
log.debug('in checkout');
|
||||
branch = common.sanitizeText(branch, configApi.getConfig());
|
||||
console.info(branches);
|
||||
if (typeof branches[branch] === 'undefined') {
|
||||
let error = new Error(
|
||||
'Trying to checkout branch which is not yet created. (Help try using "branch ' + branch + '")'
|
||||
);
|
||||
error.hash = {
|
||||
text: 'checkout ' + branch,
|
||||
token: 'checkout ' + branch,
|
||||
line: '1',
|
||||
loc: { first_line: 1, last_line: 1, first_column: 1, last_column: 1 },
|
||||
expected: ['"branch ' + branch + '"'],
|
||||
};
|
||||
throw error;
|
||||
//branches[branch] = head != null ? head.id : null;
|
||||
//log.debug('in createBranch');
|
||||
} else {
|
||||
curBranch = branch;
|
||||
const id = branches[curBranch];
|
||||
console.log(id);
|
||||
console.log('hi');
|
||||
console.log(commits);
|
||||
head = commits[id];
|
||||
}
|
||||
};
|
||||
|
||||
export const reset = function (commitRef) {
|
||||
log.debug('in reset', commitRef);
|
||||
const ref = commitRef.split(':')[0];
|
||||
let parentCount = parseInt(commitRef.split(':')[1]);
|
||||
let commit = ref === 'HEAD' ? head : commits[branches[ref]];
|
||||
log.debug(commit, parentCount);
|
||||
while (parentCount > 0) {
|
||||
commit = commits[commit.parent];
|
||||
parentCount--;
|
||||
if (!commit) {
|
||||
const err = 'Critical error - unique parent commit not found during reset';
|
||||
log.error(err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
head = commit;
|
||||
branches[curBranch] = commit.id;
|
||||
};
|
||||
// export const reset = function (commitRef) {
|
||||
// log.debug('in reset', commitRef);
|
||||
// const ref = commitRef.split(':')[0];
|
||||
// let parentCount = parseInt(commitRef.split(':')[1]);
|
||||
// let commit = ref === 'HEAD' ? head : commits[branches[ref]];
|
||||
// log.debug(commit, parentCount);
|
||||
// while (parentCount > 0) {
|
||||
// commit = commits[commit.parent];
|
||||
// parentCount--;
|
||||
// if (!commit) {
|
||||
// const err = 'Critical error - unique parent commit not found during reset';
|
||||
// log.error(err);
|
||||
// throw err;
|
||||
// }
|
||||
// }
|
||||
// head = commit;
|
||||
// branches[curBranch] = commit.id;
|
||||
// };
|
||||
|
||||
/**
|
||||
* @param arr
|
||||
@@ -185,14 +297,14 @@ function prettyPrintCommitHistory(commitArr) {
|
||||
if (branches[branch] === commit.id) label.push(branch);
|
||||
}
|
||||
log.debug(label.join(' '));
|
||||
if (Array.isArray(commit.parent)) {
|
||||
const newCommit = commits[commit.parent[0]];
|
||||
if (commit.parents && commit.parents.length == 2) {
|
||||
const newCommit = commits[commit.parents[0]];
|
||||
upsert(commitArr, commit, newCommit);
|
||||
commitArr.push(commits[commit.parent[1]]);
|
||||
} else if (commit.parent == null) {
|
||||
commitArr.push(commits[commit.parents[1]]);
|
||||
} else if (commit.parents.length == 0) {
|
||||
return;
|
||||
} else {
|
||||
const nextCommit = commits[commit.parent];
|
||||
const nextCommit = commits[commit.parents];
|
||||
upsert(commitArr, commit, nextCommit);
|
||||
}
|
||||
commitArr = uniqBy(commitArr, (c) => c.id);
|
||||
@@ -208,15 +320,16 @@ export const prettyPrint = function () {
|
||||
export const clear = function () {
|
||||
commits = {};
|
||||
head = null;
|
||||
branches = { master: head };
|
||||
curBranch = 'master';
|
||||
branches = { main: head };
|
||||
curBranch = 'main';
|
||||
seq = 0;
|
||||
};
|
||||
|
||||
export const getBranchesAsObjArray = function () {
|
||||
const branchArr = [];
|
||||
for (let branch in branches) {
|
||||
branchArr.push({ name: branch, commit: commits[branches[branch]] });
|
||||
// branchArr.push({ name: branch, commit: commits[branches[branch]] });
|
||||
branchArr.push({ name: branch });
|
||||
}
|
||||
return branchArr;
|
||||
};
|
||||
@@ -234,7 +347,7 @@ export const getCommitsArray = function () {
|
||||
commitArr.forEach(function (o) {
|
||||
log.debug(o.id);
|
||||
});
|
||||
commitArr.sort((a, b) => b.seq - a.seq);
|
||||
commitArr.sort((a, b) => a.seq - b.seq);
|
||||
return commitArr;
|
||||
};
|
||||
export const getCurrentBranch = function () {
|
||||
@@ -247,7 +360,16 @@ export const getHead = function () {
|
||||
return head;
|
||||
};
|
||||
|
||||
export const commitType = {
|
||||
NORMAL: 0,
|
||||
REVERSE: 1,
|
||||
HIGHLIGHT: 2,
|
||||
MERGE: 3,
|
||||
};
|
||||
|
||||
export default {
|
||||
parseDirective,
|
||||
getConfig: () => configApi.getConfig().gitGraph,
|
||||
setDirection,
|
||||
setOptions,
|
||||
getOptions,
|
||||
@@ -255,7 +377,7 @@ export default {
|
||||
branch,
|
||||
merge,
|
||||
checkout,
|
||||
reset,
|
||||
//reset,
|
||||
prettyPrint,
|
||||
clear,
|
||||
getBranchesAsObjArray,
|
||||
@@ -265,4 +387,5 @@ export default {
|
||||
getCurrentBranch,
|
||||
getDirection,
|
||||
getHead,
|
||||
commitType,
|
||||
};
|
||||
|
||||
570
src/diagrams/git/gitGraphParserV2.spec.js
Normal file
570
src/diagrams/git/gitGraphParserV2.spec.js
Normal file
@@ -0,0 +1,570 @@
|
||||
/* eslint-env jasmine */
|
||||
// Todo reintroduce without cryptoRandomString
|
||||
import gitGraphAst from './gitGraphAst';
|
||||
import { parser } from './parser/gitGraph';
|
||||
//import randomString from 'crypto-random-string';
|
||||
//import cryptoRandomString from 'crypto-random-string';
|
||||
import { logger } from '../../logger';
|
||||
|
||||
//jest.mock('crypto-random-string');
|
||||
|
||||
describe('when parsing a gitGraph', function () {
|
||||
let randomNumber;
|
||||
beforeEach(function () {
|
||||
parser.yy = gitGraphAst;
|
||||
parser.yy.clear();
|
||||
randomNumber = 0;
|
||||
});
|
||||
// afterEach(function() {
|
||||
// cryptoRandomString.mockReset();
|
||||
// });
|
||||
it('should handle a gitGraph commit with NO pararms, get auto-genrated reandom ID', function () {
|
||||
const str = `gitGraph:
|
||||
commit
|
||||
`;
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
//console.info(commits);
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('main');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
|
||||
const key = Object.keys(commits)[0];
|
||||
expect(commits[key].message).toBe('');
|
||||
expect(commits[key].id).not.toBeNull();
|
||||
expect(commits[key].tag).toBe('');
|
||||
expect(commits[key].type).toBe(0);
|
||||
});
|
||||
|
||||
it('should handle a gitGraph commit with custom commit id only', function () {
|
||||
const str = `gitGraph:
|
||||
commit id:"1111"
|
||||
`;
|
||||
//console.log(str);
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('main');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
|
||||
const key = Object.keys(commits)[0];
|
||||
expect(commits[key].message).toBe('');
|
||||
expect(commits[key].id).toBe('1111');
|
||||
expect(commits[key].tag).toBe('');
|
||||
expect(commits[key].type).toBe(0);
|
||||
});
|
||||
|
||||
it('should handle a gitGraph commit with custom commit tag only', function () {
|
||||
const str = `gitGraph:
|
||||
commit tag:"test"
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('main');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
|
||||
const key = Object.keys(commits)[0];
|
||||
expect(commits[key].message).toBe('');
|
||||
expect(commits[key].id).not.toBeNull();
|
||||
expect(commits[key].tag).toBe('test');
|
||||
expect(commits[key].type).toBe(0);
|
||||
});
|
||||
|
||||
it('should handle a gitGraph commit with custom commit type HIGHLIGHT only', function () {
|
||||
const str = `gitGraph:
|
||||
commit type: HIGHLIGHT
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('main');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
|
||||
const key = Object.keys(commits)[0];
|
||||
expect(commits[key].message).toBe('');
|
||||
expect(commits[key].id).not.toBeNull();
|
||||
expect(commits[key].tag).toBe('');
|
||||
expect(commits[key].type).toBe(2);
|
||||
});
|
||||
|
||||
it('should handle a gitGraph commit with custom commit type REVERSE only', function () {
|
||||
const str = `gitGraph:
|
||||
commit type: REVERSE
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('main');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
|
||||
const key = Object.keys(commits)[0];
|
||||
expect(commits[key].message).toBe('');
|
||||
expect(commits[key].id).not.toBeNull();
|
||||
expect(commits[key].tag).toBe('');
|
||||
expect(commits[key].type).toBe(1);
|
||||
});
|
||||
|
||||
it('should handle a gitGraph commit with custom commit type NORMAL only', function () {
|
||||
const str = `gitGraph:
|
||||
commit type: NORMAL
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('main');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
|
||||
const key = Object.keys(commits)[0];
|
||||
expect(commits[key].message).toBe('');
|
||||
expect(commits[key].id).not.toBeNull();
|
||||
expect(commits[key].tag).toBe('');
|
||||
expect(commits[key].type).toBe(0);
|
||||
});
|
||||
|
||||
it('should handle a gitGraph commit with custom commit msg only', function () {
|
||||
const str = `gitGraph:
|
||||
commit "test commit"
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('main');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
|
||||
const key = Object.keys(commits)[0];
|
||||
expect(commits[key].message).toBe('test commit');
|
||||
expect(commits[key].id).not.toBeNull();
|
||||
expect(commits[key].tag).toBe('');
|
||||
expect(commits[key].type).toBe(0);
|
||||
});
|
||||
|
||||
it('should handle a gitGraph commit with custom commit "msg:" key only', function () {
|
||||
const str = `gitGraph:
|
||||
commit msg: "test commit"
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('main');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
|
||||
const key = Object.keys(commits)[0];
|
||||
expect(commits[key].message).toBe('test commit');
|
||||
expect(commits[key].id).not.toBeNull();
|
||||
expect(commits[key].tag).toBe('');
|
||||
expect(commits[key].type).toBe(0);
|
||||
});
|
||||
|
||||
it('should handle a gitGraph commit with custom commit id, tag only', function () {
|
||||
const str = `gitGraph:
|
||||
commit id:"1111" tag: "test tag"
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('main');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
|
||||
const key = Object.keys(commits)[0];
|
||||
expect(commits[key].message).toBe('');
|
||||
expect(commits[key].id).toBe('1111');
|
||||
expect(commits[key].tag).toBe('test tag');
|
||||
expect(commits[key].type).toBe(0);
|
||||
});
|
||||
|
||||
it('should handle a gitGraph commit with custom commit type, tag only', function () {
|
||||
const str = `gitGraph:
|
||||
commit type:HIGHLIGHT tag: "test tag"
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('main');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
|
||||
const key = Object.keys(commits)[0];
|
||||
expect(commits[key].message).toBe('');
|
||||
expect(commits[key].id).not.toBeNull();
|
||||
expect(commits[key].tag).toBe('test tag');
|
||||
expect(commits[key].type).toBe(2);
|
||||
});
|
||||
|
||||
it('should handle a gitGraph commit with custom commit tag and type only', function () {
|
||||
const str = `gitGraph:
|
||||
commit tag: "test tag" type:HIGHLIGHT
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('main');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
|
||||
const key = Object.keys(commits)[0];
|
||||
expect(commits[key].message).toBe('');
|
||||
expect(commits[key].id).not.toBeNull();
|
||||
expect(commits[key].tag).toBe('test tag');
|
||||
expect(commits[key].type).toBe(2);
|
||||
});
|
||||
|
||||
it('should handle a gitGraph commit with custom commit id, type and tag only', function () {
|
||||
const str = `gitGraph:
|
||||
commit id:"1111" type:REVERSE tag: "test tag"
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('main');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
|
||||
const key = Object.keys(commits)[0];
|
||||
expect(commits[key].message).toBe('');
|
||||
expect(commits[key].id).toBe('1111');
|
||||
expect(commits[key].tag).toBe('test tag');
|
||||
expect(commits[key].type).toBe(1);
|
||||
});
|
||||
|
||||
it('should handle a gitGraph commit with custom commit id, type, tag and msg', function () {
|
||||
const str = `gitGraph:
|
||||
commit id:"1111" type:REVERSE tag: "test tag" msg:"test msg"
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('main');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
|
||||
const key = Object.keys(commits)[0];
|
||||
expect(commits[key].message).toBe('test msg');
|
||||
expect(commits[key].id).toBe('1111');
|
||||
expect(commits[key].tag).toBe('test tag');
|
||||
expect(commits[key].type).toBe(1);
|
||||
});
|
||||
|
||||
it('should handle a gitGraph commit with custom type,tag, msg, commit id,', function () {
|
||||
const str = `gitGraph:
|
||||
commit type:REVERSE tag: "test tag" msg: "test msg" id: "1111"
|
||||
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('main');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
|
||||
const key = Object.keys(commits)[0];
|
||||
expect(commits[key].message).toBe('test msg');
|
||||
expect(commits[key].id).toBe('1111');
|
||||
expect(commits[key].tag).toBe('test tag');
|
||||
expect(commits[key].type).toBe(1);
|
||||
});
|
||||
|
||||
it('should handle a gitGraph commit with custom tag, msg, commit id, type,', function () {
|
||||
const str = `gitGraph:
|
||||
commit tag: "test tag" msg:"test msg" id:"1111" type:REVERSE
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('main');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
|
||||
const key = Object.keys(commits)[0];
|
||||
expect(commits[key].message).toBe('test msg');
|
||||
expect(commits[key].id).toBe('1111');
|
||||
expect(commits[key].tag).toBe('test tag');
|
||||
expect(commits[key].type).toBe(1);
|
||||
});
|
||||
|
||||
it('should handle a gitGraph commit with custom msg, commit id, type,tag', function () {
|
||||
const str = `gitGraph:
|
||||
commit msg:"test msg" id:"1111" type:REVERSE tag: "test tag"
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('main');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
|
||||
const key = Object.keys(commits)[0];
|
||||
expect(commits[key].message).toBe('test msg');
|
||||
expect(commits[key].id).toBe('1111');
|
||||
expect(commits[key].tag).toBe('test tag');
|
||||
expect(commits[key].type).toBe(1);
|
||||
});
|
||||
|
||||
it('should handle 3 straight commits', function () {
|
||||
const str = `gitGraph:
|
||||
commit
|
||||
commit
|
||||
commit
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
expect(Object.keys(commits).length).toBe(3);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('main');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
|
||||
});
|
||||
|
||||
it('should handle new branch creation', function () {
|
||||
const str = `gitGraph:
|
||||
commit
|
||||
branch testBranch
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('testBranch');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(2);
|
||||
});
|
||||
|
||||
it('should handle new branch checkout', function () {
|
||||
const str = `gitGraph:
|
||||
commit
|
||||
branch testBranch
|
||||
checkout testBranch
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('testBranch');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(2);
|
||||
});
|
||||
|
||||
it('should handle new branch checkout & commit', function () {
|
||||
const str = `gitGraph:
|
||||
commit
|
||||
branch testBranch
|
||||
checkout testBranch
|
||||
commit
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
expect(Object.keys(commits).length).toBe(2);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('testBranch');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(2);
|
||||
const commit1 = Object.keys(commits)[0];
|
||||
const commit2 = Object.keys(commits)[1];
|
||||
expect(commits[commit1].branch).toBe('main');
|
||||
expect(commits[commit1].parents).toStrictEqual([]);
|
||||
expect(commits[commit2].branch).toBe('testBranch');
|
||||
expect(commits[commit2].parents).toStrictEqual([commit1]);
|
||||
});
|
||||
|
||||
it('should handle new branch checkout & commit and merge', function () {
|
||||
const str = `gitGraph:
|
||||
commit
|
||||
branch testBranch
|
||||
checkout testBranch
|
||||
commit
|
||||
commit
|
||||
checkout main
|
||||
merge testBranch
|
||||
`;
|
||||
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
expect(Object.keys(commits).length).toBe(4);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('main');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(2);
|
||||
const commit1 = Object.keys(commits)[0];
|
||||
const commit2 = Object.keys(commits)[1];
|
||||
const commit3 = Object.keys(commits)[2];
|
||||
const commit4 = Object.keys(commits)[3];
|
||||
expect(commits[commit1].branch).toBe('main');
|
||||
console.log(commits);
|
||||
|
||||
console.log(commits[commit1].parents);
|
||||
expect(commits[commit1].parents).toStrictEqual([]);
|
||||
expect(commits[commit2].branch).toBe('testBranch');
|
||||
expect(commits[commit2].parents).toStrictEqual([commits[commit1].id]);
|
||||
expect(commits[commit3].branch).toBe('testBranch');
|
||||
expect(commits[commit3].parents).toStrictEqual([commits[commit2].id]);
|
||||
expect(commits[commit4].branch).toBe('main');
|
||||
expect(commits[commit4].parents).toStrictEqual([commits[commit1].id, commits[commit3].id]);
|
||||
expect(parser.yy.getBranchesAsObjArray()).toStrictEqual([
|
||||
{ name: 'main' },
|
||||
{ name: 'testBranch' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should throw error when try to branch existing branch: main', function () {
|
||||
const str = `gitGraph
|
||||
commit
|
||||
branch testBranch
|
||||
commit
|
||||
branch main
|
||||
commit
|
||||
checkout main
|
||||
merge testBranch
|
||||
`;
|
||||
|
||||
try {
|
||||
parser.parse(str);
|
||||
// Fail test if above expression doesn't throw anything.
|
||||
expect(true).toBe(false);
|
||||
} catch (e) {
|
||||
expect(e.message).toBe(
|
||||
'Trying to create an existing branch. (Help: Either use a new name if you want create a new branch or try using "checkout main")'
|
||||
);
|
||||
}
|
||||
});
|
||||
it('should throw error when try to branch existing branch: testBranch', function () {
|
||||
const str = `gitGraph
|
||||
commit
|
||||
branch testBranch
|
||||
commit
|
||||
branch testBranch
|
||||
commit
|
||||
checkout main
|
||||
merge testBranch
|
||||
`;
|
||||
|
||||
try {
|
||||
parser.parse(str);
|
||||
// Fail test if above expression doesn't throw anything.
|
||||
expect(true).toBe(false);
|
||||
} catch (e) {
|
||||
expect(e.message).toBe(
|
||||
'Trying to create an existing branch. (Help: Either use a new name if you want create a new branch or try using "checkout testBranch")'
|
||||
);
|
||||
}
|
||||
});
|
||||
it('should throw error when try to checkout unknown branch: testBranch', function () {
|
||||
const str = `gitGraph
|
||||
commit
|
||||
checkout testBranch
|
||||
commit
|
||||
branch testBranch
|
||||
commit
|
||||
checkout main
|
||||
merge testBranch
|
||||
`;
|
||||
|
||||
try {
|
||||
parser.parse(str);
|
||||
// Fail test if above expression doesn't throw anything.
|
||||
expect(true).toBe(false);
|
||||
} catch (e) {
|
||||
expect(e.message).toBe(
|
||||
'Trying to checkout branch which is not yet created. (Help try using "branch testBranch")'
|
||||
);
|
||||
}
|
||||
});
|
||||
it('should throw error when trying to merge, when current branch has no commits', function () {
|
||||
const str = `gitGraph
|
||||
merge testBranch
|
||||
commit
|
||||
checkout testBranch
|
||||
commit
|
||||
branch testBranch
|
||||
commit
|
||||
checkout main
|
||||
merge testBranch
|
||||
`;
|
||||
|
||||
try {
|
||||
parser.parse(str);
|
||||
// Fail test if above expression doesn't throw anything.
|
||||
expect(true).toBe(false);
|
||||
} catch (e) {
|
||||
expect(e.message).toBe('Incorrect usage of "merge". Current branch (main)has no commits');
|
||||
}
|
||||
});
|
||||
it('should throw error when trying to merge unknown branch', function () {
|
||||
const str = `gitGraph
|
||||
commit
|
||||
merge testBranch
|
||||
commit
|
||||
checkout testBranch
|
||||
commit
|
||||
branch testBranch
|
||||
commit
|
||||
checkout main
|
||||
merge testBranch
|
||||
`;
|
||||
|
||||
try {
|
||||
parser.parse(str);
|
||||
// Fail test if above expression doesn't throw anything.
|
||||
expect(true).toBe(false);
|
||||
} catch (e) {
|
||||
expect(e.message).toBe(
|
||||
'Incorrect usage of "merge". Branch to be merged (testBranch) does not exist'
|
||||
);
|
||||
}
|
||||
});
|
||||
it('should throw error when trying to merge branch to itself', function () {
|
||||
const str = `gitGraph
|
||||
commit
|
||||
branch testBranch
|
||||
merge testBranch
|
||||
`;
|
||||
|
||||
try {
|
||||
parser.parse(str);
|
||||
// Fail test if above expression doesn't throw anything.
|
||||
expect(true).toBe(false);
|
||||
} catch (e) {
|
||||
expect(e.message).toBe('Incorrect usage of "merge". Cannot merge a branch to itself');
|
||||
}
|
||||
});
|
||||
it('should throw error when trying to merge branches having same heads', function () {
|
||||
const str = `gitGraph
|
||||
commit
|
||||
branch testBranch
|
||||
checkout main
|
||||
merge testBranch
|
||||
`;
|
||||
|
||||
try {
|
||||
parser.parse(str);
|
||||
// Fail test if above expression doesn't throw anything.
|
||||
expect(true).toBe(false);
|
||||
} catch (e) {
|
||||
expect(e.message).toBe('Incorrect usage of "merge". Both branches have same head');
|
||||
}
|
||||
});
|
||||
it('should throw error when trying to merge branch which has no commits', function () {
|
||||
const str = `gitGraph
|
||||
branch test1
|
||||
|
||||
checkout main
|
||||
commit
|
||||
merge test1
|
||||
`;
|
||||
|
||||
try {
|
||||
parser.parse(str);
|
||||
// Fail test if above expression doesn't throw anything.
|
||||
expect(true).toBe(false);
|
||||
} catch (e) {
|
||||
expect(e.message).toBe(
|
||||
'Incorrect usage of "merge". Branch to be merged (test1) has no commits'
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
372
src/diagrams/git/gitGraphRenderer-old.js
Normal file
372
src/diagrams/git/gitGraphRenderer-old.js
Normal file
@@ -0,0 +1,372 @@
|
||||
import { curveBasis, line, select } from 'd3';
|
||||
|
||||
import db from './gitGraphAst';
|
||||
import gitGraphParser from './parser/gitGraph';
|
||||
import { logger } from '../../logger';
|
||||
import { interpolateToCurve } from '../../utils';
|
||||
|
||||
let allCommitsDict = {};
|
||||
let branchNum;
|
||||
let config = {
|
||||
nodeSpacing: 150,
|
||||
nodeFillColor: 'yellow',
|
||||
nodeStrokeWidth: 2,
|
||||
nodeStrokeColor: 'grey',
|
||||
lineStrokeWidth: 4,
|
||||
branchOffset: 50,
|
||||
lineColor: 'grey',
|
||||
leftMargin: 50,
|
||||
branchColors: ['#442f74', '#983351', '#609732', '#AA9A39'],
|
||||
nodeRadius: 10,
|
||||
nodeLabel: {
|
||||
width: 75,
|
||||
height: 100,
|
||||
x: -25,
|
||||
y: 0,
|
||||
},
|
||||
};
|
||||
let apiConfig = {};
|
||||
export const setConf = function (c) {
|
||||
apiConfig = c;
|
||||
};
|
||||
|
||||
/** @param svg */
|
||||
function svgCreateDefs(svg) {
|
||||
svg
|
||||
.append('defs')
|
||||
.append('g')
|
||||
.attr('id', 'def-commit')
|
||||
.append('circle')
|
||||
.attr('r', config.nodeRadius)
|
||||
.attr('cx', 0)
|
||||
.attr('cy', 0);
|
||||
svg
|
||||
.select('#def-commit')
|
||||
.append('foreignObject')
|
||||
.attr('width', config.nodeLabel.width)
|
||||
.attr('height', config.nodeLabel.height)
|
||||
.attr('x', config.nodeLabel.x)
|
||||
.attr('y', config.nodeLabel.y)
|
||||
.attr('class', 'node-label')
|
||||
.attr('requiredFeatures', 'http://www.w3.org/TR/SVG11/feature#Extensibility')
|
||||
.append('p')
|
||||
.html('');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param svg
|
||||
* @param points
|
||||
* @param colorIdx
|
||||
* @param interpolate
|
||||
*/
|
||||
function svgDrawLine(svg, points, colorIdx, interpolate) {
|
||||
const curve = interpolateToCurve(interpolate, curveBasis);
|
||||
const color = config.branchColors[colorIdx % config.branchColors.length];
|
||||
const lineGen = line()
|
||||
.x(function (d) {
|
||||
return Math.round(d.x);
|
||||
})
|
||||
.y(function (d) {
|
||||
return Math.round(d.y);
|
||||
})
|
||||
.curve(curve);
|
||||
|
||||
svg
|
||||
.append('svg:path')
|
||||
.attr('d', lineGen(points))
|
||||
.style('stroke', color)
|
||||
.style('stroke-width', config.lineStrokeWidth)
|
||||
.style('fill', 'none');
|
||||
}
|
||||
|
||||
// Pass in the element and its pre-transform coords
|
||||
/**
|
||||
* @param element
|
||||
* @param coords
|
||||
*/
|
||||
function getElementCoords(element, coords) {
|
||||
coords = coords || element.node().getBBox();
|
||||
const ctm = element.node().getCTM();
|
||||
const xn = ctm.e + coords.x * ctm.a;
|
||||
const yn = ctm.f + coords.y * ctm.d;
|
||||
return {
|
||||
left: xn,
|
||||
top: yn,
|
||||
width: coords.width,
|
||||
height: coords.height,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param svg
|
||||
* @param fromId
|
||||
* @param toId
|
||||
* @param direction
|
||||
* @param color
|
||||
*/
|
||||
function svgDrawLineForCommits(svg, fromId, toId, direction, color) {
|
||||
logger.debug('svgDrawLineForCommits: ', fromId, toId);
|
||||
const fromBbox = getElementCoords(svg.select('#node-' + fromId + ' circle'));
|
||||
const toBbox = getElementCoords(svg.select('#node-' + toId + ' circle'));
|
||||
switch (direction) {
|
||||
case 'LR':
|
||||
// (toBbox)
|
||||
// +--------
|
||||
// + (fromBbox)
|
||||
if (fromBbox.left - toBbox.left > config.nodeSpacing) {
|
||||
const lineStart = {
|
||||
x: fromBbox.left - config.nodeSpacing,
|
||||
y: toBbox.top + toBbox.height / 2,
|
||||
};
|
||||
const lineEnd = { x: toBbox.left + toBbox.width, y: toBbox.top + toBbox.height / 2 };
|
||||
svgDrawLine(svg, [lineStart, lineEnd], color, 'linear');
|
||||
svgDrawLine(
|
||||
svg,
|
||||
[
|
||||
{ x: fromBbox.left, y: fromBbox.top + fromBbox.height / 2 },
|
||||
{ x: fromBbox.left - config.nodeSpacing / 2, y: fromBbox.top + fromBbox.height / 2 },
|
||||
{ x: fromBbox.left - config.nodeSpacing / 2, y: lineStart.y },
|
||||
lineStart,
|
||||
],
|
||||
color
|
||||
);
|
||||
} else {
|
||||
svgDrawLine(
|
||||
svg,
|
||||
[
|
||||
{
|
||||
x: fromBbox.left,
|
||||
y: fromBbox.top + fromBbox.height / 2,
|
||||
},
|
||||
{
|
||||
x: fromBbox.left - config.nodeSpacing / 2,
|
||||
y: fromBbox.top + fromBbox.height / 2,
|
||||
},
|
||||
{
|
||||
x: fromBbox.left - config.nodeSpacing / 2,
|
||||
y: toBbox.top + toBbox.height / 2,
|
||||
},
|
||||
{
|
||||
x: toBbox.left + toBbox.width,
|
||||
y: toBbox.top + toBbox.height / 2,
|
||||
},
|
||||
],
|
||||
color
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 'BT':
|
||||
// + (fromBbox)
|
||||
// |
|
||||
// |
|
||||
// + (toBbox)
|
||||
if (toBbox.top - fromBbox.top > config.nodeSpacing) {
|
||||
const lineStart = {
|
||||
x: toBbox.left + toBbox.width / 2,
|
||||
y: fromBbox.top + fromBbox.height + config.nodeSpacing,
|
||||
};
|
||||
const lineEnd = { x: toBbox.left + toBbox.width / 2, y: toBbox.top };
|
||||
svgDrawLine(svg, [lineStart, lineEnd], color, 'linear');
|
||||
svgDrawLine(
|
||||
svg,
|
||||
[
|
||||
{ x: fromBbox.left + fromBbox.width / 2, y: fromBbox.top + fromBbox.height },
|
||||
{
|
||||
x: fromBbox.left + fromBbox.width / 2,
|
||||
y: fromBbox.top + fromBbox.height + config.nodeSpacing / 2,
|
||||
},
|
||||
{ x: toBbox.left + toBbox.width / 2, y: lineStart.y - config.nodeSpacing / 2 },
|
||||
lineStart,
|
||||
],
|
||||
color
|
||||
);
|
||||
} else {
|
||||
svgDrawLine(
|
||||
svg,
|
||||
[
|
||||
{
|
||||
x: fromBbox.left + fromBbox.width / 2,
|
||||
y: fromBbox.top + fromBbox.height,
|
||||
},
|
||||
{
|
||||
x: fromBbox.left + fromBbox.width / 2,
|
||||
y: fromBbox.top + config.nodeSpacing / 2,
|
||||
},
|
||||
{
|
||||
x: toBbox.left + toBbox.width / 2,
|
||||
y: toBbox.top - config.nodeSpacing / 2,
|
||||
},
|
||||
{
|
||||
x: toBbox.left + toBbox.width / 2,
|
||||
y: toBbox.top,
|
||||
},
|
||||
],
|
||||
color
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param svg
|
||||
* @param selector
|
||||
*/
|
||||
function cloneNode(svg, selector) {
|
||||
return svg.select(selector).node().cloneNode(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param svg
|
||||
* @param commitid
|
||||
* @param branches
|
||||
* @param direction
|
||||
*/
|
||||
function renderCommitHistory(svg, commitid, branches, direction) {
|
||||
let commit;
|
||||
const numCommits = Object.keys(allCommitsDict).length;
|
||||
if (typeof commitid === 'string') {
|
||||
do {
|
||||
commit = allCommitsDict[commitid];
|
||||
logger.debug('in renderCommitHistory', commit.id, commit.seq);
|
||||
if (svg.select('#node-' + commitid).size() > 0) {
|
||||
return;
|
||||
}
|
||||
svg
|
||||
.append(function () {
|
||||
return cloneNode(svg, '#def-commit');
|
||||
})
|
||||
.attr('class', 'commit')
|
||||
.attr('id', function () {
|
||||
return 'node-' + commit.id;
|
||||
})
|
||||
.attr('transform', function () {
|
||||
switch (direction) {
|
||||
case 'LR':
|
||||
return (
|
||||
'translate(' +
|
||||
(commit.seq * config.nodeSpacing + config.leftMargin) +
|
||||
', ' +
|
||||
branchNum * config.branchOffset +
|
||||
')'
|
||||
);
|
||||
case 'BT':
|
||||
return (
|
||||
'translate(' +
|
||||
(branchNum * config.branchOffset + config.leftMargin) +
|
||||
', ' +
|
||||
(numCommits - commit.seq) * config.nodeSpacing +
|
||||
')'
|
||||
);
|
||||
}
|
||||
})
|
||||
.attr('fill', config.nodeFillColor)
|
||||
.attr('stroke', config.nodeStrokeColor)
|
||||
.attr('stroke-width', config.nodeStrokeWidth);
|
||||
|
||||
let branch;
|
||||
for (let branchName in branches) {
|
||||
if (branches[branchName].commit === commit) {
|
||||
branch = branches[branchName];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (branch) {
|
||||
logger.debug('found branch ', branch.name);
|
||||
svg
|
||||
.select('#node-' + commit.id + ' p')
|
||||
.append('xhtml:span')
|
||||
.attr('class', 'branch-label')
|
||||
.text(branch.name + ', ');
|
||||
}
|
||||
svg
|
||||
.select('#node-' + commit.id + ' p')
|
||||
.append('xhtml:span')
|
||||
.attr('class', 'commit-id')
|
||||
.text(commit.id);
|
||||
if (commit.message !== '' && direction === 'BT') {
|
||||
svg
|
||||
.select('#node-' + commit.id + ' p')
|
||||
.append('xhtml:span')
|
||||
.attr('class', 'commit-msg')
|
||||
.text(', ' + commit.message);
|
||||
}
|
||||
commitid = commit.parent;
|
||||
} while (commitid && allCommitsDict[commitid]);
|
||||
}
|
||||
|
||||
if (Array.isArray(commitid)) {
|
||||
logger.debug('found merge commmit', commitid);
|
||||
renderCommitHistory(svg, commitid[0], branches, direction);
|
||||
branchNum++;
|
||||
renderCommitHistory(svg, commitid[1], branches, direction);
|
||||
branchNum--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param svg
|
||||
* @param commit
|
||||
* @param direction
|
||||
* @param branchColor
|
||||
*/
|
||||
function renderLines(svg, commit, direction, branchColor) {
|
||||
branchColor = branchColor || 0;
|
||||
while (commit.seq > 0 && !commit.lineDrawn) {
|
||||
if (typeof commit.parent === 'string') {
|
||||
svgDrawLineForCommits(svg, commit.id, commit.parent, direction, branchColor);
|
||||
commit.lineDrawn = true;
|
||||
commit = allCommitsDict[commit.parent];
|
||||
} else if (Array.isArray(commit.parent)) {
|
||||
svgDrawLineForCommits(svg, commit.id, commit.parent[0], direction, branchColor);
|
||||
svgDrawLineForCommits(svg, commit.id, commit.parent[1], direction, branchColor + 1);
|
||||
renderLines(svg, allCommitsDict[commit.parent[1]], direction, branchColor + 1);
|
||||
commit.lineDrawn = true;
|
||||
commit = allCommitsDict[commit.parent[0]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const draw = function (txt, id, ver) {
|
||||
try {
|
||||
const parser = gitGraphParser.parser;
|
||||
parser.yy = db;
|
||||
parser.yy.clear();
|
||||
|
||||
logger.debug('in gitgraph renderer', txt + '\n', 'id:', id, ver);
|
||||
// Parse the graph definition
|
||||
parser.parse(txt + '\n');
|
||||
|
||||
config = Object.assign(config, apiConfig, db.getOptions());
|
||||
logger.debug('effective options', config);
|
||||
const direction = db.getDirection();
|
||||
allCommitsDict = db.getCommits();
|
||||
const branches = db.getBranchesAsObjArray();
|
||||
if (direction === 'BT') {
|
||||
config.nodeLabel.x = branches.length * config.branchOffset;
|
||||
config.nodeLabel.width = '100%';
|
||||
config.nodeLabel.y = -1 * 2 * config.nodeRadius;
|
||||
}
|
||||
const svg = select(`[id="${id}"]`);
|
||||
svgCreateDefs(svg);
|
||||
branchNum = 1;
|
||||
for (let branch in branches) {
|
||||
const v = branches[branch];
|
||||
renderCommitHistory(svg, v.commit.id, branches, direction);
|
||||
renderLines(svg, v.commit, direction);
|
||||
branchNum++;
|
||||
}
|
||||
svg.attr('height', function () {
|
||||
if (direction === 'BT') return Object.keys(allCommitsDict).length * config.nodeSpacing;
|
||||
return (branches.length + 1) * config.branchOffset;
|
||||
});
|
||||
} catch (e) {
|
||||
logger.error('Error while rendering gitgraph');
|
||||
logger.error(e.message);
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
setConf,
|
||||
draw,
|
||||
};
|
||||
@@ -1,38 +1,44 @@
|
||||
/* eslint-disable */
|
||||
import { curveBasis, line, select } from 'd3';
|
||||
|
||||
import { interpolateToCurve, getStylesFromArray, configureSvgSize } from '../../utils';
|
||||
import db from './gitGraphAst';
|
||||
//import * as db from './mockDb';
|
||||
import gitGraphParser from './parser/gitGraph';
|
||||
import { log } from '../../logger';
|
||||
import { interpolateToCurve } from '../../utils';
|
||||
/* eslint-disable */
|
||||
import { getConfig } from '../../config';
|
||||
|
||||
//import * as configApi from '../../config';
|
||||
let allCommitsDict = {};
|
||||
let branchNum;
|
||||
let config = {
|
||||
nodeSpacing: 150,
|
||||
nodeFillColor: 'yellow',
|
||||
nodeStrokeWidth: 2,
|
||||
nodeStrokeColor: 'grey',
|
||||
lineStrokeWidth: 4,
|
||||
branchOffset: 50,
|
||||
lineColor: 'grey',
|
||||
leftMargin: 50,
|
||||
branchColors: ['#442f74', '#983351', '#609732', '#AA9A39'],
|
||||
nodeRadius: 10,
|
||||
nodeLabel: {
|
||||
width: 75,
|
||||
height: 100,
|
||||
x: -25,
|
||||
y: 0,
|
||||
},
|
||||
};
|
||||
let apiConfig = {};
|
||||
export const setConf = function (c) {
|
||||
apiConfig = c;
|
||||
|
||||
//let conf = configApi.getConfig();
|
||||
//const commitType = db.commitType;
|
||||
const commitType = {
|
||||
NORMAL: 0,
|
||||
REVERSE: 1,
|
||||
HIGHLIGHT: 2,
|
||||
MERGE: 3,
|
||||
};
|
||||
|
||||
let branchPos = {};
|
||||
let commitPos = {};
|
||||
let lanes = [];
|
||||
let maxPos = 0;
|
||||
const clear = () => {
|
||||
branchPos = {};
|
||||
commitPos = {};
|
||||
allCommitsDict = {};
|
||||
maxPos = 0;
|
||||
lanes = []
|
||||
};
|
||||
|
||||
// let apiConfig = {};
|
||||
// export const setConf = function(c) {
|
||||
// apiConfig = c;
|
||||
// };
|
||||
/** @param svg */
|
||||
function svgCreateDefs(svg) {
|
||||
const config = getConfig().gitGraph;
|
||||
svg
|
||||
.append('defs')
|
||||
.append('g')
|
||||
@@ -60,44 +66,12 @@ function svgCreateDefs(svg) {
|
||||
* @param colorIdx
|
||||
* @param interpolate
|
||||
*/
|
||||
function svgDrawLine(svg, points, colorIdx, interpolate) {
|
||||
const curve = interpolateToCurve(interpolate, curveBasis);
|
||||
const color = config.branchColors[colorIdx % config.branchColors.length];
|
||||
const lineGen = line()
|
||||
.x(function (d) {
|
||||
return Math.round(d.x);
|
||||
})
|
||||
.y(function (d) {
|
||||
return Math.round(d.y);
|
||||
})
|
||||
.curve(curve);
|
||||
|
||||
svg
|
||||
.append('svg:path')
|
||||
.attr('d', lineGen(points))
|
||||
.style('stroke', color)
|
||||
.style('stroke-width', config.lineStrokeWidth)
|
||||
.style('fill', 'none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass in the element and its pre-transform coords
|
||||
// Pass in the element and its pre-transform coords
|
||||
*
|
||||
* @param element
|
||||
* @param coords
|
||||
*/
|
||||
function getElementCoords(element, coords) {
|
||||
coords = coords || element.node().getBBox();
|
||||
const ctm = element.node().getCTM();
|
||||
const xn = ctm.e + coords.x * ctm.a;
|
||||
const yn = ctm.f + coords.y * ctm.d;
|
||||
return {
|
||||
left: xn,
|
||||
top: yn,
|
||||
width: coords.width,
|
||||
height: coords.height,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param svg
|
||||
@@ -106,116 +80,299 @@ function getElementCoords(element, coords) {
|
||||
* @param direction
|
||||
* @param color
|
||||
*/
|
||||
function svgDrawLineForCommits(svg, fromId, toId, direction, color) {
|
||||
log.debug('svgDrawLineForCommits: ', fromId, toId);
|
||||
const fromBbox = getElementCoords(svg.select('#node-' + fromId + ' circle'));
|
||||
const toBbox = getElementCoords(svg.select('#node-' + toId + ' circle'));
|
||||
switch (direction) {
|
||||
case 'LR':
|
||||
// (toBbox)
|
||||
// +--------
|
||||
// + (fromBbox)
|
||||
if (fromBbox.left - toBbox.left > config.nodeSpacing) {
|
||||
const lineStart = {
|
||||
x: fromBbox.left - config.nodeSpacing,
|
||||
y: toBbox.top + toBbox.height / 2,
|
||||
};
|
||||
const lineEnd = { x: toBbox.left + toBbox.width, y: toBbox.top + toBbox.height / 2 };
|
||||
svgDrawLine(svg, [lineStart, lineEnd], color, 'linear');
|
||||
svgDrawLine(
|
||||
svg,
|
||||
[
|
||||
{ x: fromBbox.left, y: fromBbox.top + fromBbox.height / 2 },
|
||||
{ x: fromBbox.left - config.nodeSpacing / 2, y: fromBbox.top + fromBbox.height / 2 },
|
||||
{ x: fromBbox.left - config.nodeSpacing / 2, y: lineStart.y },
|
||||
lineStart,
|
||||
],
|
||||
color
|
||||
);
|
||||
|
||||
const drawText = (txt) => {
|
||||
const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
// svgLabel.setAttribute('style', style.replace('color:', 'fill:'));
|
||||
let rows = [];
|
||||
|
||||
if (typeof txt === 'string') {
|
||||
rows = txt.split(/\\n|\n|<br\s*\/?>/gi);
|
||||
} else if (Array.isArray(txt)) {
|
||||
rows = txt;
|
||||
} else {
|
||||
svgDrawLine(
|
||||
svg,
|
||||
[
|
||||
{
|
||||
x: fromBbox.left,
|
||||
y: fromBbox.top + fromBbox.height / 2,
|
||||
},
|
||||
{
|
||||
x: fromBbox.left - config.nodeSpacing / 2,
|
||||
y: fromBbox.top + fromBbox.height / 2,
|
||||
},
|
||||
{
|
||||
x: fromBbox.left - config.nodeSpacing / 2,
|
||||
y: toBbox.top + toBbox.height / 2,
|
||||
},
|
||||
{
|
||||
x: toBbox.left + toBbox.width,
|
||||
y: toBbox.top + toBbox.height / 2,
|
||||
},
|
||||
],
|
||||
color
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 'BT':
|
||||
// + (fromBbox)
|
||||
// |
|
||||
// |
|
||||
// + (toBbox)
|
||||
if (toBbox.top - fromBbox.top > config.nodeSpacing) {
|
||||
const lineStart = {
|
||||
x: toBbox.left + toBbox.width / 2,
|
||||
y: fromBbox.top + fromBbox.height + config.nodeSpacing,
|
||||
};
|
||||
const lineEnd = { x: toBbox.left + toBbox.width / 2, y: toBbox.top };
|
||||
svgDrawLine(svg, [lineStart, lineEnd], color, 'linear');
|
||||
svgDrawLine(
|
||||
svg,
|
||||
[
|
||||
{ x: fromBbox.left + fromBbox.width / 2, y: fromBbox.top + fromBbox.height },
|
||||
{
|
||||
x: fromBbox.left + fromBbox.width / 2,
|
||||
y: fromBbox.top + fromBbox.height + config.nodeSpacing / 2,
|
||||
},
|
||||
{ x: toBbox.left + toBbox.width / 2, y: lineStart.y - config.nodeSpacing / 2 },
|
||||
lineStart,
|
||||
],
|
||||
color
|
||||
);
|
||||
} else {
|
||||
svgDrawLine(
|
||||
svg,
|
||||
[
|
||||
{
|
||||
x: fromBbox.left + fromBbox.width / 2,
|
||||
y: fromBbox.top + fromBbox.height,
|
||||
},
|
||||
{
|
||||
x: fromBbox.left + fromBbox.width / 2,
|
||||
y: fromBbox.top + config.nodeSpacing / 2,
|
||||
},
|
||||
{
|
||||
x: toBbox.left + toBbox.width / 2,
|
||||
y: toBbox.top - config.nodeSpacing / 2,
|
||||
},
|
||||
{
|
||||
x: toBbox.left + toBbox.width / 2,
|
||||
y: toBbox.top,
|
||||
},
|
||||
],
|
||||
color
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
rows = [];
|
||||
}
|
||||
|
||||
for (let j = 0; j < rows.length; j++) {
|
||||
const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
|
||||
tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
|
||||
tspan.setAttribute('dy', '1em');
|
||||
tspan.setAttribute('x', '0');
|
||||
tspan.setAttribute('class', 'row');
|
||||
tspan.textContent = rows[j].trim();
|
||||
svgLabel.appendChild(tspan);
|
||||
}
|
||||
/**
|
||||
* @param svg
|
||||
* @param selector
|
||||
*/
|
||||
function cloneNode(svg, selector) {
|
||||
return svg.select(selector).node().cloneNode(true);
|
||||
return svgLabel;
|
||||
}
|
||||
|
||||
|
||||
const drawCommits = (svg, commits, modifyGraph) => {
|
||||
const gBullets = svg.append('g').attr('class', 'commit-bullets');
|
||||
const gLabels = svg.append('g').attr('class', 'commit-labels');
|
||||
let pos = 0;
|
||||
|
||||
const keys = Object.keys(commits);
|
||||
const sortedKeys = keys.sort((a, b) => {
|
||||
return commits[a].seq - commits[b].seq;
|
||||
})
|
||||
sortedKeys.forEach((key, index) => {
|
||||
const commit = commits[key];
|
||||
|
||||
const y = branchPos[commit.branch].pos;
|
||||
const x = pos + 10;
|
||||
// Don't draw the commits now but calculate the positioning which is used by the branmch lines etc.
|
||||
if (modifyGraph) {
|
||||
let typeClass;
|
||||
switch(commit.type) {
|
||||
case commitType.NORMAL:
|
||||
typeClass = 'commit-normal';
|
||||
break;
|
||||
case commitType.REVERSE:
|
||||
typeClass = 'commit-reverse';
|
||||
break;
|
||||
case commitType.HIGHLIGHT:
|
||||
typeClass = 'commit-highlight';
|
||||
break;
|
||||
case commitType.MERGE:
|
||||
typeClass = 'commit-merge';
|
||||
break;
|
||||
default:
|
||||
typeClass = 'commit-normal';
|
||||
}
|
||||
|
||||
if (commit.type === commitType.HIGHLIGHT) {
|
||||
const circle = gBullets.append('rect');
|
||||
circle.attr('x', x-10);
|
||||
circle.attr('y', y-10);
|
||||
circle.attr('height', 20);
|
||||
circle.attr('width', 20);
|
||||
circle.attr('class', 'commit ' + commit.id + ' commit-highlight' + branchPos[commit.branch].index + ' ' + typeClass+'-outer');
|
||||
gBullets.append('rect')
|
||||
.attr('x', x-6)
|
||||
.attr('y', y-6)
|
||||
.attr('height', 12)
|
||||
.attr('width', 12)
|
||||
.attr('class', 'commit ' + commit.id + ' commit' + branchPos[commit.branch].index + ' ' + typeClass+'-inner');
|
||||
} else {
|
||||
const circle = gBullets.append('circle');
|
||||
circle.attr('cx', x);
|
||||
circle.attr('cy', y);
|
||||
circle.attr('r', commit.type === commitType.MERGE ? 9:10);
|
||||
circle.attr('class', 'commit ' + commit.id + ' commit' + branchPos[commit.branch].index);
|
||||
if(commit.type === commitType.MERGE) {
|
||||
const circle2 = gBullets.append('circle');
|
||||
circle2.attr('cx', x);
|
||||
circle2.attr('cy', y);
|
||||
circle2.attr('r', 6);
|
||||
circle2.attr('class', 'commit '+typeClass + ' ' + commit.id + ' commit' + branchPos[commit.branch].index);
|
||||
}
|
||||
if(commit.type === commitType.REVERSE) {
|
||||
const cross = gBullets.append('path');
|
||||
cross
|
||||
.attr('d', `M ${x-5},${y-5}L${x+5},${y+5}M${x-5},${y+5}L${x+5},${y-5}`)
|
||||
.attr('class', 'commit '+typeClass + ' ' + commit.id + ' commit' + branchPos[commit.branch].index);
|
||||
}
|
||||
}
|
||||
}
|
||||
commitPos[commit.id] = {x: pos + 10, y: y};
|
||||
|
||||
// The first iteration over the commits are for positioning purposes, this
|
||||
// is required for drawing the lines. The circles and labels is drawn after the labels
|
||||
// placing them on top of the lines.
|
||||
if (modifyGraph) {
|
||||
const px=4;
|
||||
const py=2;
|
||||
if(commit.type !== commitType.MERGE) {
|
||||
const labelBkg = gLabels.insert('rect')
|
||||
.attr('class', 'commit-label-bkg');
|
||||
|
||||
const text = gLabels.append('text')
|
||||
.attr('x', pos)
|
||||
.attr('y', y + 25)
|
||||
.attr('class', 'commit-label')
|
||||
.text(commit.id);
|
||||
let bbox = text.node().getBBox();
|
||||
|
||||
// Now we have the label, lets position the background
|
||||
labelBkg
|
||||
.attr('x', pos + 10 - bbox.width / 2 - py)
|
||||
.attr('y', y + 13.5)
|
||||
.attr('width', bbox.width + 2 * py)
|
||||
.attr('height', bbox.height + 2 * py);
|
||||
text.attr('x', pos + 10 - bbox.width / 2);
|
||||
}
|
||||
if(commit.tag) {
|
||||
const rect = gLabels.insert('polygon');
|
||||
const hole = gLabels.append('circle');
|
||||
const tag = gLabels.append('text')
|
||||
// Note that we are delaying setting the x position until we know the width of the text
|
||||
.attr('y', y - 16)
|
||||
.attr('class', 'tag-label')
|
||||
.text(commit.tag);
|
||||
let tagBbox = tag.node().getBBox();
|
||||
tag.attr('x', pos + 10 - tagBbox.width / 2);
|
||||
|
||||
const h2 = tagBbox.height/2
|
||||
const ly = y - 19.2 ;
|
||||
rect
|
||||
.attr('class', 'tag-label-bkg')
|
||||
.attr('points', `
|
||||
${pos - tagBbox.width / 2 - px/2},${ly + py}
|
||||
${pos - tagBbox.width / 2 - px/2},${ly - py}
|
||||
${pos + 10 - tagBbox.width / 2 - px},${ly - h2 - py}
|
||||
${pos + 10 + tagBbox.width / 2 + px},${ly - h2 - py}
|
||||
${pos + 10 + tagBbox.width / 2 + px},${ly + h2 + py }
|
||||
${pos + 10 - tagBbox.width / 2 - px},${ly + h2 + py}`);
|
||||
|
||||
hole
|
||||
.attr('cx', pos - tagBbox.width / 2 + px/2)
|
||||
.attr('cy', ly)
|
||||
.attr('r', 1.5)
|
||||
.attr('class', 'tag-hole');
|
||||
|
||||
}
|
||||
}
|
||||
pos +=50;
|
||||
if(pos>maxPos) {
|
||||
maxPos = pos;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect if there are other commits between commit1s x-position and commit2s x-position on the same branch as commit2.
|
||||
* @param {*} commit1
|
||||
* @param {*} commit2
|
||||
* @returns
|
||||
*/
|
||||
const hasOverlappingCommits = (commit1, commit2, allCommits) => {
|
||||
const commit1Pos = commitPos[commit2.id];
|
||||
const commit2Pos = commitPos[commit1.id];
|
||||
|
||||
// Find commits on the same branch as commit2
|
||||
const keys = Object.keys(allCommits);
|
||||
const overlappingComits = keys.filter((key) => {
|
||||
return allCommits[key].branch === commit2.branch && allCommits[key].seq > commit1.seq && allCommits[key].seq < commit2.seq
|
||||
});
|
||||
|
||||
return overlappingComits.length > 0;
|
||||
}
|
||||
/**
|
||||
*
|
||||
*/
|
||||
const findLane = (y1, y2, _depth) => {
|
||||
const depth = _depth || 0;
|
||||
|
||||
const candidate = y1 + Math.abs(y1 - y2) / 2;
|
||||
if(depth > 5) {
|
||||
return candidate;
|
||||
}
|
||||
|
||||
let ok = true;
|
||||
for(let i = 0; i < lanes.length; i++) {
|
||||
if(Math.abs(lanes[i] - candidate) < 10) {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
if(ok) {
|
||||
lanes.push(candidate);
|
||||
return candidate;
|
||||
}
|
||||
const diff = Math.abs(y1 - y2);
|
||||
return findLane(y1, y2-(diff/5), depth);
|
||||
}
|
||||
|
||||
const drawArrow = (svg, commit1, commit2, allCommits) => {
|
||||
const conf = getConfig();
|
||||
|
||||
const p1 = commitPos[commit1.id];
|
||||
const p2 = commitPos[commit2.id];
|
||||
const overlappingCommits = hasOverlappingCommits(commit1, commit2, allCommits);
|
||||
log.debug('drawArrow', p1, p2, overlappingCommits, commit1.id, commit2.id);
|
||||
|
||||
let url = '';
|
||||
if (conf.arrowMarkerAbsolute) {
|
||||
url =
|
||||
window.location.protocol +
|
||||
'//' +
|
||||
window.location.host +
|
||||
window.location.pathname +
|
||||
window.location.search;
|
||||
url = url.replace(/\(/g, '\\(');
|
||||
url = url.replace(/\)/g, '\\)');
|
||||
}
|
||||
|
||||
let arc = '';
|
||||
let arc2 = '';
|
||||
let radius = 0;
|
||||
let offset = 0
|
||||
let colorClassNum = branchPos[commit2.branch].index
|
||||
let lineDef;
|
||||
if(overlappingCommits) {
|
||||
arc = 'A 10 10, 0, 0, 0,';
|
||||
arc2 = 'A 10 10, 0, 0, 1,';
|
||||
radius = 10;
|
||||
offset = 10;
|
||||
// Figure out the color of the arrow,arrows going down take the color from the destination branch
|
||||
colorClassNum = branchPos[commit2.branch].index;
|
||||
|
||||
const lineY = p1.y < p2.y ? findLane(p1.y, p2.y):findLane(p2.y, p1.y);
|
||||
|
||||
if(p1.y < p2.y) {
|
||||
lineDef = `M ${p1.x} ${p1.y} L ${p1.x} ${lineY-radius} ${arc} ${p1.x + offset} ${lineY} L ${p2.x-radius} ${lineY} ${arc2} ${p2.x} ${lineY+offset} L ${p2.x} ${p2.y}`;
|
||||
} else {
|
||||
lineDef = `M ${p1.x} ${p1.y} L ${p1.x} ${lineY+radius} ${arc2} ${p1.x + offset} ${lineY} L ${p2.x-radius} ${lineY} ${arc} ${p2.x} ${lineY-offset} L ${p2.x} ${p2.y}`;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if(p1.y < p2.y) {
|
||||
arc = 'A 20 20, 0, 0, 0,';
|
||||
radius = 20;
|
||||
offset = 20;
|
||||
|
||||
// Figure out the color of the arrow,arrows going down take the color from the destination branch
|
||||
colorClassNum = branchPos[commit2.branch].index;
|
||||
|
||||
lineDef = `M ${p1.x} ${p1.y} L ${p1.x} ${p2.y-radius} ${arc} ${p1.x + offset} ${p2.y} L ${p2.x} ${p2.y}`;
|
||||
}
|
||||
if(p1.y > p2.y) {
|
||||
arc = 'A 20 20, 0, 0, 0,';
|
||||
radius = 20;
|
||||
offset = 20;
|
||||
|
||||
// Arrows going up take the color from the source branch
|
||||
colorClassNum = branchPos[commit1.branch].index;
|
||||
lineDef = `M ${p1.x} ${p1.y} L ${p2.x-radius} ${p1.y} ${arc} ${p2.x} ${p1.y-offset} L ${p2.x} ${p2.y}`;
|
||||
}
|
||||
|
||||
if(p1.y === p2.y) {
|
||||
colorClassNum = branchPos[commit1.branch].index
|
||||
lineDef = `M ${p1.x} ${p1.y} L ${p1.x} ${p2.y-radius} ${arc} ${p1.x + offset} ${p2.y} L ${p2.x} ${p2.y}`;
|
||||
}
|
||||
}
|
||||
const arrow = svg.append('path').attr('d', lineDef)
|
||||
.attr('class', 'arrow arrow' + colorClassNum)
|
||||
}
|
||||
|
||||
const drawArrows = (svg, commits) => {
|
||||
const gArrows = svg.append('g').attr('class', 'commit-arrows');
|
||||
let pos = 0;
|
||||
|
||||
const k = Object.keys(commits);
|
||||
k.forEach((key, index) => {
|
||||
const commit = commits[key];
|
||||
if(commit.parents && commit.parents.length>0) {
|
||||
commit.parents.forEach((parent) => {
|
||||
drawArrow(gArrows, commits[parent], commit, commits);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -224,88 +381,41 @@ function cloneNode(svg, selector) {
|
||||
* @param branches
|
||||
* @param direction
|
||||
*/
|
||||
function renderCommitHistory(svg, commitid, branches, direction) {
|
||||
let commit;
|
||||
const numCommits = Object.keys(allCommitsDict).length;
|
||||
if (typeof commitid === 'string') {
|
||||
let cnt = 0;
|
||||
do {
|
||||
cnt++;
|
||||
commit = allCommitsDict[commitid];
|
||||
log.debug('in renderCommitHistory', commit.id, commit.seq);
|
||||
if (svg.select('#node-' + commitid).size() > 0) {
|
||||
return;
|
||||
}
|
||||
svg
|
||||
.append(function () {
|
||||
return cloneNode(svg, '#def-commit');
|
||||
})
|
||||
.attr('class', 'commit')
|
||||
.attr('id', function () {
|
||||
return 'node-' + commit.id;
|
||||
})
|
||||
.attr('transform', function () {
|
||||
switch (direction) {
|
||||
case 'LR':
|
||||
return (
|
||||
'translate(' +
|
||||
(commit.seq * config.nodeSpacing + config.leftMargin) +
|
||||
', ' +
|
||||
branchNum * config.branchOffset +
|
||||
')'
|
||||
);
|
||||
case 'BT':
|
||||
return (
|
||||
'translate(' +
|
||||
(branchNum * config.branchOffset + config.leftMargin) +
|
||||
', ' +
|
||||
(numCommits - commit.seq) * config.nodeSpacing +
|
||||
')'
|
||||
);
|
||||
}
|
||||
})
|
||||
.attr('fill', config.nodeFillColor)
|
||||
.attr('stroke', config.nodeStrokeColor)
|
||||
.attr('stroke-width', config.nodeStrokeWidth);
|
||||
const drawBranches = (svg, branches) => {
|
||||
const g = svg.append('g')
|
||||
branches.forEach((branch, index) => {
|
||||
const pos = branchPos[branch.name].pos;
|
||||
const line = g.append('line');
|
||||
line.attr('x1', 0);
|
||||
line.attr('y1', pos);
|
||||
line.attr('x2', maxPos);
|
||||
line.attr('y2', pos);
|
||||
line.attr('class', 'branch branch'+index)
|
||||
|
||||
let branch;
|
||||
for (let branchName in branches) {
|
||||
if (branches[branchName].commit === commit) {
|
||||
branch = branches[branchName];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (branch) {
|
||||
log.debug('found branch ', branch.name);
|
||||
svg
|
||||
.select('#node-' + commit.id + ' p')
|
||||
.append('xhtml:span')
|
||||
.attr('class', 'branch-label')
|
||||
.text(branch.name + ', ');
|
||||
}
|
||||
svg
|
||||
.select('#node-' + commit.id + ' p')
|
||||
.append('xhtml:span')
|
||||
.attr('class', 'commit-id')
|
||||
.text(commit.id);
|
||||
if (commit.message !== '' && direction === 'BT') {
|
||||
svg
|
||||
.select('#node-' + commit.id + ' p')
|
||||
.append('xhtml:span')
|
||||
.attr('class', 'commit-msg')
|
||||
.text(', ' + commit.message);
|
||||
}
|
||||
commitid = commit.parent;
|
||||
} while (commitid && allCommitsDict[commitid] && cnt < 1000);
|
||||
}
|
||||
lanes.push(pos);
|
||||
|
||||
// Create the actual text element
|
||||
const labelElement = drawText(branch.name);
|
||||
// Create outer g, edgeLabel, this will be positioned after graph layout
|
||||
const bkg = g.insert('rect');
|
||||
const branchLabel = g.insert('g').attr('class', 'branchLabel');
|
||||
|
||||
// Create inner g, label, this will be positioned now for centering the text
|
||||
const label = branchLabel.insert('g').attr('class', 'label branch-label'+index);
|
||||
label.node().appendChild(labelElement);
|
||||
let bbox = labelElement.getBBox();
|
||||
bkg.attr('class', 'branchLabelBkg label' + index)
|
||||
.attr('rx', 4)
|
||||
.attr('ry', 4)
|
||||
.attr('x', -bbox.width -4)
|
||||
.attr('y', -bbox.height / 2 +8 )
|
||||
.attr('width', bbox.width + 18)
|
||||
.attr('height', bbox.height + 4);
|
||||
|
||||
label.attr('transform', 'translate(' + (-bbox.width -14) + ', ' + (pos - bbox.height/2-1) + ')');
|
||||
bkg.attr('transform', 'translate(' + -19 + ', ' + (pos - bbox.height/2) + ')');
|
||||
})
|
||||
|
||||
if (Array.isArray(commitid)) {
|
||||
log.debug('found merge commmit', commitid);
|
||||
renderCommitHistory(svg, commitid[0], branches, direction);
|
||||
branchNum++;
|
||||
renderCommitHistory(svg, commitid[1], branches, direction);
|
||||
branchNum--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,77 +424,69 @@ function renderCommitHistory(svg, commitid, branches, direction) {
|
||||
* @param direction
|
||||
* @param branchColor
|
||||
*/
|
||||
function renderLines(svg, commit, direction, branchColor) {
|
||||
branchColor = branchColor || 0;
|
||||
let cnt = 0;
|
||||
while (commit.seq > 0 && !commit.lineDrawn && cnt < 1000) {
|
||||
cnt++;
|
||||
if (typeof commit.parent === 'string') {
|
||||
svgDrawLineForCommits(svg, commit.id, commit.parent, direction, branchColor);
|
||||
commit.lineDrawn = true;
|
||||
commit = allCommitsDict[commit.parent];
|
||||
} else if (Array.isArray(commit.parent)) {
|
||||
svgDrawLineForCommits(svg, commit.id, commit.parent[0], direction, branchColor);
|
||||
svgDrawLineForCommits(svg, commit.id, commit.parent[1], direction, branchColor + 1);
|
||||
renderLines(svg, allCommitsDict[commit.parent[1]], direction, branchColor + 1);
|
||||
commit.lineDrawn = true;
|
||||
commit = allCommitsDict[commit.parent[0]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const draw = function (txt, id, ver) {
|
||||
try {
|
||||
clear();
|
||||
const conf = getConfig();
|
||||
const config = conf.gitGraph;
|
||||
// try {
|
||||
const parser = gitGraphParser.parser;
|
||||
parser.yy = db;
|
||||
parser.yy.clear();
|
||||
|
||||
const securityLevel = getConfig().securityLevel;
|
||||
// Handle root and ocument for when rendering in sanbox mode
|
||||
let sandboxElement;
|
||||
if (securityLevel === 'sandbox') {
|
||||
sandboxElement = select('#i' + id);
|
||||
}
|
||||
const root =
|
||||
securityLevel === 'sandbox'
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
: select('body');
|
||||
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
||||
|
||||
log.debug('in gitgraph renderer', txt + '\n', 'id:', id, ver);
|
||||
// Parse the graph definition
|
||||
// // Parse the graph definition
|
||||
parser.parse(txt + '\n');
|
||||
|
||||
config = Object.assign(config, apiConfig, db.getOptions());
|
||||
log.debug('effective options', config);
|
||||
// config = Object.assign(config, apiConfig, db.getOptions());
|
||||
const direction = db.getDirection();
|
||||
allCommitsDict = db.getCommits();
|
||||
const branches = db.getBranchesAsObjArray();
|
||||
if (direction === 'BT') {
|
||||
config.nodeLabel.x = branches.length * config.branchOffset;
|
||||
config.nodeLabel.width = '100%';
|
||||
config.nodeLabel.y = -1 * 2 * config.nodeRadius;
|
||||
}
|
||||
const svg = root.select(`[id="${id}"]`);
|
||||
svgCreateDefs(svg);
|
||||
branchNum = 1;
|
||||
for (let branch in branches) {
|
||||
const v = branches[branch];
|
||||
renderCommitHistory(svg, v.commit.id, branches, direction);
|
||||
renderLines(svg, v.commit, direction);
|
||||
branchNum++;
|
||||
}
|
||||
svg.attr('height', function () {
|
||||
if (direction === 'BT') return Object.keys(allCommitsDict).length * config.nodeSpacing;
|
||||
return (branches.length + 1) * config.branchOffset;
|
||||
|
||||
// Position branches vertically
|
||||
let pos=0;
|
||||
branches.forEach((branch, index) => {
|
||||
branchPos[branch.name] = {pos, index};
|
||||
pos+=50;
|
||||
});
|
||||
} catch (e) {
|
||||
log.error('Error while rendering gitgraph');
|
||||
log.error(e.message);
|
||||
}
|
||||
|
||||
|
||||
|
||||
log.debug('brach pos ', branchPos);
|
||||
log.debug('effective options', config, branches);
|
||||
log.debug('commits', allCommitsDict);
|
||||
|
||||
const diagram = select(`[id="${id}"]`);
|
||||
svgCreateDefs(diagram);
|
||||
|
||||
diagram
|
||||
.append('defs')
|
||||
.append('marker')
|
||||
.attr('id', 'arrowhead')
|
||||
.attr('refX',24)
|
||||
.attr('refY', 10)
|
||||
.attr('markerUnits', 'userSpaceOnUse')
|
||||
.attr('markerWidth', 24)
|
||||
.attr('markerHeight', 24)
|
||||
.attr('orient', 'auto')
|
||||
.append('path')
|
||||
.attr('d', 'M 0 0 L 20 10 L 0 20 z'); // this is actual shape for arrowhead
|
||||
|
||||
drawCommits(diagram, allCommitsDict, false);
|
||||
drawBranches(diagram, branches);
|
||||
drawArrows(diagram, allCommitsDict);
|
||||
drawCommits(diagram, allCommitsDict, true);
|
||||
|
||||
const padding = config.diagramPadding;
|
||||
const svgBounds = diagram.node().getBBox();
|
||||
const width = svgBounds.width + padding * 2;
|
||||
const height = svgBounds.height + padding * 2;
|
||||
|
||||
configureSvgSize(diagram, height, width, conf.useMaxWidth);
|
||||
const vBox = `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`;
|
||||
// logger.debug(`viewBox ${vBox}`);
|
||||
diagram.attr('viewBox', vBox);
|
||||
};
|
||||
|
||||
export default {
|
||||
setConf,
|
||||
draw,
|
||||
};
|
||||
|
||||
21
src/diagrams/git/layout.js
Normal file
21
src/diagrams/git/layout.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import { getConfig } from '../../config';
|
||||
|
||||
export default (dir, _branches, _commits) => { // eslint-disable-line
|
||||
const config = getConfig().gitGraph;
|
||||
const branches = [];
|
||||
const commits = [];
|
||||
|
||||
for (let i = 0; i < _branches.length; i++) {
|
||||
const branch = Object.assign({}, _branches[i]);
|
||||
if (dir === 'TB' || dir === 'BT') {
|
||||
branch.x = config.branchOffset * i;
|
||||
branch.y = -1;
|
||||
} else {
|
||||
branch.y = config.branchOffset * i;
|
||||
branch.x = -1;
|
||||
}
|
||||
branches.push(branch);
|
||||
}
|
||||
|
||||
return { branches, commits };
|
||||
};
|
||||
196
src/diagrams/git/mockDb.js
Normal file
196
src/diagrams/git/mockDb.js
Normal file
@@ -0,0 +1,196 @@
|
||||
export const getDirection = () => 'LR';
|
||||
export const getCommits = () => {
|
||||
return {
|
||||
'0000001': {
|
||||
id: '0000001',
|
||||
seq: 1,
|
||||
message: '',
|
||||
branch: 'master',
|
||||
parents: null,
|
||||
tag: 'v0.1',
|
||||
commitType: 'normal',
|
||||
note: null,
|
||||
},
|
||||
'0000002': {
|
||||
id: '0000002',
|
||||
seq: 2,
|
||||
message: '',
|
||||
branch: 'develop',
|
||||
parents: ['0000001'],
|
||||
tag: null,
|
||||
commitType: 'normal',
|
||||
note: null,
|
||||
},
|
||||
'0000003': {
|
||||
id: '0000003',
|
||||
seq: 3,
|
||||
message: '',
|
||||
branch: 'featureB',
|
||||
parents: ['0000002'],
|
||||
tag: null,
|
||||
commitType: 'normal',
|
||||
note: null,
|
||||
},
|
||||
'0000004': {
|
||||
id: '0000004',
|
||||
seq: 4,
|
||||
message: '',
|
||||
branch: 'hotfix',
|
||||
parents: ['0000001'],
|
||||
tag: null,
|
||||
commitType: 'normal',
|
||||
note: null,
|
||||
},
|
||||
'0000005': {
|
||||
id: '0000005',
|
||||
seq: 5,
|
||||
message: '',
|
||||
branch: 'develop',
|
||||
parents: ['0000002'],
|
||||
tag: null,
|
||||
commitType: 'normal',
|
||||
note: null,
|
||||
},
|
||||
'0000006': {
|
||||
id: '0000006',
|
||||
seq: 6,
|
||||
message: '',
|
||||
branch: 'featureB',
|
||||
parents: ['0000003'],
|
||||
tag: null,
|
||||
commitType: 'normal',
|
||||
note: null,
|
||||
},
|
||||
'0000007': {
|
||||
id: '0000007',
|
||||
seq: 7,
|
||||
message: '',
|
||||
branch: 'master',
|
||||
parents: ['0000004'],
|
||||
tag: 'v0.2',
|
||||
commitType: 'normal',
|
||||
note: null,
|
||||
},
|
||||
'0000008': {
|
||||
id: '0000008',
|
||||
seq: 8,
|
||||
message: '',
|
||||
branch: 'featureB',
|
||||
parents: ['0000006'],
|
||||
tag: null,
|
||||
commitType: 'normal',
|
||||
note: null,
|
||||
},
|
||||
'0000009': {
|
||||
id: '0000009',
|
||||
seq: 9,
|
||||
message: '',
|
||||
branch: 'featureA',
|
||||
parents: ['0000005'],
|
||||
tag: null,
|
||||
commitType: 'normal',
|
||||
note: null,
|
||||
},
|
||||
'0000010': {
|
||||
id: '0000010',
|
||||
seq: 10,
|
||||
message: '',
|
||||
branch: 'develop',
|
||||
parents: ['0000004', '0000005'],
|
||||
tag: null,
|
||||
commitType: 'normal',
|
||||
note: null,
|
||||
},
|
||||
'0000011': {
|
||||
id: '0000011',
|
||||
seq: 11,
|
||||
message: '',
|
||||
branch: 'featureA',
|
||||
parents: ['0000009'],
|
||||
tag: null,
|
||||
commitType: 'normal',
|
||||
note: '',
|
||||
},
|
||||
'0000012': {
|
||||
id: '0000012',
|
||||
seq: 12,
|
||||
message: '',
|
||||
branch: 'featureB',
|
||||
parents: ['0000008'],
|
||||
tag: null,
|
||||
commitType: 'normal',
|
||||
note: null,
|
||||
},
|
||||
'0000013': {
|
||||
id: '0000013',
|
||||
seq: 13,
|
||||
message: '',
|
||||
branch: 'develop',
|
||||
parents: ['0000010', '0000011'],
|
||||
tag: null,
|
||||
commitType: 'normal',
|
||||
note: null,
|
||||
},
|
||||
'0000014': {
|
||||
id: '0000014',
|
||||
seq: 14,
|
||||
message: '',
|
||||
branch: 'release',
|
||||
parents: ['0000013'],
|
||||
tag: null,
|
||||
commitType: 'normal',
|
||||
note: null,
|
||||
},
|
||||
'0000015': {
|
||||
id: '0000015',
|
||||
seq: 15,
|
||||
message: '',
|
||||
branch: 'master',
|
||||
parents: ['0000007'],
|
||||
tag: null,
|
||||
commitType: 'normal',
|
||||
note: null,
|
||||
},
|
||||
'0000016': {
|
||||
id: '0000016',
|
||||
seq: 16,
|
||||
message: '',
|
||||
branch: 'release',
|
||||
parents: ['0000014', '0000015'],
|
||||
tag: 'v1.0',
|
||||
commitType: 'normal',
|
||||
note: null,
|
||||
},
|
||||
'0000017': {
|
||||
id: '0000017',
|
||||
seq: 17,
|
||||
message: '',
|
||||
branch: 'develop',
|
||||
parents: ['0000013', '0000016'],
|
||||
tag: null,
|
||||
commitType: 'normal',
|
||||
note: null,
|
||||
},
|
||||
};
|
||||
};
|
||||
export const clear = () => {};
|
||||
export const getBranchesAsObjArray = () => [
|
||||
{
|
||||
name: 'master',
|
||||
},
|
||||
{
|
||||
name: 'hotfix',
|
||||
},
|
||||
{
|
||||
name: 'release',
|
||||
},
|
||||
{
|
||||
name: 'develop',
|
||||
},
|
||||
{
|
||||
name: 'featureA',
|
||||
},
|
||||
{
|
||||
name: 'featureB',
|
||||
},
|
||||
];
|
||||
39
src/diagrams/git/parser/desired syntax
Normal file
39
src/diagrams/git/parser/desired syntax
Normal file
@@ -0,0 +1,39 @@
|
||||
commit
|
||||
branch develop
|
||||
checkout develop
|
||||
commit
|
||||
branch featureB
|
||||
checkout featureB
|
||||
commit
|
||||
checkout master
|
||||
branch hotfix
|
||||
checkout hotfix
|
||||
commit
|
||||
checkout develop
|
||||
commit
|
||||
checkout featureB
|
||||
commit
|
||||
checkout master
|
||||
merge hotfix
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
branch featureA
|
||||
commit
|
||||
checkout develop
|
||||
merge hotfix
|
||||
checkout featureA
|
||||
commit
|
||||
checkout featureB
|
||||
commit
|
||||
checkout develop
|
||||
merge featureA
|
||||
branch release
|
||||
checkout release
|
||||
commit
|
||||
checkout master
|
||||
commit
|
||||
checkout release
|
||||
merge master
|
||||
checkout develop
|
||||
merge release
|
||||
@@ -9,19 +9,35 @@
|
||||
|
||||
%x string
|
||||
%x options
|
||||
%x open_directive
|
||||
%x type_directive
|
||||
%x arg_directive
|
||||
%x close_directive
|
||||
%options case-insensitive
|
||||
|
||||
%%
|
||||
|
||||
(\r?\n)+ return 'NL';
|
||||
%%
|
||||
\%\%\{ { this.begin('open_directive'); return 'open_directive'; }
|
||||
<open_directive>((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; }
|
||||
<type_directive>":" { this.popState(); this.begin('arg_directive'); return ':'; }
|
||||
<type_directive,arg_directive>\}\%\% { this.popState(); this.popState(); return 'close_directive'; }
|
||||
<arg_directive>((?:(?!\}\%\%).|\n)*) return 'arg_directive';
|
||||
(\r?\n)+ /*{console.log('New line');return 'NL';}*/ return 'NL';
|
||||
\s+ /* skip all whitespace */
|
||||
\#[^\n]* /* skip comments */
|
||||
\%%[^\n]* /* skip comments */
|
||||
"gitGraph" return 'GG';
|
||||
"commit" return 'COMMIT';
|
||||
"id:" return 'COMMIT_ID';
|
||||
"type:" return 'COMMIT_TYPE';
|
||||
"msg:" return 'COMMIT_MSG';
|
||||
"NORMAL" return 'NORMAL';
|
||||
"REVERSE" return 'REVERSE';
|
||||
"HIGHLIGHT" return 'HIGHLIGHT';
|
||||
"tag:" return 'COMMIT_TAG';
|
||||
"branch" return 'BRANCH';
|
||||
"merge" return 'MERGE';
|
||||
"reset" return 'RESET';
|
||||
// "reset" return 'RESET';
|
||||
"checkout" return 'CHECKOUT';
|
||||
"LR" return 'DIR';
|
||||
"BT" return 'DIR';
|
||||
@@ -45,7 +61,10 @@
|
||||
%% /* language grammar */
|
||||
|
||||
start
|
||||
: GG ':' document EOF{ return $3; }
|
||||
: eol start
|
||||
| directive start
|
||||
| GG document EOF{ return $3; }
|
||||
| GG ':' document EOF{ return $3; }
|
||||
| GG DIR ':' document EOF {yy.setDirection($2); return $4;}
|
||||
;
|
||||
|
||||
@@ -64,28 +83,144 @@ body
|
||||
| body line {$1.push($2); $$=$1;}
|
||||
;
|
||||
line
|
||||
: statement NL{$$ =$1}
|
||||
: statement eol {$$ =$1}
|
||||
| NL
|
||||
;
|
||||
|
||||
statement
|
||||
: COMMIT commit_arg {yy.commit($2)}
|
||||
: commitStatement
|
||||
| BRANCH ID {yy.branch($2)}
|
||||
| CHECKOUT ID {yy.checkout($2)}
|
||||
| MERGE ID {yy.merge($2)}
|
||||
| RESET reset_arg {yy.reset($2)}
|
||||
// | RESET reset_arg {yy.reset($2)}
|
||||
;
|
||||
commitStatement
|
||||
: COMMIT commit_arg {yy.commit($2)}
|
||||
| COMMIT COMMIT_TAG STR {yy.commit('','',yy.commitType.NORMAL,$3)}
|
||||
| COMMIT COMMIT_TYPE commitType {yy.commit('','',$3,'')}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_TYPE commitType {yy.commit('','',$5,$3)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_TAG STR {yy.commit('','',$3,$5)}
|
||||
| COMMIT COMMIT_ID STR {yy.commit('',$3,yy.commitType.NORMAL,'')}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TAG STR {yy.commit('',$3,yy.commitType.NORMAL,$5)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_ID STR {yy.commit('',$5,yy.commitType.NORMAL,$3)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TYPE commitType {yy.commit('',$3,$5,'')}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_ID STR {yy.commit('',$5,$3,'')}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TYPE commitType COMMIT_TAG STR {yy.commit('',$3,$5,$7)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TAG STR COMMIT_TYPE commitType {yy.commit('',$3,$7,$5)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_ID STR COMMIT_TAG STR {yy.commit('',$5,$3,$7)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_TAG STR COMMIT_ID STR {yy.commit('',$7,$3,$5)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_TYPE commitType COMMIT_ID STR {yy.commit('',$7,$5,$3)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_ID STR COMMIT_TYPE commitType {yy.commit('',$5,$7,$3)}
|
||||
| COMMIT COMMIT_MSG STR {yy.commit($3,'',yy.commitType.NORMAL,'')}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_MSG STR {yy.commit($5,'',yy.commitType.NORMAL,$3)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TAG STR {yy.commit($3,'',yy.commitType.NORMAL,$5)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TYPE commitType {yy.commit($3,'',$5,'')}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_MSG STR {yy.commit($5,'',$3,'')}
|
||||
| COMMIT COMMIT_ID STR COMMIT_MSG STR {yy.commit($5,$3,yy.commitType.NORMAL,'')}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_ID STR {yy.commit($3,$5,yy.commitType.NORMAL,'')}
|
||||
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TYPE commitType COMMIT_TAG STR {yy.commit($3,'',$5,$7)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TAG STR COMMIT_TYPE commitType {yy.commit($3,'',$7,$5)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_MSG STR COMMIT_TAG STR {yy.commit($5,'',$3,$7)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_TAG STR COMMIT_MSG STR {yy.commit($7,'',$3,$5)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_TYPE commitType COMMIT_MSG STR {yy.commit($7,'',$5,$3)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_MSG STR COMMIT_TYPE commitType {yy.commit($5,'',$7,$3)}
|
||||
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TYPE commitType COMMIT_ID STR {yy.commit($3,$7,$5,'')}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_ID STR COMMIT_TYPE commitType {yy.commit($3,$5,$7,'')}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_MSG STR COMMIT_ID STR {yy.commit($5,$7,$3,'')}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_ID STR COMMIT_MSG STR {yy.commit($7,$5,$3,'')}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TYPE commitType COMMIT_MSG STR {yy.commit($7,$3,$5,'')}
|
||||
| COMMIT COMMIT_ID STR COMMIT_MSG STR COMMIT_TYPE commitType {yy.commit($5,$3,$7,'')}
|
||||
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TAG STR COMMIT_ID STR {yy.commit($3,$7,yy.commitType.NORMAL,$5)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_ID STR COMMIT_TAG STR {yy.commit($3,$5,yy.commitType.NORMAL,$7)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_MSG STR COMMIT_ID STR {yy.commit($5,$7,yy.commitType.NORMAL,$3)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_ID STR COMMIT_MSG STR {yy.commit($7,$5,yy.commitType.NORMAL,$3)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TAG STR COMMIT_MSG STR {yy.commit($7,$3,yy.commitType.NORMAL,$5)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_MSG STR COMMIT_TAG STR {yy.commit($5,$3,yy.commitType.NORMAL,$7)}
|
||||
|
||||
| COMMIT COMMIT_MSG STR COMMIT_ID STR COMMIT_TYPE commitType COMMIT_TAG STR {yy.commit($3,$5,$7,$9)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_ID STR COMMIT_TAG STR COMMIT_TYPE commitType {yy.commit($3,$5,$9,$7)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TYPE commitType COMMIT_ID STR COMMIT_TAG STR {yy.commit($3,$7,$5,$9)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TYPE commitType COMMIT_TAG STR COMMIT_ID STR {yy.commit($3,$9,$5,$7)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TAG STR COMMIT_ID STR COMMIT_TYPE commitType {yy.commit($3,$7,$9,$5)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TAG STR COMMIT_TYPE commitType COMMIT_ID STR {yy.commit($3,$9,$7,$5)}
|
||||
|
||||
| COMMIT COMMIT_ID STR COMMIT_MSG STR COMMIT_TYPE commitType COMMIT_TAG STR {yy.commit($5,$3,$7,$9)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_MSG STR COMMIT_TAG STR COMMIT_TYPE commitType {yy.commit($5,$3,$9,$7)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TYPE commitType COMMIT_MSG STR COMMIT_TAG STR {yy.commit($7,$3,$5,$9)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TYPE commitType COMMIT_TAG STR COMMIT_MSG STR {yy.commit($9,$3,$5,$7)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TAG STR COMMIT_MSG STR COMMIT_TYPE commitType {yy.commit($7,$3,$9,$5)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TAG STR COMMIT_TYPE commitType COMMIT_MSG STR {yy.commit($9,$3,$7,$5)}
|
||||
|
||||
| COMMIT COMMIT_TAG STR COMMIT_ID STR COMMIT_TYPE commitType COMMIT_MSG STR {yy.commit($9,$5,$7,$3)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_ID STR COMMIT_MSG STR COMMIT_TYPE commitType {yy.commit($7,$5,$9,$3)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_TYPE commitType COMMIT_ID STR COMMIT_MSG STR {yy.commit($9,$7,$5,$3)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_TYPE commitType COMMIT_MSG STR COMMIT_ID STR {yy.commit($7,$9,$5,$3)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_MSG STR COMMIT_ID STR COMMIT_TYPE commitType {yy.commit($5,$7,$9,$3)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_MSG STR COMMIT_TYPE commitType COMMIT_ID STR {yy.commit($5,$9,$7,$3)}
|
||||
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_ID STR COMMIT_MSG STR COMMIT_TAG STR {yy.commit($7,$5,$3,$9)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_ID STR COMMIT_TAG STR COMMIT_MSG STR {yy.commit($9,$5,$3,$7)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_TAG STR COMMIT_MSG STR COMMIT_ID STR {yy.commit($7,$9,$3,$5)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_TAG STR COMMIT_ID STR COMMIT_MSG STR {yy.commit($9,$7,$3,$5)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_MSG STR COMMIT_ID STR COMMIT_TAG STR {yy.commit($5,$7,$3,$9)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_MSG STR COMMIT_TAG STR COMMIT_ID STR {yy.commit($5,$9,$3,$7)}
|
||||
|
||||
|
||||
// | COMMIT COMMIT_ID STR {yy.commit('',$3,yy.commitType.NORMAL,'')}
|
||||
// | COMMIT COMMIT_TYPE commitType {yy.commit('','',$3,'')}
|
||||
// | COMMIT COMMIT_TAG STR {yy.commit('','',yy.commitType.NORMAL,$3)}
|
||||
// | COMMIT COMMIT_MSG STR {yy.commit($3,'',yy.commitType.NORMAL,'')}
|
||||
// | COMMIT COMMIT_TAG STR COMMIT_TYPE commitType {yy.commit('','',$5,$3)}
|
||||
// | COMMIT COMMIT_TYPE commitType COMMIT_TAG STR {yy.commit('','',$3,$5)}
|
||||
// | COMMIT COMMIT_ID STR COMMIT_TYPE commitType {yy.commit('',$3,$5,'')}
|
||||
// | COMMIT COMMIT_ID STR COMMIT_TAG STR {yy.commit('',$3,yy.commitType.NORMAL,$5)}
|
||||
// | COMMIT COMMIT_ID STR COMMIT_TYPE commitType COMMIT_TAG STR {yy.commit('',$3,$5,$7)}
|
||||
// | COMMIT COMMIT_ID STR COMMIT_TAG STR COMMIT_TYPE commitType {yy.commit('',$3,$7,$5)}
|
||||
;
|
||||
commit_arg
|
||||
: /* empty */ {$$ = ""}
|
||||
| STR {$$=$1}
|
||||
;
|
||||
commitType
|
||||
: NORMAL { $$=yy.commitType.NORMAL;}
|
||||
| REVERSE { $$=yy.commitType.REVERSE;}
|
||||
| HIGHLIGHT { $$=yy.commitType.HIGHLIGHT;}
|
||||
;
|
||||
|
||||
reset_arg
|
||||
: 'HEAD' reset_parents{$$ = $1+ ":" + $2 }
|
||||
| ID reset_parents{$$ = $1+ ":" + yy.count; yy.count = 0}
|
||||
directive
|
||||
: openDirective typeDirective closeDirective
|
||||
| openDirective typeDirective ':' argDirective closeDirective
|
||||
;
|
||||
reset_parents
|
||||
: /* empty */ {yy.count = 0}
|
||||
| CARET reset_parents { yy.count += 1 }
|
||||
|
||||
openDirective
|
||||
: open_directive { yy.parseDirective('%%{', 'open_directive'); }
|
||||
;
|
||||
|
||||
typeDirective
|
||||
: type_directive { yy.parseDirective($1, 'type_directive'); }
|
||||
;
|
||||
|
||||
argDirective
|
||||
: arg_directive { $1 = $1.trim().replace(/'/g, '"'); yy.parseDirective($1, 'arg_directive'); }
|
||||
;
|
||||
|
||||
closeDirective
|
||||
: close_directive { yy.parseDirective('}%%', 'close_directive', 'gitGraph'); }
|
||||
;
|
||||
|
||||
eol
|
||||
: NL
|
||||
| ';'
|
||||
| EOF
|
||||
;
|
||||
// reset_arg
|
||||
// : 'HEAD' reset_parents{$$ = $1+ ":" + $2 }
|
||||
// | ID reset_parents{$$ = $1+ ":" + yy.count; yy.count = 0}
|
||||
// ;
|
||||
// reset_parents
|
||||
// : /* empty */ {yy.count = 0}
|
||||
// | CARET reset_parents { yy.count += 1 }
|
||||
// ;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const getStyles = () =>
|
||||
const getStyles = (options) =>
|
||||
`
|
||||
.commit-id,
|
||||
.commit-msg,
|
||||
@@ -8,6 +8,48 @@ const getStyles = () =>
|
||||
font-family: 'trebuchet ms', verdana, arial, sans-serif;
|
||||
font-family: var(--mermaid-font-family);
|
||||
}
|
||||
${[0, 1, 2, 3, 4, 5, 6, 7]
|
||||
.map(
|
||||
(i) =>
|
||||
`
|
||||
.branch-label${i} { fill: ${options['gitBranchLabel' + i]}; }
|
||||
.commit${i} { stroke: ${options['git' + i]}; fill: ${options['git' + i]}; }
|
||||
.commit-highlight${i} { stroke: ${options['gitInv' + i]}; fill: ${options['gitInv' + i]}; }
|
||||
.label${i} { fill: ${options['git' + i]}; }
|
||||
.arrow${i} { stroke: ${options['git' + i]}; }
|
||||
`
|
||||
)
|
||||
.join('\n')}
|
||||
|
||||
.branch {
|
||||
stroke-width: 1;
|
||||
stroke: ${options.lineColor};
|
||||
stroke-dasharray: 2;
|
||||
}
|
||||
.commit-label { font-size: 10px; fill: ${options.commitLabelColor};}
|
||||
.commit-label-bkg { font-size: 10px; fill: ${options.commitLabelBackground}; opacity: 0.5; }
|
||||
.tag-label { font-size: 10px; fill: ${options.tagLabelColor};}
|
||||
.tag-label-bkg { fill: ${options.tagLabelBackground}; stroke: ${options.tagLabelBorder}; }
|
||||
.tag-hole { fill: ${options.textColor}; }
|
||||
|
||||
.commit-merge {
|
||||
stroke: ${options.primaryColor};
|
||||
fill: ${options.primaryColor};
|
||||
}
|
||||
.commit-reverse {
|
||||
stroke: ${options.primaryColor};
|
||||
fill: ${options.primaryColor};
|
||||
stroke-width: 3;
|
||||
}
|
||||
.commit-highlight-outer {
|
||||
}
|
||||
.commit-highlight-inner {
|
||||
stroke: ${options.primaryColor};
|
||||
fill: ${options.primaryColor};
|
||||
}
|
||||
|
||||
.arrow { stroke-width: 8; stroke-linecap: round; fill: none}
|
||||
}
|
||||
`;
|
||||
|
||||
export default getStyles;
|
||||
|
||||
@@ -56,7 +56,9 @@
|
||||
"note" return 'note';
|
||||
"activate" { this.begin('ID'); return 'activate'; }
|
||||
"deactivate" { this.begin('ID'); return 'deactivate'; }
|
||||
"title" return 'title';
|
||||
"title"\s[^#\n;]+ return 'title';
|
||||
"title:"\s[^#\n;]+ return 'legacy_title';
|
||||
"accDescription"\s[^#\n;]+ return 'accDescription';
|
||||
"sequenceDiagram" return 'SD';
|
||||
"autonumber" return 'autonumber';
|
||||
"," return ',';
|
||||
@@ -121,7 +123,9 @@ statement
|
||||
| link_statement 'NEWLINE'
|
||||
| properties_statement 'NEWLINE'
|
||||
| details_statement 'NEWLINE'
|
||||
| title text2 'NEWLINE' {$$=[{type:'setTitle', text:$2}]}
|
||||
| title {yy.setTitle($1.substring(6));$$=$1.substring(6);}
|
||||
| legacy_title {yy.setTitle($1.substring(7));$$=$1.substring(7);}
|
||||
| accDescription {yy.setAccDescription($1.substring(15));$$=$1.substring(15);}
|
||||
| 'loop' restOfLine document end
|
||||
{
|
||||
$3.unshift({type: 'loopStart', loopText:yy.parseMessage($2), signalType: yy.LINETYPE.LOOP_START});
|
||||
|
||||
@@ -8,7 +8,7 @@ let actors = {};
|
||||
let messages = [];
|
||||
const notes = [];
|
||||
let title = '';
|
||||
let titleWrapped = false;
|
||||
let description = '';
|
||||
let sequenceNumbersEnabled = false;
|
||||
let wrapEnabled = false;
|
||||
|
||||
@@ -122,9 +122,6 @@ export const getActorKeys = function () {
|
||||
export const getTitle = function () {
|
||||
return title;
|
||||
};
|
||||
export const getTitleWrapped = function () {
|
||||
return titleWrapped;
|
||||
};
|
||||
export const enableSequenceNumbers = function () {
|
||||
sequenceNumbersEnabled = true;
|
||||
};
|
||||
@@ -139,6 +136,7 @@ export const autoWrap = () => wrapEnabled;
|
||||
export const clear = function () {
|
||||
actors = {};
|
||||
messages = [];
|
||||
sequenceNumbersEnabled = false;
|
||||
};
|
||||
|
||||
export const parseMessage = function (str) {
|
||||
@@ -323,9 +321,9 @@ export const getActorProperty = function (actor, key) {
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export const setTitle = function (titleWrap) {
|
||||
title = titleWrap.text;
|
||||
titleWrapped = (titleWrap.wrap === undefined && autoWrap()) || !!titleWrap.wrap;
|
||||
export const setTitle = function (txt) {
|
||||
let sanitizedText = sanitizeText(txt, configApi.getConfig());
|
||||
title = sanitizedText;
|
||||
};
|
||||
|
||||
export const apply = function (param) {
|
||||
@@ -408,6 +406,15 @@ export const apply = function (param) {
|
||||
}
|
||||
};
|
||||
|
||||
const setAccDescription = function (description_lex) {
|
||||
let sanitizedText = sanitizeText(description_lex, configApi.getConfig());
|
||||
description = sanitizedText;
|
||||
};
|
||||
|
||||
const getAccDescription = function () {
|
||||
return description;
|
||||
};
|
||||
|
||||
export default {
|
||||
addActor,
|
||||
addMessage,
|
||||
@@ -427,7 +434,6 @@ export default {
|
||||
getTitle,
|
||||
parseDirective,
|
||||
getConfig: () => configApi.getConfig().sequence,
|
||||
getTitleWrapped,
|
||||
clear,
|
||||
parseMessage,
|
||||
LINETYPE,
|
||||
@@ -436,4 +442,6 @@ export default {
|
||||
addNote,
|
||||
setTitle,
|
||||
apply,
|
||||
setAccDescription,
|
||||
getAccDescription,
|
||||
};
|
||||
|
||||
@@ -60,7 +60,7 @@ Bob-->Alice: I am good thanks!`;
|
||||
mermaidAPI.parse(str);
|
||||
expect(parser.yy.showSequenceNumbers()).toBe(true);
|
||||
});
|
||||
it('it should handle a sequenceDiagram definition with a title', function () {
|
||||
it('it should handle a sequenceDiagram definition with a title:', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
title: Diagram Title
|
||||
@@ -73,6 +73,7 @@ Bob-->Alice: I am good thanks!`;
|
||||
expect(actors.Alice.description).toBe('Alice');
|
||||
actors.Bob.description = 'Bob';
|
||||
|
||||
expect(parser.yy.getAccDescription()).toBe('');
|
||||
const messages = parser.yy.getMessages();
|
||||
const title = parser.yy.getTitle();
|
||||
|
||||
@@ -81,6 +82,52 @@ Bob-->Alice: I am good thanks!`;
|
||||
expect(messages[2].from).toBe('Bob');
|
||||
expect(title).toBe('Diagram Title');
|
||||
});
|
||||
|
||||
it('it should handle a sequenceDiagram definition with a title without a :', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
title Diagram Title
|
||||
Alice->Bob:Hello Bob, how are you?
|
||||
Note right of Bob: Bob thinks
|
||||
Bob-->Alice: I am good thanks!`;
|
||||
|
||||
mermaidAPI.parse(str);
|
||||
const actors = parser.yy.getActors();
|
||||
expect(actors.Alice.description).toBe('Alice');
|
||||
actors.Bob.description = 'Bob';
|
||||
|
||||
expect(parser.yy.getAccDescription()).toBe('');
|
||||
const messages = parser.yy.getMessages();
|
||||
const title = parser.yy.getTitle();
|
||||
|
||||
expect(messages.length).toBe(3);
|
||||
expect(messages[0].from).toBe('Alice');
|
||||
expect(messages[2].from).toBe('Bob');
|
||||
expect(title).toBe('Diagram Title');
|
||||
});
|
||||
|
||||
it('it should handle a sequenceDiagram definition with a accDescription', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
accDescription Accessibility Description
|
||||
Alice->Bob:Hello Bob, how are you?
|
||||
Note right of Bob: Bob thinks
|
||||
Bob-->Alice: I am good thanks!`;
|
||||
|
||||
mermaidAPI.parse(str);
|
||||
const actors = parser.yy.getActors();
|
||||
expect(actors.Alice.description).toBe('Alice');
|
||||
actors.Bob.description = 'Bob';
|
||||
|
||||
expect(parser.yy.getAccDescription()).toBe('Accessibility Description');
|
||||
const messages = parser.yy.getMessages();
|
||||
const title = parser.yy.getTitle();
|
||||
|
||||
expect(messages.length).toBe(3);
|
||||
expect(messages[0].from).toBe('Alice');
|
||||
expect(messages[2].from).toBe('Bob');
|
||||
});
|
||||
|
||||
it('it should space in actor names', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
@@ -1586,6 +1633,7 @@ participant Alice
|
||||
|
||||
renderer.bounds.init();
|
||||
mermaidAPI.parse(str);
|
||||
|
||||
renderer.draw(str, 'tst');
|
||||
|
||||
const { bounds, models } = renderer.bounds.getBounds();
|
||||
@@ -1619,4 +1667,24 @@ participant Alice
|
||||
models.lastActor().y + models.lastActor().height + mermaid.sequence.boxMargin
|
||||
);
|
||||
});
|
||||
it('it should hide sequence numbers when autonumber is removed when autonumber is enabled', function () {
|
||||
const str1 = `
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
Alice->Bob:Hello Bob, how are you?
|
||||
Note right of Bob: Bob thinks
|
||||
Bob-->Alice: I am good thanks!`;
|
||||
|
||||
mermaidAPI.parse(str1);
|
||||
expect(parser.yy.showSequenceNumbers()).toBe(true);
|
||||
|
||||
const str2 = `
|
||||
sequenceDiagram
|
||||
Alice->Bob:Hello Bob, how are you?
|
||||
Note right of Bob: Bob thinks
|
||||
Bob-->Alice: I am good thanks!`;
|
||||
|
||||
mermaidAPI.parse(str2);
|
||||
expect(parser.yy.showSequenceNumbers()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,6 +6,7 @@ import common from '../common/common';
|
||||
import sequenceDb from './sequenceDb';
|
||||
import * as configApi from '../../config';
|
||||
import utils, { assignWithDepth, configureSvgSize } from '../../utils';
|
||||
import addSVGAccessibilityFields from '../../accessibility';
|
||||
|
||||
parser.yy = sequenceDb;
|
||||
|
||||
@@ -727,6 +728,7 @@ export const draw = function (text, id) {
|
||||
log.error('error while drawing message', e);
|
||||
}
|
||||
}
|
||||
|
||||
// Increment sequence counter if msg.type is a line (and not another event like activation or note, etc)
|
||||
if (
|
||||
[
|
||||
@@ -802,6 +804,8 @@ export const draw = function (text, id) {
|
||||
' ' +
|
||||
(height + extraVertForTitle)
|
||||
);
|
||||
|
||||
addSVGAccessibilityFields(parser.yy, diagram, id);
|
||||
log.debug(`models:`, bounds.models);
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import moment from 'moment-mini';
|
||||
|
||||
/** @typedef {'debug' | 'info' | 'warn' | 'error' | 'fatal'} LogLevel A log level */
|
||||
|
||||
/** @type {object<LogLevel, number>} */
|
||||
/** @type {Object<LogLevel, number>} */
|
||||
export const LEVELS = {
|
||||
debug: 1,
|
||||
info: 2,
|
||||
|
||||
8
src/mermaidAPI.js
Executable file → Normal file
8
src/mermaidAPI.js
Executable file → Normal file
@@ -94,6 +94,7 @@ function parse(text) {
|
||||
parser.parser.yy = flowDb;
|
||||
break;
|
||||
case 'sequence':
|
||||
sequenceDb.clear();
|
||||
parser = sequenceParser;
|
||||
parser.parser.yy = sequenceDb;
|
||||
break;
|
||||
@@ -422,8 +423,8 @@ const render = function (id, _txt, cb, container) {
|
||||
try {
|
||||
switch (graphType) {
|
||||
case 'git':
|
||||
cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||
gitGraphRenderer.setConf(cnf.git);
|
||||
// cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||
//gitGraphRenderer.setConf(cnf.git);
|
||||
gitGraphRenderer.draw(txt, id, false);
|
||||
break;
|
||||
case 'flowchart':
|
||||
@@ -643,7 +644,8 @@ const handleDirective = function (p, directive, type) {
|
||||
/** @param {any} conf */
|
||||
function updateRendererConfigs(conf) {
|
||||
// Todo remove, all diagrams should get config on demoand from the config object, no need for this
|
||||
gitGraphRenderer.setConf(conf.git);
|
||||
|
||||
// gitGraphRenderer.setConf(conf.git); // Todo Remove all of these
|
||||
flowRenderer.setConf(conf.flowchart);
|
||||
flowRendererV2.setConf(conf.flowchart);
|
||||
if (typeof conf['sequenceDiagram'] !== 'undefined') {
|
||||
|
||||
@@ -113,6 +113,12 @@ describe('when using mermaidAPI and ', function () {
|
||||
expect(mermaidAPI.defaultConfig['logLevel']).toBe(5);
|
||||
});
|
||||
});
|
||||
describe('dompurify config', function () {
|
||||
it('should allow dompurify config to be set', function () {
|
||||
mermaidAPI.initialize({ dompurifyConfig: { ADD_ATTR: ['onclick'] } });
|
||||
expect(mermaidAPI.getConfig().dompurifyConfig.ADD_ATTR).toEqual(['onclick']);
|
||||
});
|
||||
});
|
||||
describe('checking validity of input ', function () {
|
||||
it('it should throw for an invalid definiton', function () {
|
||||
expect(() => mermaidAPI.parse('this is not a mermaid diagram definition')).toThrow();
|
||||
|
||||
@@ -42,7 +42,7 @@ class Theme {
|
||||
// The || is to make sure that if the variable has been defiend by a user override that value is to be used
|
||||
|
||||
/* Main */
|
||||
this.primaryTextColor = this.primaryTextColor || (this.darkMode ? '#ddd' : '#333'); // invert(this.primaryColor);
|
||||
this.primaryTextColor = this.primaryTextColor || (this.darkMode ? '#eee' : '#333'); // invert(this.primaryColor);
|
||||
this.secondaryColor = this.secondaryColor || adjust(this.primaryColor, { h: -120 });
|
||||
this.tertiaryColor = this.tertiaryColor || adjust(this.primaryColor, { h: 180, l: 5 });
|
||||
|
||||
@@ -177,6 +177,59 @@ class Theme {
|
||||
this.relationLabelBackground ||
|
||||
(this.darkMode ? darken(this.secondaryColor, 30) : this.secondaryColor);
|
||||
this.relationLabelColor = this.relationLabelColor || this.actorTextColor;
|
||||
|
||||
/* git */
|
||||
this.git0 = this.git0 || this.primaryColor;
|
||||
this.git1 = this.git1 || this.secondaryColor;
|
||||
this.git2 = this.git2 || this.tertiaryColor;
|
||||
this.git3 = this.git3 || adjust(this.primaryColor, { h: -30 });
|
||||
this.git4 = this.git4 || adjust(this.primaryColor, { h: -60 });
|
||||
this.git5 = this.git5 || adjust(this.primaryColor, { h: -90 });
|
||||
this.git6 = this.git6 || adjust(this.primaryColor, { h: +60 });
|
||||
this.git7 = this.git7 || adjust(this.primaryColor, { h: +120 });
|
||||
if (this.darkMode) {
|
||||
this.git0 = lighten(this.git0, 25);
|
||||
this.git1 = lighten(this.git1, 25);
|
||||
this.git2 = lighten(this.git2, 25);
|
||||
this.git3 = lighten(this.git3, 25);
|
||||
this.git4 = lighten(this.git4, 25);
|
||||
this.git5 = lighten(this.git5, 25);
|
||||
this.git6 = lighten(this.git6, 25);
|
||||
this.git7 = lighten(this.git7, 25);
|
||||
} else {
|
||||
this.git0 = darken(this.git0, 25);
|
||||
this.git1 = darken(this.git1, 25);
|
||||
this.git2 = darken(this.git2, 25);
|
||||
this.git3 = darken(this.git3, 25);
|
||||
this.git4 = darken(this.git4, 25);
|
||||
this.git5 = darken(this.git5, 25);
|
||||
this.git6 = darken(this.git6, 25);
|
||||
this.git7 = darken(this.git7, 25);
|
||||
}
|
||||
this.gitInv0 = invert(this.git0);
|
||||
this.gitInv1 = invert(this.git1);
|
||||
this.gitInv2 = invert(this.git2);
|
||||
this.gitInv3 = invert(this.git3);
|
||||
this.gitInv4 = invert(this.git4);
|
||||
this.gitInv5 = invert(this.git5);
|
||||
this.gitInv6 = invert(this.git6);
|
||||
this.gitInv7 = invert(this.git7);
|
||||
this.branchLabelColor =
|
||||
this.branchLabelColor || (this.darkMode ? 'black' : this.labelTextColor);
|
||||
this.gitBranchLabel0 = this.gitBranchLabel0 || this.branchLabelColor;
|
||||
this.gitBranchLabel1 = this.gitBranchLabel1 || this.branchLabelColor;
|
||||
this.gitBranchLabel2 = this.gitBranchLabel2 || this.branchLabelColor;
|
||||
this.gitBranchLabel3 = this.gitBranchLabel3 || this.branchLabelColor;
|
||||
this.gitBranchLabel4 = this.gitBranchLabel4 || this.branchLabelColor;
|
||||
this.gitBranchLabel5 = this.gitBranchLabel5 || this.branchLabelColor;
|
||||
this.gitBranchLabel6 = this.gitBranchLabel6 || this.branchLabelColor;
|
||||
this.gitBranchLabel7 = this.gitBranchLabel7 || this.branchLabelColor;
|
||||
|
||||
this.tagLabelColor = this.tagLabelColor || this.primaryTextColor;
|
||||
this.tagLabelBackground = this.tagLabelBackground || this.primaryColor;
|
||||
this.tagLabelBorder = this.tagBorder || this.primaryBorderColor;
|
||||
this.commitLabelColor = this.commitLabelColor || this.secondaryTextColor;
|
||||
this.commitLabelBackground = this.commitLabelBackground || this.secondaryColor;
|
||||
}
|
||||
calculate(overrides) {
|
||||
if (typeof overrides !== 'object') {
|
||||
|
||||
@@ -7,7 +7,7 @@ class Theme {
|
||||
this.secondaryColor = lighten(this.primaryColor, 16);
|
||||
|
||||
this.tertiaryColor = adjust(this.primaryColor, { h: -160 });
|
||||
this.primaryBorderColor = mkBorder(this.primaryColor, this.darkMode);
|
||||
this.primaryBorderColor = invert(this.background);
|
||||
this.secondaryBorderColor = mkBorder(this.secondaryColor, this.darkMode);
|
||||
this.tertiaryBorderColor = mkBorder(this.tertiaryColor, this.darkMode);
|
||||
this.primaryTextColor = invert(this.primaryColor);
|
||||
@@ -187,6 +187,30 @@ class Theme {
|
||||
this.relationLabelBackground ||
|
||||
(this.darkMode ? darken(this.secondaryColor, 30) : this.secondaryColor);
|
||||
this.relationLabelColor = this.relationLabelColor || this.actorTextColor;
|
||||
|
||||
/* git */
|
||||
this.git0 = lighten(this.secondaryColor, 20);
|
||||
this.git1 = lighten(this.pie2 || this.secondaryColor, 20);
|
||||
this.git2 = lighten(this.pie3 || this.tertiaryColor, 20);
|
||||
this.git3 = lighten(this.pie4 || adjust(this.primaryColor, { h: -30 }), 20);
|
||||
this.git4 = lighten(this.pie5 || adjust(this.primaryColor, { h: -60 }), 20);
|
||||
this.git5 = lighten(this.pie6 || adjust(this.primaryColor, { h: -90 }), 10);
|
||||
this.git6 = lighten(this.pie7 || adjust(this.primaryColor, { h: +60 }), 10);
|
||||
this.git7 = lighten(this.pie8 || adjust(this.primaryColor, { h: +120 }), 20);
|
||||
this.gitInv0 = invert(this.git0);
|
||||
this.gitInv1 = invert(this.git1);
|
||||
this.gitInv2 = invert(this.git2);
|
||||
this.gitInv3 = invert(this.git3);
|
||||
this.gitInv4 = invert(this.git4);
|
||||
this.gitInv5 = invert(this.git5);
|
||||
this.gitInv6 = invert(this.git6);
|
||||
this.gitInv7 = invert(this.git7);
|
||||
|
||||
this.tagLabelColor = this.tagLabelColor || this.primaryTextColor;
|
||||
this.tagLabelBackground = this.tagLabelBackground || this.primaryColor;
|
||||
this.tagLabelBorder = this.tagBorder || this.primaryBorderColor;
|
||||
this.commitLabelColor = this.commitLabelColor || this.secondaryTextColor;
|
||||
this.commitLabelBackground = this.commitLabelBackground || this.secondaryColor;
|
||||
}
|
||||
calculate(overrides) {
|
||||
if (typeof overrides !== 'object') {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { invert, lighten, rgba, adjust } from 'khroma';
|
||||
import { invert, lighten, rgba, adjust, darken } from 'khroma';
|
||||
import { mkBorder } from './theme-helpers';
|
||||
|
||||
class Theme {
|
||||
@@ -199,6 +199,57 @@ class Theme {
|
||||
this.relationColor = this.relationColor || this.lineColor;
|
||||
this.relationLabelBackground = this.relationLabelBackground || this.labelBackground;
|
||||
this.relationLabelColor = this.relationLabelColor || this.actorTextColor;
|
||||
|
||||
/* git */
|
||||
this.git0 = this.git0 || this.primaryColor;
|
||||
this.git1 = this.git1 || this.secondaryColor;
|
||||
this.git2 = this.git2 || this.tertiaryColor;
|
||||
this.git3 = this.git3 || adjust(this.primaryColor, { h: -30 });
|
||||
this.git4 = this.git4 || adjust(this.primaryColor, { h: -60 });
|
||||
this.git5 = this.git5 || adjust(this.primaryColor, { h: -90 });
|
||||
this.git6 = this.git6 || adjust(this.primaryColor, { h: +60 });
|
||||
this.git7 = this.git7 || adjust(this.primaryColor, { h: +120 });
|
||||
if (this.darkMode) {
|
||||
this.git0 = lighten(this.git0, 25);
|
||||
this.git1 = lighten(this.git1, 25);
|
||||
this.git2 = lighten(this.git2, 25);
|
||||
this.git3 = lighten(this.git3, 25);
|
||||
this.git4 = lighten(this.git4, 25);
|
||||
this.git5 = lighten(this.git5, 25);
|
||||
this.git6 = lighten(this.git6, 25);
|
||||
this.git7 = lighten(this.git7, 25);
|
||||
} else {
|
||||
this.git0 = darken(this.git0, 25);
|
||||
this.git1 = darken(this.git1, 25);
|
||||
this.git2 = darken(this.git2, 25);
|
||||
this.git3 = darken(this.git3, 25);
|
||||
this.git4 = darken(this.git4, 25);
|
||||
this.git5 = darken(this.git5, 25);
|
||||
this.git6 = darken(this.git6, 25);
|
||||
this.git7 = darken(this.git7, 25);
|
||||
}
|
||||
this.gitInv0 = darken(invert(this.git0), 25);
|
||||
this.gitInv1 = invert(this.git1);
|
||||
this.gitInv2 = invert(this.git2);
|
||||
this.gitInv3 = invert(this.git3);
|
||||
this.gitInv4 = invert(this.git4);
|
||||
this.gitInv5 = invert(this.git5);
|
||||
this.gitInv6 = invert(this.git6);
|
||||
this.gitInv7 = invert(this.git7);
|
||||
this.gitBranchLabel0 = invert(this.labelTextColor);
|
||||
this.gitBranchLabel1 = this.labelTextColor;
|
||||
this.gitBranchLabel2 = this.labelTextColor;
|
||||
this.gitBranchLabel3 = invert(this.labelTextColor);
|
||||
this.gitBranchLabel4 = this.labelTextColor;
|
||||
this.gitBranchLabel5 = this.labelTextColor;
|
||||
this.gitBranchLabel6 = this.labelTextColor;
|
||||
this.gitBranchLabel7 = this.labelTextColor;
|
||||
|
||||
this.tagLabelColor = this.tagLabelColor || this.primaryTextColor;
|
||||
this.tagLabelBackground = this.tagLabelBackground || this.primaryColor;
|
||||
this.tagLabelBorder = this.tagBorder || this.primaryBorderColor;
|
||||
this.commitLabelColor = this.commitLabelColor || this.secondaryTextColor;
|
||||
this.commitLabelBackground = this.commitLabelBackground || this.secondaryColor;
|
||||
}
|
||||
calculate(overrides) {
|
||||
if (typeof overrides !== 'object') {
|
||||
|
||||
@@ -169,6 +169,49 @@ class Theme {
|
||||
this.relationColor = this.relationColor || this.lineColor;
|
||||
this.relationLabelBackground = this.relationLabelBackground || this.edgeLabelBackground;
|
||||
this.relationLabelColor = this.relationLabelColor || this.actorTextColor;
|
||||
|
||||
/* git */
|
||||
this.git0 = this.git0 || this.primaryColor;
|
||||
this.git1 = this.git1 || this.secondaryColor;
|
||||
this.git2 = this.git2 || this.tertiaryColor;
|
||||
this.git3 = this.git3 || adjust(this.primaryColor, { h: -30 });
|
||||
this.git4 = this.git4 || adjust(this.primaryColor, { h: -60 });
|
||||
this.git5 = this.git5 || adjust(this.primaryColor, { h: -90 });
|
||||
this.git6 = this.git6 || adjust(this.primaryColor, { h: +60 });
|
||||
this.git7 = this.git7 || adjust(this.primaryColor, { h: +120 });
|
||||
if (this.darkMode) {
|
||||
this.git0 = lighten(this.git0, 25);
|
||||
this.git1 = lighten(this.git1, 25);
|
||||
this.git2 = lighten(this.git2, 25);
|
||||
this.git3 = lighten(this.git3, 25);
|
||||
this.git4 = lighten(this.git4, 25);
|
||||
this.git5 = lighten(this.git5, 25);
|
||||
this.git6 = lighten(this.git6, 25);
|
||||
this.git7 = lighten(this.git7, 25);
|
||||
} else {
|
||||
this.git0 = darken(this.git0, 25);
|
||||
this.git1 = darken(this.git1, 25);
|
||||
this.git2 = darken(this.git2, 25);
|
||||
this.git3 = darken(this.git3, 25);
|
||||
this.git4 = darken(this.git4, 25);
|
||||
this.git5 = darken(this.git5, 25);
|
||||
this.git6 = darken(this.git6, 25);
|
||||
this.git7 = darken(this.git7, 25);
|
||||
}
|
||||
this.gitInv0 = invert(this.git0);
|
||||
this.gitInv1 = invert(this.git1);
|
||||
this.gitInv2 = invert(this.git2);
|
||||
this.gitInv3 = invert(this.git3);
|
||||
this.gitInv4 = invert(this.git4);
|
||||
this.gitInv5 = invert(this.git5);
|
||||
this.gitInv6 = invert(this.git6);
|
||||
this.gitInv7 = invert(this.git7);
|
||||
|
||||
this.tagLabelColor = this.tagLabelColor || this.primaryTextColor;
|
||||
this.tagLabelBackground = this.tagLabelBackground || this.primaryColor;
|
||||
this.tagLabelBorder = this.tagBorder || this.primaryBorderColor;
|
||||
this.commitLabelColor = this.commitLabelColor || this.secondaryTextColor;
|
||||
this.commitLabelBackground = this.commitLabelBackground || this.secondaryColor;
|
||||
}
|
||||
calculate(overrides) {
|
||||
if (typeof overrides !== 'object') {
|
||||
|
||||
@@ -219,6 +219,41 @@ class Theme {
|
||||
this.relationColor = this.relationColor || this.lineColor;
|
||||
this.relationLabelBackground = this.relationLabelBackground || this.edgeLabelBackground;
|
||||
this.relationLabelColor = this.relationLabelColor || this.actorTextColor;
|
||||
|
||||
/* git */
|
||||
this.git0 = darken(this.pie1, 25) || this.primaryColor;
|
||||
this.git1 = this.pie2 || this.secondaryColor;
|
||||
this.git2 = this.pie3 || this.tertiaryColor;
|
||||
this.git3 = this.pie4 || adjust(this.primaryColor, { h: -30 });
|
||||
this.git4 = this.pie5 || adjust(this.primaryColor, { h: -60 });
|
||||
this.git5 = this.pie6 || adjust(this.primaryColor, { h: -90 });
|
||||
this.git6 = this.pie7 || adjust(this.primaryColor, { h: +60 });
|
||||
this.git7 = this.pie8 || adjust(this.primaryColor, { h: +120 });
|
||||
|
||||
this.gitInv0 = invert(this.git0);
|
||||
this.gitInv1 = invert(this.git1);
|
||||
this.gitInv2 = invert(this.git2);
|
||||
this.gitInv3 = invert(this.git3);
|
||||
this.gitInv4 = invert(this.git4);
|
||||
this.gitInv5 = invert(this.git5);
|
||||
this.gitInv6 = invert(this.git6);
|
||||
this.gitInv7 = invert(this.git7);
|
||||
|
||||
this.branchLabelColor = this.branchLabelColor || this.labelTextColor;
|
||||
this.gitBranchLabel0 = this.branchLabelColor;
|
||||
this.gitBranchLabel1 = 'white';
|
||||
this.gitBranchLabel2 = this.branchLabelColor;
|
||||
this.gitBranchLabel3 = 'white';
|
||||
this.gitBranchLabel4 = this.branchLabelColor;
|
||||
this.gitBranchLabel5 = this.branchLabelColor;
|
||||
this.gitBranchLabel6 = this.branchLabelColor;
|
||||
this.gitBranchLabel7 = this.branchLabelColor;
|
||||
|
||||
this.tagLabelColor = this.tagLabelColor || this.primaryTextColor;
|
||||
this.tagLabelBackground = this.tagLabelBackground || this.primaryColor;
|
||||
this.tagLabelBorder = this.tagBorder || this.primaryBorderColor;
|
||||
this.commitLabelColor = this.commitLabelColor || this.secondaryTextColor;
|
||||
this.commitLabelBackground = this.commitLabelBackground || this.secondaryColor;
|
||||
}
|
||||
calculate(overrides) {
|
||||
if (typeof overrides !== 'object') {
|
||||
|
||||
@@ -250,7 +250,7 @@ describe('when formatting urls', function () {
|
||||
|
||||
config.securityLevel = 'strict';
|
||||
result = utils.formatUrl(url, config);
|
||||
expect(result).toEqual('about:blank');
|
||||
expect(result).toEqual(url);
|
||||
});
|
||||
it('should handle mailto', function () {
|
||||
const url = 'mailto:user@user.user';
|
||||
|
||||
Reference in New Issue
Block a user