Compare commits

..

150 Commits
9.1.1 ... 9.1.2

Author SHA1 Message Date
ashishj
3b8d74f1f9 Updated release version to 9.1.2 2022-06-14 19:30:31 +02:00
Knut Sveidqvist
3fd9cabd43 Test file 2022-06-14 18:42:00 +02:00
ashishj
113efd1150 Added placeholder docs fro C4C diagram 2022-06-14 18:27:15 +02:00
Ashish Jain
f159808df6 Merge pull request #3122 from activus-d/typo-correction
typos in configuration.md corrected
2022-06-14 17:11:32 +02:00
Ashish Jain
e9148b4caf Merge pull request #3120 from flywire/patch-1
Styling links default
2022-06-14 17:11:08 +02:00
Ashish Jain
611880414b Merge pull request #3114 from siddhant-tripathy1/3093_Removing_sass_files
Removed the Sass files
2022-06-14 17:10:45 +02:00
dependabot[bot]
36321c7cb8 chore(deps-dev): bump webpack-cli from 4.9.2 to 4.10.0 (#3130)
Bumps [webpack-cli](https://github.com/webpack/webpack-cli) from 4.9.2 to 4.10.0.
- [Release notes](https://github.com/webpack/webpack-cli/releases)
- [Changelog](https://github.com/webpack/webpack-cli/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-cli/compare/webpack-cli@4.9.2...webpack-cli@4.10.0)

---
updated-dependencies:
- dependency-name: webpack-cli
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-13 21:05:39 +02:00
dependabot[bot]
6c0f8e2800 chore(deps-dev): bump lint-staged from 13.0.0 to 13.0.1 (#3132)
Bumps [lint-staged](https://github.com/okonet/lint-staged) from 13.0.0 to 13.0.1.
- [Release notes](https://github.com/okonet/lint-staged/releases)
- [Commits](https://github.com/okonet/lint-staged/compare/v13.0.0...v13.0.1)

---
updated-dependencies:
- dependency-name: lint-staged
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-13 20:57:15 +02:00
dependabot[bot]
71e75c0900 chore(deps-dev): bump @applitools/eyes-cypress from 3.26.1 to 3.26.2 (#3136)
Bumps [@applitools/eyes-cypress](https://github.com/applitools/eyes.sdk.javascript1/tree/HEAD/packages/eyes-cypress) from 3.26.1 to 3.26.2.
- [Release notes](https://github.com/applitools/eyes.sdk.javascript1/releases)
- [Changelog](https://github.com/applitools/eyes.sdk.javascript1/blob/master/packages/eyes-cypress/CHANGELOG.md)
- [Commits](https://github.com/applitools/eyes.sdk.javascript1/commits/@applitools/eyes-cypress@3.26.2/packages/eyes-cypress)

---
updated-dependencies:
- dependency-name: "@applitools/eyes-cypress"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-13 20:52:55 +02:00
dependabot[bot]
0400a597ef chore(deps-dev): bump webpack-dev-server from 4.9.1 to 4.9.2 (#3133)
Bumps [webpack-dev-server](https://github.com/webpack/webpack-dev-server) from 4.9.1 to 4.9.2.
- [Release notes](https://github.com/webpack/webpack-dev-server/releases)
- [Changelog](https://github.com/webpack/webpack-dev-server/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-dev-server/compare/v4.9.1...v4.9.2)

---
updated-dependencies:
- dependency-name: webpack-dev-server
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-13 20:33:48 +02:00
dependabot[bot]
0e923ec771 chore(deps-dev): bump babel-jest from 28.1.0 to 28.1.1 (#3137)
Bumps [babel-jest](https://github.com/facebook/jest/tree/HEAD/packages/babel-jest) from 28.1.0 to 28.1.1.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v28.1.1/packages/babel-jest)

---
updated-dependencies:
- dependency-name: babel-jest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-13 20:32:46 +02:00
dependabot[bot]
79ce18c9bc chore(deps-dev): bump jest-environment-jsdom from 28.1.0 to 28.1.1 (#3129)
Bumps [jest-environment-jsdom](https://github.com/facebook/jest/tree/HEAD/packages/jest-environment-jsdom) from 28.1.0 to 28.1.1.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v28.1.1/packages/jest-environment-jsdom)

---
updated-dependencies:
- dependency-name: jest-environment-jsdom
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-13 20:28:26 +02:00
dependabot[bot]
91f863ad9f chore(deps-dev): bump @babel/core from 7.18.2 to 7.18.5 (#3134)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.18.2 to 7.18.5.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.5/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-13 20:21:46 +02:00
dependabot[bot]
1415c8eda0 chore(deps-dev): bump jest from 28.1.0 to 28.1.1 (#3131)
Bumps [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest) from 28.1.0 to 28.1.1.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v28.1.1/packages/jest)

---
updated-dependencies:
- dependency-name: jest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-13 20:20:54 +02:00
mmorel-35
9eae97ddab chore: update browsers list 2022-06-13 07:03:33 +00:00
Damilola Mohammed
df28de62c1 typos in configuration.md corrected 2022-06-11 14:46:27 +01:00
flywire
72ada38417 Styling links default 2022-06-11 18:24:45 +10:00
Knut Sveidqvist
5d30d46535 Merge pull request #3118 from mermaid-js/3116_paddings
Handle diagram paddings in a consistent way
2022-06-08 20:24:18 +02:00
Knut Sveidqvist
4dd3d3bc76 2022-06-08 20:17:31 +02:00
Knut Sveidqvist
348fa3318b Merge pull request #3115 from mermaid-js/#3060-Support-cherry-commit-in-Gitgraph
#3060 support cherry commit in gitgraph
2022-06-07 21:08:50 +02:00
ashishj
84ae430806 #3080 Updated docs for cherry pick functionality 2022-06-07 21:00:26 +02:00
siddhant tripathy
61c1b0aebb Removed the Sass files 2022-06-08 00:27:23 +05:30
ashishj
e3df38e078 #3080 Added more rendering test for cherry pick functionality 2022-06-07 20:52:52 +02:00
ashishj
44b2fae0db #3080 Added docs for cherry pick functionality 2022-06-07 20:48:40 +02:00
ashishj
c147404d1c #3080 Added support for cherry pick commits 2022-06-07 20:32:43 +02:00
Knut Sveidqvist
7a4acb5c36 Merge pull request #3113 from mermaid-js/#3080-Commit-label-tilt
#3080 Adding rotated commit label functionality
2022-06-07 20:21:25 +02:00
ashishj
90d187c48a #3080 Added rendering test cases 2022-06-07 18:52:38 +02:00
ashishj
1851e81794 #3080 Adding rotated commit label functionality 2022-06-07 18:45:07 +02:00
Knut Sveidqvist
aeb6e860bb Merge pull request #3094 from deining/contrib
Fixing various typos
2022-06-07 17:17:49 +02:00
Knut Sveidqvist
3300ad09f3 Merge pull request #3038 from pinghe/develop
Add C4 Diagram. Compatible with C4-PlantUML syntax.
2022-06-07 17:12:10 +02:00
dependabot[bot]
c6e689255e chore(deps-dev): bump @applitools/eyes-cypress from 3.26.0 to 3.26.1 (#3105)
Bumps [@applitools/eyes-cypress](https://github.com/applitools/eyes.sdk.javascript1/tree/HEAD/packages/eyes-cypress) from 3.26.0 to 3.26.1.
- [Release notes](https://github.com/applitools/eyes.sdk.javascript1/releases)
- [Changelog](https://github.com/applitools/eyes.sdk.javascript1/blob/master/packages/eyes-cypress/CHANGELOG.md)
- [Commits](https://github.com/applitools/eyes.sdk.javascript1/commits/@applitools/eyes-cypress@3.26.1/packages/eyes-cypress)

---
updated-dependencies:
- dependency-name: "@applitools/eyes-cypress"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-06 22:19:49 +02:00
dependabot[bot]
8aff0d6321 chore(deps-dev): bump eslint from 8.16.0 to 8.17.0 (#3103)
Bumps [eslint](https://github.com/eslint/eslint) from 8.16.0 to 8.17.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.16.0...v8.17.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-06 22:15:00 +02:00
dependabot[bot]
a4ead2f259 chore(deps-dev): bump lint-staged from 12.4.2 to 13.0.0 (#3109)
Bumps [lint-staged](https://github.com/okonet/lint-staged) from 12.4.2 to 13.0.0.
- [Release notes](https://github.com/okonet/lint-staged/releases)
- [Commits](https://github.com/okonet/lint-staged/compare/v12.4.2...v13.0.0)

---
updated-dependencies:
- dependency-name: lint-staged
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-06 22:08:44 +02:00
dependabot[bot]
a569d5cbf6 chore(deps-dev): bump terser-webpack-plugin from 5.3.1 to 5.3.3 (#3106)
Bumps [terser-webpack-plugin](https://github.com/webpack-contrib/terser-webpack-plugin) from 5.3.1 to 5.3.3.
- [Release notes](https://github.com/webpack-contrib/terser-webpack-plugin/releases)
- [Changelog](https://github.com/webpack-contrib/terser-webpack-plugin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/terser-webpack-plugin/compare/v5.3.1...v5.3.3)

---
updated-dependencies:
- dependency-name: terser-webpack-plugin
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-06 22:06:28 +02:00
dependabot[bot]
fb50a3a249 chore(deps-dev): bump @commitlint/config-conventional (#3104)
Bumps [@commitlint/config-conventional](https://github.com/conventional-changelog/commitlint/tree/HEAD/@commitlint/config-conventional) from 17.0.0 to 17.0.2.
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/config-conventional/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v17.0.2/@commitlint/config-conventional)

---
updated-dependencies:
- dependency-name: "@commitlint/config-conventional"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-06 22:06:01 +02:00
dependabot[bot]
c8cd61f0f8 chore(deps-dev): bump @commitlint/cli from 17.0.1 to 17.0.2 (#3102)
Bumps [@commitlint/cli](https://github.com/conventional-changelog/commitlint/tree/HEAD/@commitlint/cli) from 17.0.1 to 17.0.2.
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/cli/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v17.0.2/@commitlint/cli)

---
updated-dependencies:
- dependency-name: "@commitlint/cli"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-06 22:05:41 +02:00
dependabot[bot]
d1e51abe2d chore(deps-dev): bump eslint-plugin-jest from 26.4.5 to 26.5.3 (#3110)
Bumps [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest) from 26.4.5 to 26.5.3.
- [Release notes](https://github.com/jest-community/eslint-plugin-jest/releases)
- [Changelog](https://github.com/jest-community/eslint-plugin-jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jest-community/eslint-plugin-jest/compare/v26.4.5...v26.5.3)

---
updated-dependencies:
- dependency-name: eslint-plugin-jest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-06 22:04:55 +02:00
dependabot[bot]
b8c0cd9564 chore(deps-dev): bump webpack-dev-server from 4.9.0 to 4.9.1 (#3107)
Bumps [webpack-dev-server](https://github.com/webpack/webpack-dev-server) from 4.9.0 to 4.9.1.
- [Release notes](https://github.com/webpack/webpack-dev-server/releases)
- [Changelog](https://github.com/webpack/webpack-dev-server/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-dev-server/compare/v4.9.0...v4.9.1)

---
updated-dependencies:
- dependency-name: webpack-dev-server
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-06 22:04:43 +02:00
dependabot[bot]
56f2073ad5 chore(deps-dev): bump webpack from 5.72.1 to 5.73.0 (#3108)
Bumps [webpack](https://github.com/webpack/webpack) from 5.72.1 to 5.73.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.72.1...v5.73.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-06 22:04:14 +02:00
mmorel-35
794d46beec chore: update browsers list 2022-06-06 07:03:41 +00:00
Andreas Deininger
8e157423e0 Fixing various typos
Changing links from http to https
2022-06-01 12:06:53 +02:00
Knut Sveidqvist
ef9740bb38 Merge pull request #3092 from mermaid-js/_3089_cluster_edge_self
Fix for case where a compound state has a transition to it self.
2022-05-31 20:41:45 +02:00
Knut Sveidqvist
bd459fadd3 2022-05-31 20:35:44 +02:00
Knut Sveidqvist
bb5baa65cb Merge branch 'develop' of github.com:mermaid-js/mermaid into develop 2022-05-31 17:11:29 +02:00
Knut Sveidqvist
ee61a26faf Merge pull request #3063 from financelurker/feature/3062_critical_region_and_break_in_sequence_diagrams
feat: adding "Critical Region"/"Option" and "Break" blocks to sequence diagram
2022-05-31 17:11:03 +02:00
dependabot[bot]
ef943d4b0b chore(deps-dev): bump cypress from 9.6.1 to 9.7.0 (#3082)
Bumps [cypress](https://github.com/cypress-io/cypress) from 9.6.1 to 9.7.0.
- [Release notes](https://github.com/cypress-io/cypress/releases)
- [Changelog](https://github.com/cypress-io/cypress/blob/develop/.releaserc.base.js)
- [Commits](https://github.com/cypress-io/cypress/compare/v9.6.1...v9.7.0)

---
updated-dependencies:
- dependency-name: cypress
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-30 09:30:08 +02:00
dependabot[bot]
4c25b95124 chore(deps-dev): bump @commitlint/cli from 17.0.0 to 17.0.1 (#3086)
Bumps [@commitlint/cli](https://github.com/conventional-changelog/commitlint/tree/HEAD/@commitlint/cli) from 17.0.0 to 17.0.1.
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/cli/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v17.0.1/@commitlint/cli)

---
updated-dependencies:
- dependency-name: "@commitlint/cli"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-30 09:29:42 +02:00
dependabot[bot]
3451a87d64 chore(deps-dev): bump eslint-plugin-jsdoc from 39.3.0 to 39.3.2 (#3088)
Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 39.3.0 to 39.3.2.
- [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases)
- [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v39.3.0...v39.3.2)

---
updated-dependencies:
- dependency-name: eslint-plugin-jsdoc
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-30 09:29:09 +02:00
dependabot[bot]
560b44daef chore(deps-dev): bump eslint-plugin-jest from 26.2.2 to 26.4.5 (#3085)
Bumps [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest) from 26.2.2 to 26.4.5.
- [Release notes](https://github.com/jest-community/eslint-plugin-jest/releases)
- [Changelog](https://github.com/jest-community/eslint-plugin-jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jest-community/eslint-plugin-jest/compare/v26.2.2...v26.4.5)

---
updated-dependencies:
- dependency-name: eslint-plugin-jest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-30 09:28:53 +02:00
dependabot[bot]
c7c211e031 chore(deps-dev): bump @babel/core from 7.18.0 to 7.18.2 (#3083)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.18.0 to 7.18.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.2/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-30 09:28:29 +02:00
dependabot[bot]
de3cbeeff3 chore(deps-dev): bump @babel/preset-env from 7.18.0 to 7.18.2 (#3084)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.18.0 to 7.18.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.2/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-30 09:27:46 +02:00
dependabot[bot]
689b204327 chore(deps-dev): bump @babel/eslint-parser from 7.17.0 to 7.18.2 (#3087)
Bumps [@babel/eslint-parser](https://github.com/babel/babel/tree/HEAD/eslint/babel-eslint-parser) from 7.17.0 to 7.18.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.2/eslint/babel-eslint-parser)

---
updated-dependencies:
- dependency-name: "@babel/eslint-parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-30 09:27:28 +02:00
dependabot[bot]
ea265bc28e chore(deps-dev): bump lint-staged from 12.4.1 to 12.4.2 (#3081)
Bumps [lint-staged](https://github.com/okonet/lint-staged) from 12.4.1 to 12.4.2.
- [Release notes](https://github.com/okonet/lint-staged/releases)
- [Commits](https://github.com/okonet/lint-staged/compare/v12.4.1...v12.4.2)

---
updated-dependencies:
- dependency-name: lint-staged
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-30 09:27:06 +02:00
mmorel-35
63f145f5c0 chore: update browsers list 2022-05-30 07:07:08 +00:00
Knut Sveidqvist
66f2f42294 Selecting the correct title for gantt charts 2022-05-24 20:10:04 +02:00
Ashish Jain
1148039c6b Merge pull request #3075 from mermaid-js/3074_access
Separation between title and accessibility title (sometimes)
2022-05-24 19:02:11 +02:00
Knut Sveidqvist
b82b2d2b78 #3074 Using regular title as a fallback for the accessibility title when no dedicated accessibility title is present 2022-05-24 18:52:37 +02:00
Knut Sveidqvist
6eef26f107 #3074 Fix for tests 2022-05-24 18:33:13 +02:00
Knut Sveidqvist
2ab1e162ea #3074 Cleanup and fixes for issues with accessibility for gantt and journey diagrams 2022-05-24 18:20:05 +02:00
Knut Sveidqvist
56f79692a3 Disabling md linting for mental sanity 2022-05-24 17:27:48 +02:00
Knut Sveidqvist
ef66cf77e1 Merge pull request #3070 from mermaid-js/dependabot/npm_and_yarn/develop/commitlint/cli-17.0.0
chore(deps-dev): bump @commitlint/cli from 16.3.0 to 17.0.0
2022-05-24 17:18:13 +02:00
Knut Sveidqvist
4b72539e33 Merge pull request #3069 from mermaid-js/dependabot/npm_and_yarn/develop/babel/core-7.18.0
chore(deps-dev): bump @babel/core from 7.17.10 to 7.18.0
2022-05-24 17:17:57 +02:00
Ashish Jain
da31880319 Merge pull request #3057 from mgenereu/remove-textlength
Removed unnecessary textLength attribute.
2022-05-24 17:09:17 +02:00
dependabot[bot]
96dfa1dbed chore(deps-dev): bump @babel/core from 7.17.10 to 7.18.0
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.17.10 to 7.18.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.0/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-24 15:08:54 +00:00
dependabot[bot]
dcedfdb674 chore(deps-dev): bump @commitlint/cli from 16.3.0 to 17.0.0
Bumps [@commitlint/cli](https://github.com/conventional-changelog/commitlint/tree/HEAD/@commitlint/cli) from 16.3.0 to 17.0.0.
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/cli/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v17.0.0/@commitlint/cli)

---
updated-dependencies:
- dependency-name: "@commitlint/cli"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-24 15:08:37 +00:00
Ashish Jain
bcb0cdfb3f Merge pull request #3059 from schmelto/patch-2
docs: remove edit on GitHub duplicate
2022-05-24 17:07:11 +02:00
Knut Sveidqvist
6beab4f286 Merge pull request #3072 from mermaid-js/dependabot/npm_and_yarn/develop/eslint-plugin-jsdoc-39.3.0
chore(deps-dev): bump eslint-plugin-jsdoc from 39.2.9 to 39.3.0
2022-05-24 17:04:53 +02:00
Knut Sveidqvist
2f150b0c82 Merge pull request #3071 from mermaid-js/dependabot/npm_and_yarn/develop/applitools/eyes-cypress-3.26.0
chore(deps-dev): bump @applitools/eyes-cypress from 3.25.7 to 3.26.0
2022-05-24 17:04:35 +02:00
Knut Sveidqvist
8c29007c69 Merge pull request #3068 from mermaid-js/dependabot/npm_and_yarn/develop/babel/preset-env-7.18.0
chore(deps-dev): bump @babel/preset-env from 7.17.10 to 7.18.0
2022-05-24 17:02:04 +02:00
Knut Sveidqvist
02aafcabba Merge pull request #3067 from mermaid-js/dependabot/npm_and_yarn/develop/commitlint/config-conventional-17.0.0
chore(deps-dev): bump @commitlint/config-conventional from 16.2.4 to 17.0.0
2022-05-24 17:01:53 +02:00
Knut Sveidqvist
81a7e6bc05 Merge pull request #3066 from mermaid-js/dependabot/npm_and_yarn/develop/eslint-8.16.0
chore(deps-dev): bump eslint from 8.15.0 to 8.16.0
2022-05-24 17:01:39 +02:00
Knut Sveidqvist
bf977311e1 Merge pull request #3065 from mermaid-js/dependabot/npm_and_yarn/develop/concurrently-7.2.1
chore(deps-dev): bump concurrently from 7.2.0 to 7.2.1
2022-05-24 17:01:24 +02:00
Knut Sveidqvist
79636af9f9 Merge pull request #3054 from sylhare/develop
[Documentation] Use actual theme name
2022-05-24 17:01:07 +02:00
Knut Sveidqvist
c956fb6570 Merge pull request #3064 from detj/fix/language-rename
docs: fix capitalisation of well known technologies
2022-05-24 17:00:20 +02:00
dependabot[bot]
48b2a15fd0 chore(deps-dev): bump eslint-plugin-jsdoc from 39.2.9 to 39.3.0
Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 39.2.9 to 39.3.0.
- [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases)
- [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v39.2.9...v39.3.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-jsdoc
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-23 07:05:13 +00:00
mmorel-35
ce5bb4fef7 chore: update browsers list 2022-05-23 07:05:04 +00:00
dependabot[bot]
06081c73e9 chore(deps-dev): bump @applitools/eyes-cypress from 3.25.7 to 3.26.0
Bumps [@applitools/eyes-cypress](https://github.com/applitools/eyes.sdk.javascript1/tree/HEAD/packages/eyes-cypress) from 3.25.7 to 3.26.0.
- [Release notes](https://github.com/applitools/eyes.sdk.javascript1/releases)
- [Changelog](https://github.com/applitools/eyes.sdk.javascript1/blob/master/packages/eyes-cypress/CHANGELOG.md)
- [Commits](https://github.com/applitools/eyes.sdk.javascript1/commits/@applitools/eyes-cypress@3.26.0/packages/eyes-cypress)

---
updated-dependencies:
- dependency-name: "@applitools/eyes-cypress"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-23 07:04:55 +00:00
dependabot[bot]
6c3c6a1e65 chore(deps-dev): bump @babel/preset-env from 7.17.10 to 7.18.0
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.17.10 to 7.18.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.0/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-23 07:03:45 +00:00
dependabot[bot]
e8f551964b chore(deps-dev): bump @commitlint/config-conventional
Bumps [@commitlint/config-conventional](https://github.com/conventional-changelog/commitlint/tree/HEAD/@commitlint/config-conventional) from 16.2.4 to 17.0.0.
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/config-conventional/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v17.0.0/@commitlint/config-conventional)

---
updated-dependencies:
- dependency-name: "@commitlint/config-conventional"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-23 07:03:17 +00:00
dependabot[bot]
95407eea80 chore(deps-dev): bump eslint from 8.15.0 to 8.16.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.15.0 to 8.16.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.15.0...v8.16.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-23 07:03:02 +00:00
dependabot[bot]
61e35edf27 chore(deps-dev): bump concurrently from 7.2.0 to 7.2.1
Bumps [concurrently](https://github.com/open-cli-tools/concurrently) from 7.2.0 to 7.2.1.
- [Release notes](https://github.com/open-cli-tools/concurrently/releases)
- [Commits](https://github.com/open-cli-tools/concurrently/compare/v7.2.0...v7.2.1)

---
updated-dependencies:
- dependency-name: concurrently
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-23 07:02:45 +00:00
Debjeet Biswas
fe32845197 docs: fix capitalisation of well known technologies 2022-05-22 10:42:51 +05:30
Ronald Heggenberger
077e6621b9 Undo whitespace changes 2022-05-21 09:40:21 +02:00
Ronald Heggenberger
7372ca5e8e Adding "Critical Region" and "Break" blocks 2022-05-21 09:31:06 +02:00
Tom Schmelzer
949f6dd4f9 docs: remove edit on GitHub duplicate 2022-05-20 08:30:04 +02:00
Michael Genereux
938b47bead Removed unnecessary textLength attribute.
This attribute makes two digit numbers look bad.
2022-05-19 23:17:11 +00:00
Sidharth Vinod
ef2fea157b Merge pull request #3052 from MindaugasLaganeckas/patch-2
Make initThrowsErrors available to clients
2022-05-19 18:03:58 +05:30
sylhare
eb20782aa4 Rename theme names 2022-05-18 15:14:13 -04:00
Mindaugas Laganeckas
ce3ba4f772 Make initThrowsErrors available to clients
Missing piece for https://github.com/mermaid-js/mermaid/pull/2379
2022-05-18 08:51:19 +02:00
Knut Sveidqvist
0fd11562bc Merge pull request #3051 from mermaid-js/3050_setTitle_rename
#3050 Renaming setTitle to setAccTitle
2022-05-17 20:29:06 +02:00
Knut Sveidqvist
a3878528c6 #3050 Renaming setTitle to setAccTitle 2022-05-17 20:23:45 +02:00
Knut Sveidqvist
3cb37ab802 Adding more hint for adding new diagrams 2022-05-17 19:56:50 +02:00
Knut Sveidqvist
7d52e99aba Merge pull request #3049 from mermaid-js/3046_IIIegible-style-in-Git-when-more-that-8-branches
# Add support for cyclic themeVariable rotation when more than 8 branches
2022-05-17 19:32:18 +02:00
ashishj
91d5c7ed71 #3046 Fixed liniting issue 2022-05-17 19:28:23 +02:00
ashishj
85062ac570 #3046 Add support for cyclic themeVariable rotation for more than 8 branches 2022-05-17 19:15:50 +02:00
Ashish Jain
6f6755ec02 Merge pull request #3030 from sylhare/patch-1
[Documentation] Re-order theme variables
2022-05-17 17:24:50 +02:00
Ashish Jain
6d2c6c13a7 Merge pull request #3035 from SlideeScherz/patch-1
Fixed whitespace typo in Class diagram
2022-05-17 17:23:15 +02:00
ashishj
bda13c41fd Merge branch 'develop' of github.com:mermaid-js/mermaid into develop 2022-05-17 17:06:54 +02:00
ashishj
ea58bb3359 Merge branch 'master' into develop 2022-05-17 17:06:38 +02:00
pinghe
390ec89045 Merge remote-tracking branch 'origin/develop' into develop 2022-05-17 22:41:10 +08:00
pinghe
4906460bf4 Merge branch 'mermaid-js:develop' into develop 2022-05-17 22:16:17 +08:00
pinghe
28ca1420f9 Add C4Context diagram. Compatible with C4-PlantUML syntax.
For an example, see the source code demos/index.html

 - System Context
 - Container diagram
 - Component diagram
 - Dynamic diagram
 - Deployment diagram
2022-05-17 19:57:03 +08:00
pinghe
9ba8e6e491 Merge remote-tracking branch 'upstream/develop' into c4 2022-05-17 19:45:43 +08:00
dependabot[bot]
24eb2123e4 chore(deps-dev): bump cypress from 9.6.0 to 9.6.1 (#3041)
Bumps [cypress](https://github.com/cypress-io/cypress) from 9.6.0 to 9.6.1.
- [Release notes](https://github.com/cypress-io/cypress/releases)
- [Changelog](https://github.com/cypress-io/cypress/blob/develop/.releaserc.base.js)
- [Commits](https://github.com/cypress-io/cypress/compare/v9.6.0...v9.6.1)

---
updated-dependencies:
- dependency-name: cypress
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-16 09:42:10 +02:00
dependabot[bot]
a67b86b73b chore(deps-dev): bump @commitlint/cli from 16.2.4 to 16.3.0 (#3040)
Bumps [@commitlint/cli](https://github.com/conventional-changelog/commitlint/tree/HEAD/@commitlint/cli) from 16.2.4 to 16.3.0.
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/cli/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v16.3.0/@commitlint/cli)

---
updated-dependencies:
- dependency-name: "@commitlint/cli"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-16 09:41:56 +02:00
dependabot[bot]
95a2ce244c chore(deps): bump dompurify from 2.3.6 to 2.3.8 (#3045)
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 2.3.6 to 2.3.8.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/2.3.6...2.3.8)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-16 09:39:45 +02:00
dependabot[bot]
35e2dd4047 chore(deps-dev): bump eslint-plugin-jest from 26.1.5 to 26.2.2 (#3044)
Bumps [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest) from 26.1.5 to 26.2.2.
- [Release notes](https://github.com/jest-community/eslint-plugin-jest/releases)
- [Changelog](https://github.com/jest-community/eslint-plugin-jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jest-community/eslint-plugin-jest/compare/v26.1.5...v26.2.2)

---
updated-dependencies:
- dependency-name: eslint-plugin-jest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-16 09:39:35 +02:00
dependabot[bot]
6ee632f245 chore(deps-dev): bump concurrently from 7.1.0 to 7.2.0 (#3039)
Bumps [concurrently](https://github.com/open-cli-tools/concurrently) from 7.1.0 to 7.2.0.
- [Release notes](https://github.com/open-cli-tools/concurrently/releases)
- [Commits](https://github.com/open-cli-tools/concurrently/compare/v7.1.0...v7.2.0)

---
updated-dependencies:
- dependency-name: concurrently
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-16 09:39:15 +02:00
dependabot[bot]
f9eb552382 chore(deps-dev): bump eslint from 8.4.1 to 8.15.0 (#3042)
Bumps [eslint](https://github.com/eslint/eslint) from 8.4.1 to 8.15.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.4.1...v8.15.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-16 09:38:25 +02:00
dependabot[bot]
deff411f85 chore(deps-dev): bump webpack from 5.72.0 to 5.72.1 (#3043)
Bumps [webpack](https://github.com/webpack/webpack) from 5.72.0 to 5.72.1.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.72.0...v5.72.1)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-16 09:23:50 +02:00
mmorel-35
e531997868 chore: update browsers list 2022-05-16 07:08:51 +00:00
pinghe
7d658403c2 Merge branch 'develop' of github.com:pinghe/mermaid into develop 2022-05-15 17:12:43 +08:00
pinghe
015c112103 Add C4Context diagram. Compatible with C4-PlantUML syntax.
```
    C4Context
      title System Context diagram for Internet Banking System

      Person(customerA, "Banking Customer A", "A customer of the bank, with personal bank accounts.")
      Person(customerB, "Banking Customer B")
      Person_Ext(customerC, "Banking Customer C")
      System(SystemAA, "Internet Banking System", "Allows customers to view information about their bank accounts, and make payments.")

      Person(customerD, "Banking Customer D", "A customer of the bank, <br/> with personal bank accounts.")

      Enterprise_Boundary(b1, "BankBoundary") {

        SystemDb_Ext(SystemE, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")

        System_Boundary(b2, "BankBoundary2") {
          System(SystemA, "Banking System A")
          System(SystemB, "Banking System B", "A system of the bank, with personal bank accounts.")
        }

        System_Ext(SystemC, "E-mail system", "The internal Microsoft Exchange e-mail system.")
        SystemDb(SystemD, "Banking System D Database", "A system of the bank, with personal bank accounts.")

        Boundary(b3, "BankBoundary3", "boundary") {
          SystemQueue(SystemF, "Banking System F Queue", "A system of the bank, with personal bank accounts.")
          SystemQueue_Ext(SystemG, "Banking System G Queue", "A system of the bank, with personal bank accounts.")
        }
      }

      BiRel(customerA, SystemAA, "Uses")
      BiRel(SystemAA, SystemE, "Uses")
      Rel(SystemAA, SystemC, "Sends e-mails", "SMTP")
      Rel(SystemC, customerA, "Sends e-mails to")
```
2022-05-15 17:08:09 +08:00
pinghe
a1ef3f0f4a Add C4Context diagram. Compatible with C4-PlantUML syntax.
```
    C4Context
      title System Context diagram for Internet Banking System

      Person(customerA, "Banking Customer A", "A customer of the bank, with personal bank accounts.")
      Person(customerB, "Banking Customer B")
      Person_Ext(customerC, "Banking Customer C")
      System(SystemAA, "Internet Banking System", "Allows customers to view information about their bank accounts, and make payments.")

      Person(customerD, "Banking Customer D", "A customer of the bank, <br/> with personal bank accounts.")

      Enterprise_Boundary(b1, "BankBoundary") {

        SystemDb_Ext(SystemE, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")

        System_Boundary(b2, "BankBoundary2") {
          System(SystemA, "Banking System A")
          System(SystemB, "Banking System B", "A system of the bank, with personal bank accounts.")
        }

        System_Ext(SystemC, "E-mail system", "The internal Microsoft Exchange e-mail system.")
        SystemDb(SystemD, "Banking System D Database", "A system of the bank, with personal bank accounts.")

        Boundary(b3, "BankBoundary3", "boundary") {
          SystemQueue(SystemF, "Banking System F Queue", "A system of the bank, with personal bank accounts.")
          SystemQueue_Ext(SystemG, "Banking System G Queue", "A system of the bank, with personal bank accounts.")
        }
      }

      BiRel(customerA, SystemAA, "Uses")
      BiRel(SystemAA, SystemE, "Uses")
      Rel(SystemAA, SystemC, "Sends e-mails", "SMTP")
      Rel(SystemC, customerA, "Sends e-mails to")
```
2022-05-15 13:24:47 +08:00
Scott Scherzer
0c65ea25cb Fixed whitespace typo in Class diagram
Easier copy and pasting
2022-05-13 15:59:35 -04:00
Sylhare
53c63b31c8 Re-order theme variables 2022-05-12 09:49:24 -04:00
Yash-Singh1
18114ab9ce fix: linting err in flowchart docs 2022-05-10 18:52:02 -07:00
Yash-Singh1
32a2e5fc47 fix: allow dot in entity name; fixes #1895 2022-05-10 18:39:11 -07:00
Yash-Singh1
af4c0591f9 chore: husky hooks executable 2022-05-10 18:27:55 -07:00
Yash-Singh1
d7b1cd912c chore: no lint for html in md 2022-05-10 18:11:23 -07:00
Matthieu MOREL
3a56bbed2e build: setup eslint-plugin-json (#2552)
Co-authored-by: Yash Singh <saiansh2525@gmail.com>
2022-05-10 17:52:55 -07:00
Yash-Singh1
b7b02fcc2c chore: rm cypress ex. and prevent dup ci 2022-05-10 17:29:50 -07:00
Yash-Singh1
9365138206 chore: split ci into seperate workflows 2022-05-10 17:26:17 -07:00
dependabot[bot]
61771b97ad chore(deps-dev): bump jest from 28.0.3 to 28.1.0 (#3018)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-10 17:19:44 -07:00
Yash-Singh1
bc4ecdc791 fix: config files at root 2022-05-10 17:09:42 -07:00
Yash-Singh1
bc58c8e03c chore: reduce excessive logs in unit tests 2022-05-10 17:09:42 -07:00
dependabot[bot]
8394bcd4a9 chore(deps-dev): bump jest-environment-jsdom from 28.0.2 to 28.1.0 (#3017)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-10 17:04:41 -07:00
Yash-Singh1
c6cde959b3 chore: rm dist again 2022-05-10 16:56:19 -07:00
Yash-Singh1
e74e51fb25 fix: ci fails by removing more debug files 2022-05-10 16:50:52 -07:00
ashishj
4a0321fe3e Merge branch 'master' into develop 2022-05-10 20:52:20 +02:00
Knut Sveidqvist
e306fcc795 merge 2022-05-10 20:37:39 +02:00
ashishj
20c4a68aa8 Merging release 9.1.0 to develop 2022-05-10 18:51:21 +02:00
Knut Sveidqvist
4fabf91e16 Merge pull request #3016 from mermaid-js/dependabot/npm_and_yarn/develop/husky-8.0.0
chore(deps-dev): bump husky from 7.0.4 to 8.0.0
2022-05-10 17:05:44 +02:00
Knut Sveidqvist
8ed7ea6b36 Merge pull request #3015 from mermaid-js/dependabot/npm_and_yarn/develop/eslint-8.15.0
chore(deps-dev): bump eslint from 8.14.0 to 8.15.0
2022-05-10 17:05:31 +02:00
Knut Sveidqvist
99f0eecb86 Merge pull request #3014 from mermaid-js/dependabot/npm_and_yarn/develop/webpack-dev-server-4.9.0
chore(deps-dev): bump webpack-dev-server from 4.8.1 to 4.9.0
2022-05-10 17:05:17 +02:00
Knut Sveidqvist
996e8ef9b8 Merge pull request #3013 from mermaid-js/dependabot/npm_and_yarn/develop/babel-jest-28.1.0
chore(deps-dev): bump babel-jest from 28.0.3 to 28.1.0
2022-05-10 17:01:19 +02:00
Knut Sveidqvist
734cef9017 Merge pull request #3004 from timmaffett/parse_parseError_fixes
fix mermaidAPI.parse() behavior to match documentation, add tests to ensure behavior matches docs
2022-05-10 17:00:22 +02:00
dependabot[bot]
0856d2e82c chore(deps-dev): bump babel-jest from 28.0.3 to 28.1.0
Bumps [babel-jest](https://github.com/facebook/jest/tree/HEAD/packages/babel-jest) from 28.0.3 to 28.1.0.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v28.1.0/packages/babel-jest)

---
updated-dependencies:
- dependency-name: babel-jest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-10 01:23:21 +00:00
dependabot[bot]
a8000bf51b chore(deps-dev): bump webpack-dev-server from 4.8.1 to 4.9.0
Bumps [webpack-dev-server](https://github.com/webpack/webpack-dev-server) from 4.8.1 to 4.9.0.
- [Release notes](https://github.com/webpack/webpack-dev-server/releases)
- [Changelog](https://github.com/webpack/webpack-dev-server/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-dev-server/compare/v4.8.1...v4.9.0)

---
updated-dependencies:
- dependency-name: webpack-dev-server
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-10 01:22:45 +00:00
dependabot[bot]
24f181afc8 chore(deps-dev): bump eslint from 8.14.0 to 8.15.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.14.0 to 8.15.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.14.0...v8.15.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-10 01:20:15 +00:00
Yash-Singh1
97cc8a4afe docs: add coffeescript highlighting 2022-05-09 18:17:04 -07:00
Yash-Singh1
4c1cf345fc chore: rm classDiagram debug file 2022-05-09 18:05:18 -07:00
mmorel-35
01cdd28938 chore: update browsers list 2022-05-09 07:03:52 +00:00
dependabot[bot]
7198b6884c chore(deps-dev): bump husky from 7.0.4 to 8.0.0
Bumps [husky](https://github.com/typicode/husky) from 7.0.4 to 8.0.0.
- [Release notes](https://github.com/typicode/husky/releases)
- [Commits](https://github.com/typicode/husky/compare/v7.0.4...v8.0.0)

---
updated-dependencies:
- dependency-name: husky
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-09 07:02:28 +00:00
Tim Maffett
c8e5525899 Merge branch 'develop' into parse_parseError_fixes 2022-05-06 09:24:49 -07:00
Tim Maffett
f7c28ff31e Merge branch 'mermaid-js:develop' into parse_parseError_fixes 2022-05-05 11:52:23 -07:00
Tim Maffett
ca8080a371 add more test for mermaidAPI.parse() to ensure it matches documented behavior 2022-05-05 11:50:11 -07:00
Tim Maffett
0df80d2b52 fix parseError documentation to match reality 2022-05-05 11:49:27 -07:00
Tim Maffett
67b6414693 fix parse() to match spec (return true if valid, false if invalid (and a parseError handler is defined)) 2022-05-05 11:48:53 -07:00
Tim Maffett
8210e3c80a add setParseErrorHandler,check for undefined mermaidAPI before using 2022-05-05 11:47:46 -07:00
156 changed files with 6408 additions and 168866 deletions

View File

@@ -1,2 +1,3 @@
dist/**
.github/**
docs/Setup.md

View File

@@ -13,17 +13,25 @@
},
"sourceType": "module"
},
"extends": ["eslint:recommended", "plugin:jsdoc/recommended", "plugin:markdown/recommended", "plugin:prettier/recommended"],
"plugins": ["html", "jest", "jsdoc", "prettier"],
"extends": [
"eslint:recommended",
//"plugin:jsdoc/recommended",
"plugin:json/recommended",
// "plugin:markdown/recommended",
"plugin:prettier/recommended"
],
"plugins": ["html", "jest", "jsdoc", "json", "prettier"],
"rules": {
"no-prototype-builtins": 0,
"no-unused-vars": 0,
"jsdoc/check-indentation": 0,
"jsdoc/check-alignment": 0,
"jsdoc/check-line-alignment": 0,
"jsdoc/multiline-blocks": 0,
"jsdoc/newline-after-description": 0,
"jsdoc/tag-lines": 0,
"no-prototype-builtins": "off",
"no-unused-vars": "off",
"jsdoc/check-indentation": "off",
"jsdoc/check-alignment": "off",
"jsdoc/check-line-alignment": "off",
"jsdoc/multiline-blocks": "off",
"jsdoc/newline-after-description": "off",
"jsdoc/tag-lines": "off",
"cypress/no-async-tests": "off",
"json/*": ["error", "allowComments"],
"no-empty": ["error", { "allowEmptyCatch": true }]
},
"overrides": [
@@ -33,6 +41,12 @@
"no-undef": "off",
"jsdoc/require-jsdoc": "off"
}
},
{
"files": "./**/*.md/*.html",
"rules": {
"prettier/prettier": "off"
}
}
]
}

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
* text=auto

View File

@@ -1,6 +1,12 @@
name: Build
on: [push, pull_request]
on:
push: {}
pull_request:
types:
- opened
- synchronize
- ready_for_review
permissions:
contents: read
@@ -37,7 +43,3 @@ jobs:
with:
name: dist
path: dist
- name: Run Unit Tests
run: |
yarn test --coverage

View File

@@ -1,4 +1,10 @@
on: [push]
on:
push: {}
pull_request:
types:
- opened
- synchronize
- ready_for_review
name: Static analysis

View File

@@ -7,6 +7,10 @@ on:
pull_request:
# The branches below must be a subset of the branches above
branches: [ develop ]
types:
- opened
- synchronize
- ready_for_review
jobs:
analyze:

39
.github/workflows/lint.yml vendored Normal file
View File

@@ -0,0 +1,39 @@
name: Lint
on:
push: {}
pull_request:
types:
- opened
- synchronize
- ready_for_review
permissions:
contents: read
jobs:
lint:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x]
steps:
- uses: actions/checkout@v3
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
cache: yarn
node-version: ${{ matrix.node-version }}
- name: Install Yarn
run: npm i yarn --global
- name: Install Packages
run: |
yarn install --frozen-lockfile
env:
CYPRESS_CACHE_FOLDER: .cache/Cypress
- name: Run Linting
run: yarn lint

View File

@@ -1,5 +1,11 @@
name: Validate PR Labeler Configuration
on: [push, pull_request]
on:
push: {}
pull_request:
types:
- opened
- synchronize
- ready_for_review
jobs:
pr-labeler:

34
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,34 @@
name: Unit Tests
on: [push, pull_request]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x]
steps:
- uses: actions/checkout@v3
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
cache: yarn
node-version: ${{ matrix.node-version }}
- name: Install Yarn
run: npm i yarn --global
- name: Install Packages
run: |
yarn install --frozen-lockfile
env:
CYPRESS_CACHE_FOLDER: .cache/Cypress
- name: Run Unit Tests
run: |
yarn ci --coverage

0
.husky/commit-msg Normal file → Executable file
View File

0
.husky/pre-commit Normal file → Executable file
View File

View File

@@ -1,5 +1,5 @@
{
"*.{js,html,md}": [
"*.{js,json,html,md}": [
"yarn lint:fix"
]
}

View File

@@ -3,12 +3,9 @@
"libs": [
"browser"
],
"loadEagerly": [
"path/to/your/js/**/*.js"
],
"loadEagerly": [],
"dontLoad": [
"node_modules/**",
"path/to/your/js/**/*.js"
"node_modules/**"
],
"plugins": {
"modules": {},

View File

@@ -23,7 +23,7 @@
- Missing fontawesome icon support [\#830](https://github.com/knsv/mermaid/issues/830)
- Docs for integration with wiki.js? [\#829](https://github.com/knsv/mermaid/issues/829)
- Is this project still maintained? [\#826](https://github.com/knsv/mermaid/issues/826)
- typroa [\#823](https://github.com/knsv/mermaid/issues/823)
- typora [\#823](https://github.com/knsv/mermaid/issues/823)
- Maintain the order of the nodes in Flowchart [\#815](https://github.com/knsv/mermaid/issues/815)
- Overlap, Overflow and cut titles in flowchart [\#814](https://github.com/knsv/mermaid/issues/814)
- How load mermaidApi notejs electron [\#813](https://github.com/knsv/mermaid/issues/813)

View 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 committed to https://mermaid-js.github.io/#/
The changes in master is reflected in https://mermaid-js.github.io/mermaid/ once released the updates are committed to https://mermaid-js.github.io/#/
## Last words

File diff suppressed because one or more lines are too long

View File

@@ -1,264 +0,0 @@
/// <reference types="Cypress" />
context('Actions', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/actions');
});
// https://on.cypress.io/interacting-with-elements
it('.type() - type into a DOM element', () => {
// https://on.cypress.io/type
cy.get('.action-email')
.type('fake@email.com')
.should('have.value', 'fake@email.com')
// .type() with special character sequences
.type('{leftarrow}{rightarrow}{uparrow}{downarrow}')
.type('{del}{selectall}{backspace}')
// .type() with key modifiers
.type('{alt}{option}') //these are equivalent
.type('{ctrl}{control}') //these are equivalent
.type('{meta}{command}{cmd}') //these are equivalent
.type('{shift}')
// Delay each keypress by 0.1 sec
.type('slow.typing@email.com', { delay: 100 })
.should('have.value', 'slow.typing@email.com');
cy.get('.action-disabled')
// Ignore error checking prior to type
// like whether the input is visible or disabled
.type('disabled error checking', { force: true })
.should('have.value', 'disabled error checking');
});
it('.focus() - focus on a DOM element', () => {
// https://on.cypress.io/focus
cy.get('.action-focus')
.focus()
.should('have.class', 'focus')
.prev()
.should('have.attr', 'style', 'color: orange;');
});
it('.blur() - blur off a DOM element', () => {
// https://on.cypress.io/blur
cy.get('.action-blur')
.type('About to blur')
.blur()
.should('have.class', 'error')
.prev()
.should('have.attr', 'style', 'color: red;');
});
it('.clear() - clears an input or textarea element', () => {
// https://on.cypress.io/clear
cy.get('.action-clear')
.type('Clear this text')
.should('have.value', 'Clear this text')
.clear()
.should('have.value', '');
});
it('.submit() - submit a form', () => {
// https://on.cypress.io/submit
cy.get('.action-form').find('[type="text"]').type('HALFOFF');
cy.get('.action-form').submit().next().should('contain', 'Your form has been submitted!');
});
it('.click() - click on a DOM element', () => {
// https://on.cypress.io/click
cy.get('.action-btn').click();
// You can click on 9 specific positions of an element:
// -----------------------------------
// | topLeft top topRight |
// | |
// | |
// | |
// | left center right |
// | |
// | |
// | |
// | bottomLeft bottom bottomRight |
// -----------------------------------
// clicking in the center of the element is the default
cy.get('#action-canvas').click();
cy.get('#action-canvas').click('topLeft');
cy.get('#action-canvas').click('top');
cy.get('#action-canvas').click('topRight');
cy.get('#action-canvas').click('left');
cy.get('#action-canvas').click('right');
cy.get('#action-canvas').click('bottomLeft');
cy.get('#action-canvas').click('bottom');
cy.get('#action-canvas').click('bottomRight');
// .click() accepts an x and y coordinate
// that controls where the click occurs :)
cy.get('#action-canvas')
.click(80, 75) // click 80px on x coord and 75px on y coord
.click(170, 75)
.click(80, 165)
.click(100, 185)
.click(125, 190)
.click(150, 185)
.click(170, 165);
// click multiple elements by passing multiple: true
cy.get('.action-labels>.label').click({ multiple: true });
// Ignore error checking prior to clicking
cy.get('.action-opacity>.btn').click({ force: true });
});
it('.dblclick() - double click on a DOM element', () => {
// https://on.cypress.io/dblclick
// Our app has a listener on 'dblclick' event in our 'scripts.js'
// that hides the div and shows an input on double click
cy.get('.action-div').dblclick().should('not.be.visible');
cy.get('.action-input-hidden').should('be.visible');
});
it('.check() - check a checkbox or radio element', () => {
// https://on.cypress.io/check
// By default, .check() will check all
// matching checkbox or radio elements in succession, one after another
cy.get('.action-checkboxes [type="checkbox"]').not('[disabled]').check().should('be.checked');
cy.get('.action-radios [type="radio"]').not('[disabled]').check().should('be.checked');
// .check() accepts a value argument
cy.get('.action-radios [type="radio"]').check('radio1').should('be.checked');
// .check() accepts an array of values
cy.get('.action-multiple-checkboxes [type="checkbox"]')
.check(['checkbox1', 'checkbox2'])
.should('be.checked');
// Ignore error checking prior to checking
cy.get('.action-checkboxes [disabled]').check({ force: true }).should('be.checked');
cy.get('.action-radios [type="radio"]').check('radio3', { force: true }).should('be.checked');
});
it('.uncheck() - uncheck a checkbox element', () => {
// https://on.cypress.io/uncheck
// By default, .uncheck() will uncheck all matching
// checkbox elements in succession, one after another
cy.get('.action-check [type="checkbox"]').not('[disabled]').uncheck().should('not.be.checked');
// .uncheck() accepts a value argument
cy.get('.action-check [type="checkbox"]')
.check('checkbox1')
.uncheck('checkbox1')
.should('not.be.checked');
// .uncheck() accepts an array of values
cy.get('.action-check [type="checkbox"]')
.check(['checkbox1', 'checkbox3'])
.uncheck(['checkbox1', 'checkbox3'])
.should('not.be.checked');
// Ignore error checking prior to unchecking
cy.get('.action-check [disabled]').uncheck({ force: true }).should('not.be.checked');
});
it('.select() - select an option in a <select> element', () => {
// https://on.cypress.io/select
// Select option(s) with matching text content
cy.get('.action-select').select('apples');
cy.get('.action-select-multiple').select(['apples', 'oranges', 'bananas']);
// Select option(s) with matching value
cy.get('.action-select').select('fr-bananas');
cy.get('.action-select-multiple').select(['fr-apples', 'fr-oranges', 'fr-bananas']);
});
it('.scrollIntoView() - scroll an element into view', () => {
// https://on.cypress.io/scrollintoview
// normally all of these buttons are hidden,
// because they're not within
// the viewable area of their parent
// (we need to scroll to see them)
cy.get('#scroll-horizontal button').should('not.be.visible');
// scroll the button into view, as if the user had scrolled
cy.get('#scroll-horizontal button').scrollIntoView().should('be.visible');
cy.get('#scroll-vertical button').should('not.be.visible');
// Cypress handles the scroll direction needed
cy.get('#scroll-vertical button').scrollIntoView().should('be.visible');
cy.get('#scroll-both button').should('not.be.visible');
// Cypress knows to scroll to the right and down
cy.get('#scroll-both button').scrollIntoView().should('be.visible');
});
it('.trigger() - trigger an event on a DOM element', () => {
// https://on.cypress.io/trigger
// To interact with a range input (slider)
// we need to set its value & trigger the
// event to signal it changed
// Here, we invoke jQuery's val() method to set
// the value and trigger the 'change' event
cy.get('.trigger-input-range')
.invoke('val', 25)
.trigger('change')
.get('input[type=range]')
.siblings('p')
.should('have.text', '25');
});
it('cy.scrollTo() - scroll the window or element to a position', () => {
// https://on.cypress.io/scrollTo
// You can scroll to 9 specific positions of an element:
// -----------------------------------
// | topLeft top topRight |
// | |
// | |
// | |
// | left center right |
// | |
// | |
// | |
// | bottomLeft bottom bottomRight |
// -----------------------------------
// if you chain .scrollTo() off of cy, we will
// scroll the entire window
cy.scrollTo('bottom');
cy.get('#scrollable-horizontal').scrollTo('right');
// or you can scroll to a specific coordinate:
// (x axis, y axis) in pixels
cy.get('#scrollable-vertical').scrollTo(250, 250);
// or you can scroll to a specific percentage
// of the (width, height) of the element
cy.get('#scrollable-both').scrollTo('75%', '25%');
// control the easing of the scroll (default is 'swing')
cy.get('#scrollable-vertical').scrollTo('center', { easing: 'linear' });
// control the duration of the scroll (in ms)
cy.get('#scrollable-both').scrollTo('center', { duration: 2000 });
});
});

View File

@@ -1,36 +0,0 @@
/// <reference types="Cypress" />
context('Aliasing', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/aliasing');
});
it('.as() - alias a DOM element for later use', () => {
// https://on.cypress.io/as
// Alias a DOM element for use later
// We don't have to traverse to the element
// later in our code, we reference it with @
cy.get('.as-table').find('tbody>tr').first().find('td').first().find('button').as('firstBtn');
// when we reference the alias, we place an
// @ in front of its name
cy.get('@firstBtn').click();
cy.get('@firstBtn').should('have.class', 'btn-success').and('contain', 'Changed');
});
it('.as() - alias a route for later use', () => {
// Alias the route to wait for its response
cy.server();
cy.route('GET', 'comments/*').as('getComment');
// we have code that gets a comment when
// the button is clicked in scripts.js
cy.get('.network-btn').click();
// https://on.cypress.io/wait
cy.wait('@getComment').its('status').should('eq', 200);
});
});

View File

@@ -1,169 +0,0 @@
/// <reference types="Cypress" />
context('Assertions', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/assertions');
});
describe('Implicit Assertions', () => {
it('.should() - make an assertion about the current subject', () => {
// https://on.cypress.io/should
cy.get('.assertion-table')
.find('tbody tr:last')
.should('have.class', 'success')
.find('td')
.first()
// checking the text of the <td> element in various ways
.should('have.text', 'Column content')
.should('contain', 'Column content')
.should('have.html', 'Column content')
// chai-jquery uses "is()" to check if element matches selector
.should('match', 'td')
// to match text content against a regular expression
// first need to invoke jQuery method text()
// and then match using regular expression
.invoke('text')
.should('match', /column content/i);
// a better way to check element's text content against a regular expression
// is to use "cy.contains"
// https://on.cypress.io/contains
cy.get('.assertion-table')
.find('tbody tr:last')
// finds first <td> element with text content matching regular expression
.contains('td', /column content/i)
.should('be.visible');
// for more information about asserting element's text
// see https://on.cypress.io/using-cypress-faq#How-do-I-get-an-elements-text-contents
});
it('.and() - chain multiple assertions together', () => {
// https://on.cypress.io/and
cy.get('.assertions-link')
.should('have.class', 'active')
.and('have.attr', 'href')
.and('include', 'cypress.io');
});
});
describe('Explicit Assertions', () => {
// https://on.cypress.io/assertions
it('expect - make an assertion about a specified subject', () => {
// We can use Chai's BDD style assertions
expect(true).to.be.true;
const o = { foo: 'bar' };
expect(o).to.equal(o);
expect(o).to.deep.equal({ foo: 'bar' });
// matching text using regular expression
expect('FooBar').to.match(/bar$/i);
});
it('pass your own callback function to should()', () => {
// Pass a function to should that can have any number
// of explicit assertions within it.
// The ".should(cb)" function will be retried
// automatically until it passes all your explicit assertions or times out.
cy.get('.assertions-p')
.find('p')
.should(($p) => {
// https://on.cypress.io/$
// return an array of texts from all of the p's
// @ts-ignore TS6133 unused variable
const texts = $p.map((i, el) => Cypress.$(el).text());
// jquery map returns jquery object
// and .get() convert this to simple array
const paragraphs = texts.get();
// array should have length of 3
expect(paragraphs, 'has 3 paragraphs').to.have.length(3);
// use second argument to expect(...) to provide clear
// message with each assertion
expect(paragraphs, 'has expected text in each paragraph').to.deep.eq([
'Some text from first p',
'More text from second p',
'And even more text from third p',
]);
});
});
it('finds element by class name regex', () => {
cy.get('.docs-header')
.find('div')
// .should(cb) callback function will be retried
.should(($div) => {
expect($div).to.have.length(1);
const className = $div[0].className;
expect(className).to.match(/heading-/);
})
// .then(cb) callback is not retried,
// it either passes or fails
.then(($div) => {
expect($div, 'text content').to.have.text('Introduction');
});
});
it('can throw any error', () => {
cy.get('.docs-header')
.find('div')
.should(($div) => {
if ($div.length !== 1) {
// you can throw your own errors
throw new Error('Did not find 1 element');
}
const className = $div[0].className;
if (!className.match(/heading-/)) {
throw new Error(`Could not find class "heading-" in ${className}`);
}
});
});
it('matches unknown text between two elements', () => {
/**
* Text from the first element.
*
* @type {string}
*/
let text;
/**
* Normalizes passed text, useful before comparing text with spaces and different capitalization.
*
* @param {string} s Text to normalize
*/
const normalizeText = (s) => s.replace(/\s/g, '').toLowerCase();
cy.get('.two-elements')
.find('.first')
.then(($first) => {
// save text from the first element
text = normalizeText($first.text());
});
cy.get('.two-elements')
.find('.second')
.should(($div) => {
// we can massage text before comparing
const secondText = normalizeText($div.text());
expect(secondText, 'second text').to.equal(text);
});
});
it('assert - assert shape of an object', () => {
const person = {
name: 'Joe',
age: 20,
};
assert.isObject(person, 'value is object');
});
});
});

View File

@@ -1,55 +0,0 @@
/// <reference types="Cypress" />
context('Connectors', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/connectors');
});
it('.each() - iterate over an array of elements', () => {
// https://on.cypress.io/each
cy.get('.connectors-each-ul>li').each(($el, index, $list) => {
console.log($el, index, $list);
});
});
it('.its() - get properties on the current subject', () => {
// https://on.cypress.io/its
cy.get('.connectors-its-ul>li')
// calls the 'length' property yielding that value
.its('length')
.should('be.gt', 2);
});
it('.invoke() - invoke a function on the current subject', () => {
// our div is hidden in our script.js
// $('.connectors-div').hide()
// https://on.cypress.io/invoke
cy.get('.connectors-div')
.should('be.hidden')
// call the jquery method 'show' on the 'div.container'
.invoke('show')
.should('be.visible');
});
it('.spread() - spread an array as individual args to callback function', () => {
// https://on.cypress.io/spread
const arr = ['foo', 'bar', 'baz'];
cy.wrap(arr).spread((foo, bar, baz) => {
expect(foo).to.eq('foo');
expect(bar).to.eq('bar');
expect(baz).to.eq('baz');
});
});
it('.then() - invoke a callback function with the current subject', () => {
// https://on.cypress.io/then
cy.get('.connectors-list > li').then(($lis) => {
expect($lis, '3 items').to.have.length(3);
expect($lis.eq(0), 'first item').to.contain('Walk the dog');
expect($lis.eq(1), 'second item').to.contain('Feed the cat');
expect($lis.eq(2), 'third item').to.contain('Write JavaScript');
});
});
});

View File

@@ -1,79 +0,0 @@
/// <reference types="Cypress" />
context('Cookies', () => {
beforeEach(() => {
Cypress.Cookies.debug(true);
cy.visit('https://example.cypress.io/commands/cookies');
// clear cookies again after visiting to remove
// any 3rd party cookies picked up such as cloudflare
cy.clearCookies();
});
it('cy.getCookie() - get a browser cookie', () => {
// https://on.cypress.io/getcookie
cy.get('#getCookie .set-a-cookie').click();
// cy.getCookie() yields a cookie object
cy.getCookie('token').should('have.property', 'value', '123ABC');
});
it('cy.getCookies() - get browser cookies', () => {
// https://on.cypress.io/getcookies
cy.getCookies().should('be.empty');
cy.get('#getCookies .set-a-cookie').click();
// cy.getCookies() yields an array of cookies
cy.getCookies()
.should('have.length', 1)
.should((cookies) => {
// each cookie has these properties
expect(cookies[0]).to.have.property('name', 'token');
expect(cookies[0]).to.have.property('value', '123ABC');
expect(cookies[0]).to.have.property('httpOnly', false);
expect(cookies[0]).to.have.property('secure', false);
expect(cookies[0]).to.have.property('domain');
expect(cookies[0]).to.have.property('path');
});
});
it('cy.setCookie() - set a browser cookie', () => {
// https://on.cypress.io/setcookie
cy.getCookies().should('be.empty');
cy.setCookie('foo', 'bar');
// cy.getCookie() yields a cookie object
cy.getCookie('foo').should('have.property', 'value', 'bar');
});
it('cy.clearCookie() - clear a browser cookie', () => {
// https://on.cypress.io/clearcookie
cy.getCookie('token').should('be.null');
cy.get('#clearCookie .set-a-cookie').click();
cy.getCookie('token').should('have.property', 'value', '123ABC');
// cy.clearCookies() yields null
cy.clearCookie('token').should('be.null');
cy.getCookie('token').should('be.null');
});
it('cy.clearCookies() - clear browser cookies', () => {
// https://on.cypress.io/clearcookies
cy.getCookies().should('be.empty');
cy.get('#clearCookies .set-a-cookie').click();
cy.getCookies().should('have.length', 1);
// cy.clearCookies() yields null
cy.clearCookies();
cy.getCookies().should('be.empty');
});
});

View File

@@ -1,225 +0,0 @@
/// <reference types="Cypress" />
context('Cypress.Commands', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/cypress-api');
});
// https://on.cypress.io/custom-commands
it('.add() - create a custom command', () => {
Cypress.Commands.add(
'console',
{
prevSubject: true,
},
(subject, method) => {
// the previous subject is automatically received
// and the commands arguments are shifted
// allow us to change the console method used
method = method || 'log';
// log the subject to the console
// @ts-ignore TS7017
console[method]('The subject is', subject);
// whatever we return becomes the new subject
// we don't want to change the subject so
// we return whatever was passed in
return subject;
}
);
// @ts-ignore TS2339
cy.get('button')
.console('info')
.then(($button) => {
// subject is still $button
});
});
});
context('Cypress.Cookies', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/cypress-api');
});
// https://on.cypress.io/cookies
it('.debug() - enable or disable debugging', () => {
Cypress.Cookies.debug(true);
// Cypress will now log in the console when
// cookies are set or cleared
cy.setCookie('fakeCookie', '123ABC');
cy.clearCookie('fakeCookie');
cy.setCookie('fakeCookie', '123ABC');
cy.clearCookie('fakeCookie');
cy.setCookie('fakeCookie', '123ABC');
});
it('.preserveOnce() - preserve cookies by key', () => {
// normally cookies are reset after each test
cy.getCookie('fakeCookie').should('not.be.ok');
// preserving a cookie will not clear it when
// the next test starts
cy.setCookie('lastCookie', '789XYZ');
Cypress.Cookies.preserveOnce('lastCookie');
});
it('.defaults() - set defaults for all cookies', () => {
// now any cookie with the name 'session_id' will
// not be cleared before each new test runs
Cypress.Cookies.defaults({
whitelist: 'session_id',
});
});
});
context('Cypress.Server', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/cypress-api');
});
// Permanently override server options for
// all instances of cy.server()
// https://on.cypress.io/cypress-server
it('.defaults() - change default config of server', () => {
Cypress.Server.defaults({
delay: 0,
force404: false,
});
});
});
context('Cypress.arch', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/cypress-api');
});
it('Get CPU architecture name of underlying OS', () => {
// https://on.cypress.io/arch
expect(Cypress.arch).to.exist;
});
});
context('Cypress.config()', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/cypress-api');
});
it('Get and set configuration options', () => {
// https://on.cypress.io/config
let myConfig = Cypress.config();
expect(myConfig).to.have.property('animationDistanceThreshold', 5);
expect(myConfig).to.have.property('baseUrl', null);
expect(myConfig).to.have.property('defaultCommandTimeout', 4000);
expect(myConfig).to.have.property('requestTimeout', 5000);
expect(myConfig).to.have.property('responseTimeout', 30000);
expect(myConfig).to.have.property('viewportHeight', 660);
expect(myConfig).to.have.property('viewportWidth', 1000);
expect(myConfig).to.have.property('pageLoadTimeout', 60000);
expect(myConfig).to.have.property('waitForAnimations', true);
expect(Cypress.config('pageLoadTimeout')).to.eq(60000);
// this will change the config for the rest of your tests!
Cypress.config('pageLoadTimeout', 20000);
expect(Cypress.config('pageLoadTimeout')).to.eq(20000);
Cypress.config('pageLoadTimeout', 60000);
});
});
context('Cypress.dom', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/cypress-api');
});
// https://on.cypress.io/dom
it('.isHidden() - determine if a DOM element is hidden', () => {
let hiddenP = Cypress.$('.dom-p p.hidden').get(0);
let visibleP = Cypress.$('.dom-p p.visible').get(0);
// our first paragraph has css class 'hidden'
expect(Cypress.dom.isHidden(hiddenP)).to.be.true;
expect(Cypress.dom.isHidden(visibleP)).to.be.false;
});
});
context('Cypress.env()', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/cypress-api');
});
// We can set environment variables for highly dynamic values
// https://on.cypress.io/environment-variables
it('Get environment variables', () => {
// https://on.cypress.io/env
// set multiple environment variables
Cypress.env({
host: 'veronica.dev.local',
api_server: 'http://localhost:8888/v1/',
});
// get environment variable
expect(Cypress.env('host')).to.eq('veronica.dev.local');
// set environment variable
Cypress.env('api_server', 'http://localhost:8888/v2/');
expect(Cypress.env('api_server')).to.eq('http://localhost:8888/v2/');
// get all environment variable
expect(Cypress.env()).to.have.property('host', 'veronica.dev.local');
expect(Cypress.env()).to.have.property('api_server', 'http://localhost:8888/v2/');
});
});
context('Cypress.log', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/cypress-api');
});
it('Control what is printed to the Command Log', () => {
// https://on.cypress.io/cypress-log
});
});
context('Cypress.platform', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/cypress-api');
});
it('Get underlying OS name', () => {
// https://on.cypress.io/platform
expect(Cypress.platform).to.be.exist;
});
});
context('Cypress.version', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/cypress-api');
});
it('Get current version of Cypress being run', () => {
// https://on.cypress.io/version
expect(Cypress.version).to.be.exist;
});
});
context('Cypress.spec', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/cypress-api');
});
it('Get current spec information', () => {
// https://on.cypress.io/spec
// wrap the object so we can inspect it easily by clicking in the command log
cy.wrap(Cypress.spec).should('have.keys', ['name', 'relative', 'absolute']);
});
});

View File

@@ -1,114 +0,0 @@
/// <reference types="Cypress" />
/// JSON fixture file can be loaded directly using
// the built-in JavaScript bundler
// @ts-ignore
const requiredExample = require('../../fixtures/example');
context('Files', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/files');
});
beforeEach(() => {
// load example.json fixture file and store
// in the test context object
cy.fixture('example.json').as('example');
});
it('cy.fixture() - load a fixture', () => {
// https://on.cypress.io/fixture
// Instead of writing a response inline you can
// use a fixture file's content.
cy.server();
cy.fixture('example.json').as('comment');
// when application makes an Ajax request matching "GET comments/*"
// Cypress will intercept it and reply with object
// from the "comment" alias
cy.route('GET', 'comments/*', '@comment').as('getComment');
// we have code that gets a comment when
// the button is clicked in scripts.js
cy.get('.fixture-btn').click();
cy.wait('@getComment')
.its('responseBody')
.should('have.property', 'name')
.and('include', 'Using fixtures to represent data');
// you can also just write the fixture in the route
cy.route('GET', 'comments/*', 'fixture:example.json').as('getComment');
// we have code that gets a comment when
// the button is clicked in scripts.js
cy.get('.fixture-btn').click();
cy.wait('@getComment')
.its('responseBody')
.should('have.property', 'name')
.and('include', 'Using fixtures to represent data');
// or write fx to represent fixture
// by default it assumes it's .json
cy.route('GET', 'comments/*', 'fx:example').as('getComment');
// we have code that gets a comment when
// the button is clicked in scripts.js
cy.get('.fixture-btn').click();
cy.wait('@getComment')
.its('responseBody')
.should('have.property', 'name')
.and('include', 'Using fixtures to represent data');
});
it('cy.fixture() or require - load a fixture', function () {
// we are inside the "function () { ... }"
// callback and can use test context object "this"
// "this.example" was loaded in "beforeEach" function callback
expect(this.example, 'fixture in the test context').to.deep.equal(requiredExample);
// or use "cy.wrap" and "should('deep.equal', ...)" assertion
// @ts-ignore
cy.wrap(this.example, 'fixture vs require').should('deep.equal', requiredExample);
});
it('cy.readFile() - read a files contents', () => {
// https://on.cypress.io/readfile
// You can read a file and yield its contents
// The filePath is relative to your project's root.
cy.readFile('cypress.json').then((json) => {
expect(json).to.be.an('object');
});
});
it('cy.writeFile() - write to a file', () => {
// https://on.cypress.io/writefile
// You can write to a file
// Use a response from a request to automatically
// generate a fixture file for use later
cy.request('https://jsonplaceholder.cypress.io/users').then((response) => {
cy.writeFile('cypress/fixtures/users.json', response.body);
});
cy.fixture('users').should((users) => {
expect(users[0].name).to.exist;
});
// JavaScript arrays and objects are stringified
// and formatted into text.
cy.writeFile('cypress/fixtures/profile.json', {
id: 8739,
name: 'Jane',
email: 'jane@example.com',
});
cy.fixture('profile').should((profile) => {
expect(profile.name).to.eq('Jane');
});
});
});

View File

@@ -1,58 +0,0 @@
/// <reference types="Cypress" />
context('Local Storage', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/local-storage');
});
// Although local storage is automatically cleared
// in between tests to maintain a clean state
// sometimes we need to clear the local storage manually
it('cy.clearLocalStorage() - clear all data in local storage', () => {
// https://on.cypress.io/clearlocalstorage
cy.get('.ls-btn')
.click()
.should(() => {
expect(localStorage.getItem('prop1')).to.eq('red');
expect(localStorage.getItem('prop2')).to.eq('blue');
expect(localStorage.getItem('prop3')).to.eq('magenta');
});
// clearLocalStorage() yields the localStorage object
cy.clearLocalStorage().should((ls) => {
expect(ls.getItem('prop1')).to.be.null;
expect(ls.getItem('prop2')).to.be.null;
expect(ls.getItem('prop3')).to.be.null;
});
// Clear key matching string in Local Storage
cy.get('.ls-btn')
.click()
.should(() => {
expect(localStorage.getItem('prop1')).to.eq('red');
expect(localStorage.getItem('prop2')).to.eq('blue');
expect(localStorage.getItem('prop3')).to.eq('magenta');
});
cy.clearLocalStorage('prop1').should((ls) => {
expect(ls.getItem('prop1')).to.be.null;
expect(ls.getItem('prop2')).to.eq('blue');
expect(ls.getItem('prop3')).to.eq('magenta');
});
// Clear keys matching regex in Local Storage
cy.get('.ls-btn')
.click()
.should(() => {
expect(localStorage.getItem('prop1')).to.eq('red');
expect(localStorage.getItem('prop2')).to.eq('blue');
expect(localStorage.getItem('prop3')).to.eq('magenta');
});
cy.clearLocalStorage(/prop1|2/).should((ls) => {
expect(ls.getItem('prop1')).to.be.null;
expect(ls.getItem('prop2')).to.be.null;
expect(ls.getItem('prop3')).to.eq('magenta');
});
});
});

View File

@@ -1,32 +0,0 @@
/// <reference types="Cypress" />
context('Location', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/location');
});
it('cy.hash() - get the current URL hash', () => {
// https://on.cypress.io/hash
cy.hash().should('be.empty');
});
it('cy.location() - get window.location', () => {
// https://on.cypress.io/location
cy.location().should((location) => {
expect(location.hash).to.be.empty;
expect(location.href).to.eq('https://example.cypress.io/commands/location');
expect(location.host).to.eq('example.cypress.io');
expect(location.hostname).to.eq('example.cypress.io');
expect(location.origin).to.eq('https://example.cypress.io');
expect(location.pathname).to.eq('/commands/location');
expect(location.port).to.eq('');
expect(location.protocol).to.eq('https:');
expect(location.search).to.be.empty;
});
});
it('cy.url() - get the current URL', () => {
// https://on.cypress.io/url
cy.url().should('eq', 'https://example.cypress.io/commands/location');
});
});

View File

@@ -1,77 +0,0 @@
/// <reference types="Cypress" />
context('Misc', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/misc');
});
it('.end() - end the command chain', () => {
// https://on.cypress.io/end
// cy.end is useful when you want to end a chain of commands
// and force Cypress to re-query from the root element
cy.get('.misc-table').within(() => {
// ends the current chain and yields null
cy.contains('Cheryl').click().end();
// queries the entire table again
cy.contains('Charles').click();
});
});
it('cy.exec() - execute a system command', () => {
// https://on.cypress.io/exec
// execute a system command.
// so you can take actions necessary for
// your test outside the scope of Cypress.
cy.exec('echo Jane Lane').its('stdout').should('contain', 'Jane Lane');
// we can use Cypress.platform string to
// select appropriate command
// https://on.cypress/io/platform
cy.log(`Platform ${Cypress.platform} architecture ${Cypress.arch}`);
if (Cypress.platform === 'win32') {
cy.exec('print cypress.json').its('stderr').should('be.empty');
} else {
cy.exec('cat cypress.json').its('stderr').should('be.empty');
cy.exec('pwd').its('code').should('eq', 0);
}
});
it('cy.focused() - get the DOM element that has focus', () => {
// https://on.cypress.io/focused
cy.get('.misc-form').find('#name').click();
cy.focused().should('have.id', 'name');
cy.get('.misc-form').find('#description').click();
cy.focused().should('have.id', 'description');
});
context('Cypress.Screenshot', function () {
it('cy.screenshot() - take a screenshot', () => {
// https://on.cypress.io/screenshot
cy.screenshot('my-image');
});
it('Cypress.Screenshot.defaults() - change default config of screenshots', function () {
Cypress.Screenshot.defaults({
blackout: ['.foo'],
capture: 'viewport',
clip: { x: 0, y: 0, width: 200, height: 200 },
scale: false,
disableTimersAndAnimations: true,
screenshotOnRunFailure: true,
beforeScreenshot() {},
afterScreenshot() {},
});
});
});
it('cy.wrap() - wrap an object', () => {
// https://on.cypress.io/wrap
cy.wrap({ foo: 'bar' }).should('have.property', 'foo').and('include', 'bar');
});
});

View File

@@ -1,56 +0,0 @@
/// <reference types="Cypress" />
context('Navigation', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io');
cy.get('.navbar-nav').contains('Commands').click();
cy.get('.dropdown-menu').contains('Navigation').click();
});
it("cy.go() - go back or forward in the browser's history", () => {
// https://on.cypress.io/go
cy.location('pathname').should('include', 'navigation');
cy.go('back');
cy.location('pathname').should('not.include', 'navigation');
cy.go('forward');
cy.location('pathname').should('include', 'navigation');
// clicking back
cy.go(-1);
cy.location('pathname').should('not.include', 'navigation');
// clicking forward
cy.go(1);
cy.location('pathname').should('include', 'navigation');
});
it('cy.reload() - reload the page', () => {
// https://on.cypress.io/reload
cy.reload();
// reload the page without using the cache
cy.reload(true);
});
it('cy.visit() - visit a remote url', () => {
// https://on.cypress.io/visit
// Visit any sub-domain of your current domain
// Pass options to the visit
cy.visit('https://example.cypress.io/commands/navigation', {
timeout: 50000, // increase total time for the visit to resolve
onBeforeLoad(contentWindow) {
// contentWindow is the remote page's window object
expect(typeof contentWindow === 'object').to.be.true;
},
onLoad(contentWindow) {
// contentWindow is the remote page's window object
expect(typeof contentWindow === 'object').to.be.true;
},
});
});
});

View File

@@ -1,192 +0,0 @@
/// <reference types="Cypress" />
context('Network Requests', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/network-requests');
});
// Manage AJAX / XHR requests in your app
it('cy.server() - control behavior of network requests and responses', () => {
// https://on.cypress.io/server
cy.server().should((server) => {
// the default options on server
// you can override any of these options
expect(server.delay).to.eq(0);
expect(server.method).to.eq('GET');
expect(server.status).to.eq(200);
expect(server.headers).to.be.null;
expect(server.response).to.be.null;
expect(server.onRequest).to.be.undefined;
expect(server.onResponse).to.be.undefined;
expect(server.onAbort).to.be.undefined;
// These options control the server behavior
// affecting all requests
// pass false to disable existing route stubs
expect(server.enable).to.be.true;
// forces requests that don't match your routes to 404
expect(server.force404).to.be.false;
// whitelists requests from ever being logged or stubbed
expect(server.whitelist).to.be.a('function');
});
cy.server({
method: 'POST',
delay: 1000,
status: 422,
response: {},
});
// any route commands will now inherit the above options
// from the server. anything we pass specifically
// to route will override the defaults though.
});
it('cy.request() - make an XHR request', () => {
// https://on.cypress.io/request
cy.request('https://jsonplaceholder.cypress.io/comments').should((response) => {
expect(response.status).to.eq(200);
expect(response.body).to.have.length(500);
expect(response).to.have.property('headers');
expect(response).to.have.property('duration');
});
});
it('cy.request() - verify response using BDD syntax', () => {
cy.request('https://jsonplaceholder.cypress.io/comments').then((response) => {
// https://on.cypress.io/assertions
expect(response).property('status').to.equal(200);
expect(response).property('body').to.have.length(500);
expect(response).to.include.keys('headers', 'duration');
});
});
it('cy.request() with query parameters', () => {
// will execute request
// https://jsonplaceholder.cypress.io/comments?postId=1&id=3
cy.request({
url: 'https://jsonplaceholder.cypress.io/comments',
qs: {
postId: 1,
id: 3,
},
})
.its('body')
.should('be.an', 'array')
.and('have.length', 1)
.its('0') // yields first element of the array
.should('contain', {
postId: 1,
id: 3,
});
});
it('cy.request() - pass result to the second request', () => {
// first, let's find out the userId of the first user we have
cy.request('https://jsonplaceholder.cypress.io/users?_limit=1')
.its('body.0') // yields the first element of the returned list
.then((user) => {
expect(user).property('id').to.be.a('number');
// make a new post on behalf of the user
cy.request('POST', 'https://jsonplaceholder.cypress.io/posts', {
userId: user.id,
title: 'Cypress Test Runner',
body: 'Fast, easy and reliable testing for anything that runs in a browser.',
});
})
// note that the value here is the returned value of the 2nd request
// which is the new post object
.then((response) => {
expect(response).property('status').to.equal(201); // new entity created
expect(response).property('body').to.contain({
id: 101, // there are already 100 posts, so new entity gets id 101
title: 'Cypress Test Runner',
});
// we don't know the user id here - since it was in above closure
// so in this test just confirm that the property is there
expect(response.body).property('userId').to.be.a('number');
});
});
it('cy.request() - save response in the shared test context', () => {
// https://on.cypress.io/variables-and-aliases
cy.request('https://jsonplaceholder.cypress.io/users?_limit=1')
.its('body.0') // yields the first element of the returned list
.as('user') // saves the object in the test context
.then(function () {
// NOTE 👀
// By the time this callback runs the "as('user')" command
// has saved the user object in the test context.
// To access the test context we need to use
// the "function () { ... }" callback form,
// otherwise "this" points at a wrong or undefined object!
cy.request('POST', 'https://jsonplaceholder.cypress.io/posts', {
userId: this.user.id,
title: 'Cypress Test Runner',
body: 'Fast, easy and reliable testing for anything that runs in a browser.',
})
.its('body')
.as('post'); // save the new post from the response
})
.then(function () {
// When this callback runs, both "cy.request" API commands have finished
// and the test context has "user" and "post" objects set.
// Let's verify them.
expect(this.post, 'post has the right user id').property('userId').to.equal(this.user.id);
});
});
it('cy.route() - route responses to matching requests', () => {
// https://on.cypress.io/route
let message = 'whoa, this comment does not exist';
cy.server();
// Listen to GET to comments/1
cy.route('GET', 'comments/*').as('getComment');
// we have code that gets a comment when
// the button is clicked in scripts.js
cy.get('.network-btn').click();
// https://on.cypress.io/wait
cy.wait('@getComment').its('status').should('eq', 200);
// Listen to POST to comments
cy.route('POST', '/comments').as('postComment');
// we have code that posts a comment when
// the button is clicked in scripts.js
cy.get('.network-post').click();
cy.wait('@postComment');
// get the route
cy.get('@postComment').should((xhr) => {
expect(xhr.requestBody).to.include('email');
expect(xhr.requestHeaders).to.have.property('Content-Type');
expect(xhr.responseBody).to.have.property('name', 'Using POST in cy.route()');
});
// Stub a response to PUT comments/ ****
cy.route({
method: 'PUT',
url: 'comments/*',
status: 404,
response: { error: message },
delay: 500,
}).as('putComment');
// we have code that puts a comment when
// the button is clicked in scripts.js
cy.get('.network-put').click();
cy.wait('@putComment');
// our 404 statusCode logic in scripts.js executed
cy.get('.network-put-comment').should('contain', message);
});
});

View File

@@ -1,75 +0,0 @@
/// <reference types="Cypress" />
context('Querying', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/querying');
});
// The most commonly used query is 'cy.get()', you can
// think of this like the '$' in jQuery
it('cy.get() - query DOM elements', () => {
// https://on.cypress.io/get
cy.get('#query-btn').should('contain', 'Button');
cy.get('.query-btn').should('contain', 'Button');
cy.get('#querying .well>button:first').should('contain', 'Button');
// ↲
// Use CSS selectors just like jQuery
cy.get('[data-test-id="test-example"]').should('have.class', 'example');
// 'cy.get()' yields jQuery object, you can get its attribute
// by invoking `.attr()` method
cy.get('[data-test-id="test-example"]')
.invoke('attr', 'data-test-id')
.should('equal', 'test-example');
// or you can get element's CSS property
cy.get('[data-test-id="test-example"]').invoke('css', 'position').should('equal', 'static');
// or use assertions directly during 'cy.get()'
// https://on.cypress.io/assertions
cy.get('[data-test-id="test-example"]')
.should('have.attr', 'data-test-id', 'test-example')
.and('have.css', 'position', 'static');
});
it('cy.contains() - query DOM elements with matching content', () => {
// https://on.cypress.io/contains
cy.get('.query-list').contains('bananas').should('have.class', 'third');
// we can pass a regexp to `.contains()`
cy.get('.query-list').contains(/^b\w+/).should('have.class', 'third');
cy.get('.query-list').contains('apples').should('have.class', 'first');
// passing a selector to contains will
// yield the selector containing the text
cy.get('#querying').contains('ul', 'oranges').should('have.class', 'query-list');
cy.get('.query-button').contains('Save Form').should('have.class', 'btn');
});
it('.within() - query DOM elements within a specific element', () => {
// https://on.cypress.io/within
cy.get('.query-form').within(() => {
cy.get('input:first').should('have.attr', 'placeholder', 'Email');
cy.get('input:last').should('have.attr', 'placeholder', 'Password');
});
});
it('cy.root() - query the root DOM element', () => {
// https://on.cypress.io/root
// By default, root is the document
cy.root().should('match', 'html');
cy.get('.query-ul').within(() => {
// In this within, the root is now the ul DOM element
cy.root().should('have.class', 'query-ul');
});
});
});

View File

@@ -1,94 +0,0 @@
/// <reference types="Cypress" />
context('Spies, Stubs, and Clock', () => {
it('cy.spy() - wrap a method in a spy', () => {
// https://on.cypress.io/spy
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks');
const obj = {
foo() {},
};
const spy = cy.spy(obj, 'foo').as('anyArgs');
obj.foo();
expect(spy).to.be.called;
});
it('cy.spy() retries until assertions pass', () => {
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks');
const obj = {
/**
* Prints the argument passed
*
* @param x {any}
*/
foo(x) {
console.log('obj.foo called with', x);
},
};
cy.spy(obj, 'foo').as('foo');
setTimeout(() => {
obj.foo('first');
}, 500);
setTimeout(() => {
obj.foo('second');
}, 2500);
cy.get('@foo').should('have.been.calledTwice');
});
it('cy.stub() - create a stub and/or replace a function with stub', () => {
// https://on.cypress.io/stub
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks');
const obj = {
/**
* Prints both arguments to the console
*
* @param a {string}
* @param b {string}
*/
foo(a, b) {
console.log('a', a, 'b', b);
},
};
const stub = cy.stub(obj, 'foo').as('foo');
obj.foo('foo', 'bar');
expect(stub).to.be.called;
});
it('cy.clock() - control time in the browser', () => {
// https://on.cypress.io/clock
// create the date in UTC so its always the same
// no matter what local timezone the browser is running in
const now = new Date(Date.UTC(2017, 2, 14)).getTime();
cy.clock(now);
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks');
cy.get('#clock-div').click().should('have.text', '1489449600');
});
it('cy.tick() - move time in the browser', () => {
// https://on.cypress.io/tick
// create the date in UTC so its always the same
// no matter what local timezone the browser is running in
const now = new Date(Date.UTC(2017, 2, 14)).getTime();
cy.clock(now);
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks');
cy.get('#tick-div').click().should('have.text', '1489449600');
cy.tick(10000); // 10 seconds passed
cy.get('#tick-div').click().should('have.text', '1489449610');
});
});

View File

@@ -1,97 +0,0 @@
/// <reference types="Cypress" />
context('Traversal', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/traversal');
});
it('.children() - get child DOM elements', () => {
// https://on.cypress.io/children
cy.get('.traversal-breadcrumb').children('.active').should('contain', 'Data');
});
it('.closest() - get closest ancestor DOM element', () => {
// https://on.cypress.io/closest
cy.get('.traversal-badge').closest('ul').should('have.class', 'list-group');
});
it('.eq() - get a DOM element at a specific index', () => {
// https://on.cypress.io/eq
cy.get('.traversal-list>li').eq(1).should('contain', 'siamese');
});
it('.filter() - get DOM elements that match the selector', () => {
// https://on.cypress.io/filter
cy.get('.traversal-nav>li').filter('.active').should('contain', 'About');
});
it('.find() - get descendant DOM elements of the selector', () => {
// https://on.cypress.io/find
cy.get('.traversal-pagination').find('li').find('a').should('have.length', 7);
});
it('.first() - get first DOM element', () => {
// https://on.cypress.io/first
cy.get('.traversal-table td').first().should('contain', '1');
});
it('.last() - get last DOM element', () => {
// https://on.cypress.io/last
cy.get('.traversal-buttons .btn').last().should('contain', 'Submit');
});
it('.next() - get next sibling DOM element', () => {
// https://on.cypress.io/next
cy.get('.traversal-ul').contains('apples').next().should('contain', 'oranges');
});
it('.nextAll() - get all next sibling DOM elements', () => {
// https://on.cypress.io/nextall
cy.get('.traversal-next-all').contains('oranges').nextAll().should('have.length', 3);
});
it('.nextUntil() - get next sibling DOM elements until next el', () => {
// https://on.cypress.io/nextuntil
cy.get('#veggies').nextUntil('#nuts').should('have.length', 3);
});
it('.not() - remove DOM elements from set of DOM elements', () => {
// https://on.cypress.io/not
cy.get('.traversal-disabled .btn').not('[disabled]').should('not.contain', 'Disabled');
});
it('.parent() - get parent DOM element from DOM elements', () => {
// https://on.cypress.io/parent
cy.get('.traversal-mark').parent().should('contain', 'Morbi leo risus');
});
it('.parents() - get parent DOM elements from DOM elements', () => {
// https://on.cypress.io/parents
cy.get('.traversal-cite').parents().should('match', 'blockquote');
});
it('.parentsUntil() - get parent DOM elements from DOM elements until el', () => {
// https://on.cypress.io/parentsuntil
cy.get('.clothes-nav').find('.active').parentsUntil('.clothes-nav').should('have.length', 2);
});
it('.prev() - get previous sibling DOM element', () => {
// https://on.cypress.io/prev
cy.get('.birds').find('.active').prev().should('contain', 'Lorikeets');
});
it('.prevAll() - get all previous sibling DOM elements', () => {
// https://on.cypress.io/prevAll
cy.get('.fruits-list').find('.third').prevAll().should('have.length', 2);
});
it('.prevUntil() - get all previous sibling DOM elements until el', () => {
// https://on.cypress.io/prevUntil
cy.get('.foods-list').find('#nuts').prevUntil('#veggies').should('have.length', 3);
});
it('.siblings() - get all sibling DOM elements', () => {
// https://on.cypress.io/siblings
cy.get('.traversal-pills .active').siblings().should('have.length', 2);
});
});

View File

@@ -1,129 +0,0 @@
/// <reference types="Cypress" />
context('Utilities', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/utilities');
});
it('Cypress._ - call a lodash method', () => {
// https://on.cypress.io/_
cy.request('https://jsonplaceholder.cypress.io/users').then((response) => {
let ids = Cypress._.chain(response.body).map('id').take(3).value();
expect(ids).to.deep.eq([1, 2, 3]);
});
});
it('Cypress.$ - call a jQuery method', () => {
// https://on.cypress.io/$
let $li = Cypress.$('.utility-jquery li:first');
cy.wrap($li).should('not.have.class', 'active').click().should('have.class', 'active');
});
it('Cypress.Blob - blob utilities and base64 string conversion', () => {
// https://on.cypress.io/blob
cy.get('.utility-blob').then(($div) =>
// https://github.com/nolanlawson/blob-util#imgSrcToDataURL
// get the dataUrl string for the javascript-logo
Cypress.Blob.imgSrcToDataURL(
'https://example.cypress.io/assets/img/javascript-logo.png',
undefined,
'anonymous'
).then((dataUrl) => {
// create an <img> element and set its src to the dataUrl
let img = Cypress.$('<img />', { src: dataUrl });
// need to explicitly return cy here since we are initially returning
// the Cypress.Blob.imgSrcToDataURL promise to our test
// append the image
$div.append(img);
cy.get('.utility-blob img').click().should('have.attr', 'src', dataUrl);
})
);
});
it('Cypress.minimatch - test out glob patterns against strings', () => {
// https://on.cypress.io/minimatch
let matching = Cypress.minimatch('/users/1/comments', '/users/*/comments', {
matchBase: true,
});
expect(matching, 'matching wildcard').to.be.true;
matching = Cypress.minimatch('/users/1/comments/2', '/users/*/comments', {
matchBase: true,
});
expect(matching, 'comments').to.be.false;
// ** matches against all downstream path segments
matching = Cypress.minimatch('/foo/bar/baz/123/quux?a=b&c=2', '/foo/**', {
matchBase: true,
});
expect(matching, 'comments').to.be.true;
// whereas * matches only the next path segment
matching = Cypress.minimatch('/foo/bar/baz/123/quux?a=b&c=2', '/foo/*', {
matchBase: false,
});
expect(matching, 'comments').to.be.false;
});
it('Cypress.moment() - format or parse dates using a moment method', () => {
// https://on.cypress.io/moment
const time = Cypress.moment().utc('2014-04-25T19:38:53.196Z').format('h:mm A');
expect(time).to.be.a('string');
cy.get('.utility-moment').contains('3:38 PM').should('have.class', 'badge');
// the time in the element should be between 3pm and 5pm
const start = Cypress.moment('3:00 PM', 'LT');
const end = Cypress.moment('5:00 PM', 'LT');
cy.get('.utility-moment .badge').should(($el) => {
// parse American time like "3:38 PM"
const m = Cypress.moment($el.text().trim(), 'LT');
// display hours + minutes + AM|PM
const f = 'h:mm A';
expect(
m.isBetween(start, end),
`${m.format(f)} should be between ${start.format(f)} and ${end.format(f)}`
).to.be.true;
});
});
it('Cypress.Promise - instantiate a bluebird promise', () => {
// https://on.cypress.io/promise
let waited = false;
/** @returns Bluebird<string> */
function waitOneSecond() {
// return a promise that resolves after 1 second
// @ts-ignore TS2351 (new Cypress.Promise)
return new Cypress.Promise((resolve, reject) => {
setTimeout(() => {
// set waited to true
waited = true;
// resolve with 'foo' string
resolve('foo');
}, 1000);
});
}
cy.then(() =>
// return a promise to cy.then() that
// is awaited until it resolves
// @ts-ignore TS7006
waitOneSecond().then((str) => {
expect(str).to.eq('foo');
expect(waited).to.be.true;
})
);
});
});

View File

@@ -1,59 +0,0 @@
/// <reference types="Cypress" />
context('Viewport', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/viewport');
});
it('cy.viewport() - set the viewport size and dimension', () => {
// https://on.cypress.io/viewport
cy.get('#navbar').should('be.visible');
cy.viewport(320, 480);
// the navbar should have collapse since our screen is smaller
cy.get('#navbar').should('not.be.visible');
cy.get('.navbar-toggle').should('be.visible').click();
cy.get('.nav').find('a').should('be.visible');
// lets see what our app looks like on a super large screen
cy.viewport(2999, 2999);
// cy.viewport() accepts a set of preset sizes
// to easily set the screen to a device's width and height
// We added a cy.wait() between each viewport change so you can see
// the change otherwise it is a little too fast to see :)
cy.viewport('macbook-15');
cy.wait(200);
cy.viewport('macbook-13');
cy.wait(200);
cy.viewport('macbook-11');
cy.wait(200);
cy.viewport('ipad-2');
cy.wait(200);
cy.viewport('ipad-mini');
cy.wait(200);
cy.viewport('iphone-6+');
cy.wait(200);
cy.viewport('iphone-6');
cy.wait(200);
cy.viewport('iphone-5');
cy.wait(200);
cy.viewport('iphone-4');
cy.wait(200);
cy.viewport('iphone-3');
cy.wait(200);
// cy.viewport() accepts an orientation for all presets
// the default orientation is 'portrait'
cy.viewport('ipad-2', 'portrait');
cy.wait(200);
cy.viewport('iphone-4', 'landscape');
cy.wait(200);
// The viewport will be reset back to the default dimensions
// in between tests (the default can be set in cypress.json)
});
});

View File

@@ -1,33 +0,0 @@
/// <reference types="Cypress" />
context('Waiting', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/waiting');
});
// BE CAREFUL of adding unnecessary wait times.
// https://on.cypress.io/best-practices#Unnecessary-Waiting
// https://on.cypress.io/wait
it('cy.wait() - wait for a specific amount of time', () => {
cy.get('.wait-input1').type('Wait 1000ms after typing');
cy.wait(1000);
cy.get('.wait-input2').type('Wait 1000ms after typing');
cy.wait(1000);
cy.get('.wait-input3').type('Wait 1000ms after typing');
cy.wait(1000);
});
it('cy.wait() - wait for a specific route', () => {
cy.server();
// Listen to GET to comments/1
cy.route('GET', 'comments/*').as('getComment');
// we have code that gets a comment when
// the button is clicked in scripts.js
cy.get('.network-btn').click();
// wait for GET comments/1
cy.wait('@getComment').its('status').should('eq', 200);
});
});

View File

@@ -1,22 +0,0 @@
/// <reference types="Cypress" />
context('Window', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/window');
});
it('cy.window() - get the global window object', () => {
// https://on.cypress.io/window
cy.window().should('have.property', 'top');
});
it('cy.document() - get the document object', () => {
// https://on.cypress.io/document
cy.document().should('have.property', 'charset').and('eq', 'UTF-8');
});
it('cy.title() - get the title', () => {
// https://on.cypress.io/title
cy.title().should('include', 'Kitchen Sink');
});
});

View File

@@ -1,5 +0,0 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}

View File

@@ -102,4 +102,109 @@ describe('Git Graph diagram', () => {
{}
);
});
it('8: should render a simple gitgraph with more than 8 branchs & overriding variables', () => {
imgSnapshotTest(
`%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': {
'gitBranchLabel0': '#ffffff',
'gitBranchLabel1': '#ffffff',
'gitBranchLabel2': '#ffffff',
'gitBranchLabel3': '#ffffff',
'gitBranchLabel4': '#ffffff',
'gitBranchLabel5': '#ffffff',
'gitBranchLabel6': '#ffffff',
'gitBranchLabel7': '#ffffff',
} } }%%
gitGraph
checkout main
branch branch1
branch branch2
branch branch3
branch branch4
branch branch5
branch branch6
branch branch7
branch branch8
branch branch9
checkout branch1
commit id: "1"
`,
{}
);
});
it('9: should render a simple gitgraph with rotated labels', () => {
imgSnapshotTest(
`%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'gitGraph': {
'rotateCommitLabel': true
} } }%%
gitGraph
commit id: "75f7219e83b321cd3fdde7dcf83bc7c1000a6828"
commit id: "0db4784daf82736dec4569e0dc92980d328c1f2e"
commit id: "7067e9973f9eaa6cd4a4b723c506d1eab598e83e"
commit id: "66972321ad6c199013b5b31f03b3a86fa3f9817d"
`,
{}
);
});
it('10: should render a simple gitgraph with horizontal labels', () => {
imgSnapshotTest(
`%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'gitGraph': {
'rotateCommitLabel': false
} } }%%
gitGraph
commit id: "Alpha"
commit id: "Beta"
commit id: "Gamma"
commit id: "Delta"
`,
{}
);
});
it('11: should render a simple gitgraph with cherry pick commit', () => {
imgSnapshotTest(
`
gitGraph
commit id: "ZERO"
branch develop
commit id:"A"
checkout main
commit id:"ONE"
checkout develop
commit id:"B"
checkout main
commit id:"TWO"
cherry-pick id:"A"
commit id:"THREE"
checkout develop
commit id:"C"
`,
{}
);
});
it('11: should render a simple gitgraph with two cherry pick commit', () => {
imgSnapshotTest(
`
gitGraph
commit id: "ZERO"
branch develop
commit id:"A"
checkout main
commit id:"ONE"
checkout develop
commit id:"B"
branch featureA
commit id:"FIX"
commit id: "FIX-2"
checkout main
commit id:"TWO"
cherry-pick id:"A"
commit id:"THREE"
cherry-pick id:"FIX"
checkout develop
commit id:"C"
merge featureA
`,
{}
);
});
});

View File

@@ -452,6 +452,42 @@ context('Sequence diagram', () => {
{}
);
});
it('should render rect around and inside criticals', () => {
imgSnapshotTest(
`
sequenceDiagram
A ->> B: 1
rect rgb(204, 0, 102)
critical yes
C ->> C: 1
option no
rect rgb(0, 204, 204)
C ->> C: 0
end
end
end
B ->> A: Return
`,
{}
);
});
it('should render rect around and inside breaks', () => {
imgSnapshotTest(
`
sequenceDiagram
A ->> B: 1
rect rgb(204, 0, 102)
break yes
rect rgb(0, 204, 204)
C ->> C: 0
end
end
end
B ->> A: Return
`,
{}
);
});
it('should render autonumber when configured with such', () => {
imgSnapshotTest(
`

View File

@@ -346,6 +346,21 @@ describe('State diagram', () => {
}
);
});
it('v2 A compound state should be able to link to itself', () => {
imgSnapshotTest(
`
stateDiagram
state Active {
Idle
}
Inactive --> Idle: ACT
Active --> Active: LOG
`,
{
logLevel: 0,
}
);
});
it('v2 width of compond state should grow with title if title is wider', () => {
imgSnapshotTest(
`

View File

@@ -78,7 +78,7 @@
a_a --> c --> d_d --> c_c
classDef apa fill:#f9f,stroke:#333,stroke-width:4px;
class a_a apa;
click a_a "http://www.aftonbladet.se" "apa"
click a_a "https://www.aftonbladet.se" "apa"
</div>

View File

@@ -30,7 +30,54 @@
<div class="mermaid" style="width: 50%;">
<div class="mermaid2" style="width: 50%;">
journey
title Adding journey diagram functionality to mermaid
accTitle: Adding acc journey diagram functionality to mermaid
accDescr {
My multi-line description
of the diagram
}
section Order from website
</div>
<div class="mermaid2" style="width: 50%;">
pie
accTitle: My Pie Chart Accessibility Title
accDescr: My Pie Chart Accessibility Description
title Key elements in Product X
"Calcium" : 42.96
"Potassium" : 50.05
"Magnesium" : 10.01
"Iron" : 5
</div>
<div class="mermaid2" style="width: 50%;">
gitGraph
accTitle: My Gitgraph Accessibility Title
accDescr: My Gitgraph Accessibility Description
commit
commit
branch develop
checkout develop
commit
commit
checkout main
merge develop
commit
commit
</div>
<div class="mermaid2" style="width: 50%;">
sequenceDiagram
title: My Sequence Diagram Title
accTitle: My Acc Sequence Diagram
accDescr: My Sequence Diagram Description
Alice->>John: Hello John, how are you?
John-->>Alice: Great!
Alice-)John: See you later!
</div>
<div class="mermaid2" style="width: 50%;">
graph TD
A -->|000| B
B -->|111| C
@@ -38,18 +85,23 @@ graph TD
linkStyle 1 stroke:#ff3,stroke-width:4px,color:red;
</div>
<div class="mermaid2" style="width: 100%;">
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: 5: Me
journey
accTitle: My User Journey Diagram
accDescr: My User Journey Diagram Description
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: 5: Me
</div>
<div class="mermaid2" style="width: 100%;">
requirementDiagram
accTitle: My req Diagram
accDescr: My req Diagram Description
requirement test_req {
id: 1
@@ -87,65 +139,38 @@ requirementDiagram
test_req - contains -> test_req3
test_req <- copies - test_entity2
</div>
<div class="mermaid2" style="width: 100%;">
erDiagram
CUSTOMER }|..|{ DELIVERY-ADDRESS : has
CUSTOMER ||--o{ ORDER : places
CUSTOMER ||--o{ INVOICE : "liable for"
DELIVERY-ADDRESS ||--o{ ORDER : receives
INVOICE ||--|{ ORDER : covers
ORDER ||--|{ ORDER-ITEM : includes
PRODUCT-CATEGORY ||--|{ PRODUCT : contains
PRODUCT ||--o{ ORDER-ITEM : "ordered in"
<div class="mermaid" style="width: 100%;">
stateDiagram
state Active {
Idle
}
Inactive --> Idle: ACT
Active --> Active: LOG
</div>
<div class="mermaid2" style="width: 100%;">
graph TB
accTitle: My flowchart
accDescr: My flowchart Description
subgraph One
a1-->a2-->a3
end
</div>
<div class="mermaid2" style="width: 100%;">
gantt
dateFormat YYYY-MM-DD
axisFormat %d/%m
title Adding GANTT diagram to mermaid
excludes weekdays 2014-01-10
section A section
Completed task :done, des1, 2014-01-06,2014-01-08
Active task :active, des2, 2014-01-09, 3d
Future task : des3, after des2, 5d
Future task2 : des4, after des3, 5d
section Critical tasks
Completed task in the critical line :crit, done, 2014-01-06,24h
Implement parser and jison :crit, done, after des1, 2d
Create tests for parser :crit, active, 3d
Future task in critical line :crit, 5d
Create tests for renderer :2d
Add to mermaid :1d
section Documentation
Describe gantt syntax :active, a1, after des1, 3d
Add gantt diagram to demo page :after a1 , 20h
Add another diagram to demo page :doc1, after a1 , 48h
section Clickable
Visit mermaidjs :active, cl1, 2014-01-07,2014-01-10
Calling a Callback (look at the console log) :cl2, after cl1, 3d
Calling a Callback with args :cl3, after cl1, 3d
click cl1 href "https://mermaid-js.github.io/mermaid/#/"
click cl2 call clickByGantt()
click cl3 call clickByGantt("test1", test2, test3)
section Last section
Describe gantt syntax :after doc1, 3d
Add gantt diagram to demo page : 20h
Add another diagram to demo page : 48h
sequenceDiagram
A ->> B: 1
rect rgb(204, 0, 102)
break yes
rect rgb(0, 204, 204)
C ->> C: 0
end
end
end
B ->> A: Return
</div>
<div class="mermaid2" style="width: 100%;">
classDiagram
accTitle: My class diagram
accDescr: My class diagram Description
Class01 <|-- AveryLongClass : Cool
Class09 --> C2 : Where am i?
Class09 --* C3
@@ -162,6 +187,8 @@ class Class10 {
</div>
<div class="mermaid2" style="width: 100%;">
stateDiagram
accTitle: Apa
accDescr: One that can climb better then any man
[*] --> S1
state "Some long name" as S1
</div>
@@ -203,6 +230,7 @@ class Class10 {
nodeSpacing: 10,
curve: 'cardinal',
htmlLabels: true,
useMaxWidth: false,
// defaultRenderer: 'dagre-d3',
},
class: {

View File

@@ -11,52 +11,207 @@
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
font-family: 'Courier New', Courier, monospace;
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
.mermaid {
border: 1px solid red;
font-family: 'Courier New', Courier, monospace;
/* font-size: 18px !important; */
}
</style>
</head>
<body>
<div>info below</div>
<div class="flex">
<div class="">
<div class="mermaid2" style="width: 100%; height: 400px;">
%%{init: { "logLevel": 1, "er": {"fontSize":18 }} }%%
erDiagram
CUSTOMER }|..|{ DELIVERY-ADDRESS : has
CUSTOMER ||--o{ ORDER : places
CUSTOMER ||--o{ INVOICE : "liable for"
DELIVERY-ADDRESS ||--o{ ORDER : receives
INVOICE ||--|{ ORDER : covers
ORDER ||--|{ ORDER-ITEM : includes
PRODUCT-CATEGORY ||--|{ PRODUCT : contains
PRODUCT ||--o{ ORDER-ITEM : "ordered in"
flowchart TB;subgraph "number as labels";1;end;
</div>
<div class="mermaid2" style="width: 50%; height: 400px;">
<div class="mermaid2" style="width: 100%; height: 400px;">
flowchart TB;a[APA];
</div>
<div class="mermaid2" style="margin-left:100px;">
graph TD
work --> sleep
sleep --> work
eat --> sleep
work --> eat
</div>
<div class="mermaid2" style="margin-left:100px;">
flowchart TD
A[Christmas] ==> D
A[Christmas] -->|Get money| B(Go shopping)
A[Christmas] ==> C
subgraph T ["Test"]
A
B
C
end
work --> sleep
sleep --> work
eat --> sleep
work --> eat
</div>
<div class="mermaid2" style="">
graph TB
A
B
subgraph foo[Foo SubGraph]
C
D
end
subgraph bar[Bar SubGraph]
E
F
end
G
classDef Test fill:#F84E68,stroke:#333,color:white;
class A,T Test
classDef TestSub fill:green;
class T TestSub
linkStyle 0,1 color:orange, stroke: orange;
A-->B
B-->C
C-->D
B-->D
D-->E
E-->A
E-->F
F-->D
F-->G
B-->G
G-->D
style foo fill:#F99,stroke-width:2px,stroke:#F0F,color:darkred
style bar fill:#999,stroke-width:2px,stroke:#0F0,color:blue
</div>
<div class="mermaid2" style="">
graph TB
%%{init: { "logLevel": 1, "flowchart": {"htmlLabels":true }} }%%
A
B
subgraph foo[Foo SubGraph]
C
D
end
subgraph bar[Bar SubGraph]
E
F
end
G
A-->B
B-->C
C-->D
B-->D
D-->E
E-->A
E-->F
F-->D
F-->G
B-->G
G-->D
style foo fill:#F99,stroke-width:2px,stroke:#F0F,color:darkred
style bar fill:#999,stroke-width:10px,stroke:#0F0,color:blue
</div>
<div class="mermaid2" style="">
graph TD
A[Christmas] ==> D
A[Christmas] -->|Get money| B(Go shopping)
A[Christmas] ==> C
</div>
<div class="mermaid2" style="">
graph TD
%%{init: { "logLevel": 1, "flowchart": {"htmlLabels":true }} }%%
A[Christmas] ==> D
A[Christmas] -->|Get money| B(Go shopping)
A[Christmas] ==> C
</div>
<div class="mermaid2" style="">
flowchart TD
A[Christmas] ==> D
A[Christmas] -->|Get money| B(Go shopping)
A[Christmas] ==> C
</div>
<div class="mermaid2" style="">
flowchart TD
%%{init: { "logLevel": 1, "flowchart": {"htmlLabels":true }} }%%
A[Christmas] ==> D
A[Christmas] -->|Get money| B(Go shopping)
A[Christmas] ==> C
</div>
<div class="mermaid2" style="">
flowchart LR
a["<strong>Haiya</strong>"]---->b
</div>
<div class="mermaid" style="width: 100%; height: 20%;">
flowchart TB
<div class="mermaid2" style="">
flowchart LR
%%{init: { "logLevel": 1, "flowchart": {"htmlLabels":true }} }%%
a["<strong>Haiya</strong>"]---->b
</div>
<div class="mermaid2" style="">
flowchart TD
A[Christmas] ==> D
A[Christmas] -->|Get money| B(Go shopping)
A[Christmas] ==> C
</div>
<div class="mermaid2" style="">
flowchart TD
%%{init: { "logLevel": 1, "flowchart": {"htmlLabels":true }} }%%
A[Christmas] ==> D
A[Christmas] -->|Get money| B(Go shopping)
A[Christmas] ==> C
</div>
<div class="mermaid2" style="">
%%{init: { "logLevel": 1, "flowchart": {"htmlLabels":true }} }%%
classDiagram-v2
Class01 <|-- AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class03 *-- Class04
Class05 o-- Class06
Class07 .. Class08
Class09 --> C2 : Where am i?
Class09 --* C3
Class09 --|> Class07
Class12 <|.. Class08
Class11 ..>Class12
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class01 : -int privateChimp
Class01 : +int publicGorilla
Class01 : #int protectedMarmoset
Class08 <--> C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
test()
}
</div>
<div class="mermaid2" style="">
classDiagram-v2
Class01 <|-- AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class03 *-- Class04
Class05 o-- Class06
Class07 .. Class08
Class09 --> C2 : Where am i?
Class09 --* C3
Class09 --|> Class07
Class12 <|.. Class08
Class11 ..>Class12
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class01 : -int privateChimp
Class01 : +int publicGorilla
Class01 : #int protectedMarmoset
Class08 <--> C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
test()
}
</div>
<div class="mermaid" style="">
flowchart BT
subgraph S1
sub1 -->sub2
end
@@ -66,141 +221,25 @@ flowchart TB
S1 --> S2
sub1 --> sub4
</div>
<div class="mermaid2" style="width: 100%; height: 20%;">
flowchart TB
c1-->a2
subgraph one
a1-->a2
end
subgraph two
b1-->b2
end
subgraph three
c1-->c2
end
one --> two
three --> two
two --> c2
</div>
<div class="mermaid2" style="width: 100%; height: 20%;">
stateDiagram-v2
state S1 {
sub1 -->sub2
}
state S2 {
sub4
}
S1 --> S2
sub1 --> sub4
</div>
<div class="mermaid2" style="width: 100%; height: 20%;">
requirementDiagram
requirement test_req {
id: 1
text: the test text.
risk: high
verifymethod: test
}
functionalRequirement test_req2 {
id: 1.1
text: the second test text.
risk: low
verifymethod: inspection
}
performanceRequirement test_req3 {
id: 1.2
text: the third test text.
risk: medium
verifymethod: demonstration
}
element test_entity {
type: simulation
}
element test_entity2 {
type: word doc
docRef: reqs/test_entity
}
test_entity - satisfies -> test_req2
test_req - traces -> test_req2
test_req - contains -> test_req3
test_req <- copies - test_entity2
</div>
<div class="mermaid2" style="width: 50%; height: 20%;">
flowchart LR
classDef dark fill:#000,stroke:#000,stroke-width:4px,color:#fff
Lorem --> Ipsum --> Dolor
class Lorem,Dolor dark
</div>
<div class="mermaid2" style="width: 50%; height: 20%;">
%%{init: {'theme': 'base' }}%%
%%{init2: { 'logLevel': 0, 'theme': 'forest'} }%%
flowchart TD
L1 --- L2
L2 --- C
M1 ---> C
R1 .-> R2
R2 <.-> C
C -->|Label 1| E1
C <-- Label 2 ---> E2
C ----> E3
C <-...-> E4
C ======> E5
</div>
<div class="mermaid2" style="width: 50%; height: 21%;">
flowchart LR
A[red text] -->|default style| B(blue text)
C([red text]) -->|default style| D[[blue text]]
E[(red text)] -->|default style| F((blue text))
G>red text] -->|default style| H{blue text}
I{{red text}} -->|default style| J[/blue text/]
K[
ed text] -->|default style| L[/blue text]
M[
ed text/] -->|default style| N[blue text]
linkStyle default color:Sienna;
style A stroke:#ff0000,fill:#ffcccc,color:#ff0000
style B stroke:#0000ff,fill:#ccccff,color:#0000ff
style C stroke:#ff0000,fill:#ffcccc,color:#ff0000
style D stroke:#0000ff,fill:#ccccff,color:#0000ff
style E stroke:#ff0000,fill:#ffcccc,color:#ff0000
style F stroke:#0000ff,fill:#ccccff,color:#0000ff
style G stroke:#ff0000,fill:#ffcccc,color:#ff0000
style H stroke:#0000ff,fill:#ccccff,color:#0000ff
style I stroke:#ff0000,fill:#ffcccc,color:#ff0000
style J stroke:#0000ff,fill:#ccccff,color:#0000ff
style K stroke:#ff0000,fill:#ffcccc,color:#ff0000
style L stroke:#0000ff,fill:#ccccff,color:#0000ff
style M stroke:#ff0000,fill:#ffcccc,color:#ff0000
style N stroke:#0000ff,fill:#ccccff,color:#0000ff
</div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'neutral',
arrowMarkerAbsolute: true,
// theme: 'neutral',
// arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
flowchart: { nodeSpacing: 10, curve: 'cardinal', htmlLabels: true },
htmlLabels: true,
flowchart: { curve: 'cardinal', htmlLabels: false },
// htmlLabels: true,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
// sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'cardinal',
fontFamily: 'courier',
// fontSize: 18,
// curve: 'cardinal',
securityLevel: 'loose',
// themeVariables: {relationLabelColor: 'red'}
});

View File

@@ -20,6 +20,165 @@
</div>
<hr />
<div class="mermaid">
C4Context
title System Context diagram for Internet Banking System
Enterprise_Boundary(b0, "BankBoundary0") {
Person(customerA, "Banking Customer A", "A customer of the bank, with personal bank accounts.")
Person(customerB, "Banking Customer B")
Person_Ext(customerC, "Banking Customer C", "desc")
Person(customerD, "Banking Customer D", "A customer of the bank, <br/> with personal bank accounts.")
System(SystemAA, "Internet Banking System", "Allows customers to view information about their bank accounts, and make payments.")
Enterprise_Boundary(b1, "BankBoundary") {
SystemDb_Ext(SystemE, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")
System_Boundary(b2, "BankBoundary2") {
System(SystemA, "Banking System A")
System(SystemB, "Banking System B", "A system of the bank, with personal bank accounts. next line.")
}
System_Ext(SystemC, "E-mail system", "The internal Microsoft Exchange e-mail system.")
SystemDb(SystemD, "Banking System D Database", "A system of the bank, with personal bank accounts.")
Boundary(b3, "BankBoundary3", "boundary") {
SystemQueue(SystemF, "Banking System F Queue", "A system of the bank.")
SystemQueue_Ext(SystemG, "Banking System G Queue", "A system of the bank, with personal bank accounts.")
}
}
}
BiRel(customerA, SystemAA, "Uses")
BiRel(SystemAA, SystemE, "Uses")
Rel(SystemAA, SystemC, "Sends e-mails", "SMTP")
Rel(SystemC, customerA, "Sends e-mails to")
</div>
<div class="mermaid">
C4Container
title Container diagram for Internet Banking System
System_Ext(email_system, "E-Mail System", "The internal Microsoft Exchange system")
Person(customer, Customer, "A customer of the bank, with personal bank accounts")
Container_Boundary(c1, "Internet Banking") {
Container(spa, "Single-Page App", "JavaScript, Angular", "Provides all the Internet banking functionality to cutomers via their web browser")
Container_Ext(mobile_app, "Mobile App", "C#, Xamarin", "Provides a limited subset of the Internet banking functionality to customers via their mobile device")
Container(web_app, "Web Application", "Java, Spring MVC", "Delivers the static content and the Internet banking SPA")
ContainerDb(database, "Database", "SQL Database", "Stores user registration information, hashed auth credentials, access logs, etc.")
ContainerDb_Ext(backend_api, "API Application", "Java, Docker Container", "Provides Internet banking functionality via API")
}
System_Ext(banking_system, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")
Rel(customer, web_app, "Uses", "HTTPS")
Rel(customer, spa, "Uses", "HTTPS")
Rel(customer, mobile_app, "Uses")
Rel(web_app, spa, "Delivers")
Rel(spa, backend_api, "Uses", "async, JSON/HTTPS")
Rel(mobile_app, backend_api, "Uses", "async, JSON/HTTPS")
Rel_Back(database, backend_api, "Reads from and writes to", "sync, JDBC")
Rel(email_system, customer, "Sends e-mails to")
Rel(backend_api, email_system, "Sends e-mails using", "sync, SMTP")
Rel(backend_api, banking_system, "Uses", "sync/async, XML/HTTPS")
</div>
<div class="mermaid">
C4Component
title Component diagram for Internet Banking System - API Application
Container(spa, "Single Page Application", "javascript and angular", "Provides all the internet banking functionality to customers via their web browser.")
Container(ma, "Mobile App", "Xamarin", "Provides a limited subset ot the internet banking functionality to customers via their mobile mobile device.")
ContainerDb(db, "Database", "Relational Database Schema", "Stores user registration information, hashed authentication credentials, access logs, etc.")
System_Ext(mbs, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")
Container_Boundary(api, "API Application") {
Component(sign, "Sign In Controller", "MVC Rest Controlle", "Allows users to sign in to the internet banking system")
Component(accounts, "Accounts Summary Controller", "MVC Rest Controller", "Provides customers with a summary of their bank accounts")
Component(security, "Security Component", "Spring Bean", "Provides functionality related to singing in, changing passwords, etc.")
Component(mbsfacade, "Mainframe Banking System Facade", "Spring Bean", "A facade onto the mainframe banking system.")
Rel(sign, security, "Uses")
Rel(accounts, mbsfacade, "Uses")
Rel(security, db, "Read & write to", "JDBC")
Rel(mbsfacade, mbs, "Uses", "XML/HTTPS")
}
Rel_Back(spa, sign, "Uses", "JSON/HTTPS")
Rel(spa, accounts, "Uses", "JSON/HTTPS")
Rel(ma, sign, "Uses", "JSON/HTTPS")
Rel(ma, accounts, "Uses", "JSON/HTTPS")
</div>
<div class="mermaid">
C4Dynamic
title Dynamic diagram for Internet Banking System - API Application
ContainerDb(c4, "Database", "Relational Database Schema", "Stores user registration information, hashed authentication credentials, access logs, etc.")
Container(c1, "Single-Page Application", "JavaScript and Angular", "Provides all of the Internet banking functionality to customers via their web browser.")
Container_Boundary(b, "API Application") {
Component(c3, "Security Component", "Spring Bean", "Provides functionality Related to signing in, changing passwords, etc.")
Component(c2, "Sign In Controller", "Spring MVC Rest Controller", "Allows users to sign in to the Internet Banking System.")
}
Rel(c1, c2, "Submits credentials to", "JSON/HTTPS")
Rel(c2, c3, "Calls isAuthenticated() on")
Rel(c3, c4, "select * from users where username = ?", "JDBC")
</div>
<div class="mermaid">
C4Deployment
title Deployment Diagram for Internet Banking System - Live
Deployment_Node(mob, "Customer's mobile device", "Apple IOS or Android"){
Container(mobile, "Mobile App", "Xamarin", "Provides a limited subset of the Internet Banking functionality to customers via their mobile device.")
}
Deployment_Node(comp, "Customer's computer", "Mircosoft Windows or Apple macOS"){
Deployment_Node(browser, "Web Browser", "Google Chrome, Mozilla Firefox,<br/> Apple Safari or Microsoft Edge"){
Container(spa, "Single Page Application", "JavaScript and Angular", "Provides all of the Internet Banking functionality to customers via their web browser.")
}
}
Deployment_Node(plc, "Big Bank plc", "Big Bank plc data center"){
Deployment_Node(dn, "bigbank-api*** x8", "Ubuntu 16.04 LTS"){
Deployment_Node(apache, "Apache Tomcat", "Apache Tomcat 8.x"){
Container(api, "API Application", "Java and Spring MVC", "Provides Internet Banking functionality via a JSON/HTTPS API.")
}
}
Deployment_Node(bb2, "bigbank-web*** x4", "Ubuntu 16.04 LTS"){
Deployment_Node(apache2, "Apache Tomcat", "Apache Tomcat 8.x"){
Container(web, "Web Application", "Java and Spring MVC", "Delivers the static content and the Internet Banking single page application.")
}
}
Deployment_Node(bigbankdb01, "bigbank-db01", "Ubuntu 16.04 LTS"){
Deployment_Node(oracle, "Oracle - Primary", "Oracle 12c"){
ContainerDb(db, "Database", "Relational Database Schema", "Stores user registration information, hashed authentication credentials, access logs, etc.")
}
}
Deployment_Node(bigbankdb02, "bigbank-db02", "Ubuntu 16.04 LTS") {
Deployment_Node(oracle2, "Oracle - Secondary", "Oracle 12c") {
ContainerDb(db2, "Database", "Relational Database Schema", "Stores user registration information, hashed authentication credentials, access logs, etc.")
}
}
}
Rel(mobile, api, "Makes API calls to", "json/HTTPS")
Rel(spa, api, "Makes API calls to", "json/HTTPS")
Rel_U(web, spa, "Delivers to the customer's web browser")
Rel(api, db, "Reads from and writes to", "JDBC")
Rel(api, db2, "Reads from and writes to", "JDBC")
Rel_R(db, db2, "Replicates data to")
</div>
<hr />
<div class="mermaid">
pie
title Key elements in Product X

31940
dist/mermaid.core.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

129094
dist/mermaid.js vendored

File diff suppressed because one or more lines are too long

1
dist/mermaid.js.map vendored

File diff suppressed because one or more lines are too long

View File

@@ -203,7 +203,7 @@ Ensures options parameter does not attempt to override siteConfig secure keys.
| Parameter | Description |Type | Required | Values|
| --- | --- | --- | --- | --- |
| conf| base set of values, which currentConfig coul be reset to.| Dictionary | Required | Any Values, with respect to the secure Array|
| conf| base set of values, which currentConfig could be reset to.| Dictionary | Required | Any Values, with respect to the secure Array|
```note
default: current siteConfig (optional, default `getSiteConfig()`)

View File

@@ -2,7 +2,7 @@
**Mermaid lets you create diagrams and visualizations using text and code.**
It is a Javascript based diagramming and charting tool that renders Markdown-inspired text definitions to create and modify diagrams dynamically.
It is a JavaScript based diagramming and charting tool that renders Markdown-inspired text definitions to create and modify diagrams dynamically.
>If you are familiar with Markdown you should have no problem learning [Mermaid's Syntax](./n00b-syntaxReference.md).
@@ -18,7 +18,7 @@ It is a Javascript based diagramming and charting tool that renders Markdown-ins
<!-- <Main description> -->
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.
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.
> Doc-Rot is a Catch-22 that Mermaid helps to solve.
@@ -195,7 +195,7 @@ To Deploy Mermaid:
<script>mermaid.initialize({startOnLoad:true});
</script>
```
**Doing so will command the mermaid parser to look for the `<div>` tags with `class="mermaid"`. From these tags mermaid will try to read the diagram/chart definitions and render them into svg charts.**
**Doing so will command the mermaid parser to look for the `<div>` tags with `class="mermaid"`. From these tags mermaid will try to read the diagram/chart definitions and render them into SVG charts.**
**Examples can be found at** [Other examples](/examples)
@@ -277,9 +277,9 @@ Detailed information about how to contribute can be found in the [contribution g
## Security and safe diagrams
For public sites, it can be precarious to retrieve text from users on the internet, storing that content for presentation in a browser at a later stage. The reason is that the user content can contain embedded malicious scripts that will run when the data is presented. For Mermaid this is a risk, specially as mermaid diagrams contain many characters that are used in html which makes the standard sanitation unusable as it also breaks the diagrams. We still make an effort to sanitise the incoming code and keep refining the process but it is hard to guarantee that there are no loop holes.
For public sites, it can be precarious to retrieve text from users on the internet, storing that content for presentation in a browser at a later stage. The reason is that the user content can contain embedded malicious scripts that will run when the data is presented. For Mermaid this is a risk, specially as mermaid diagrams contain many characters that are used in html which makes the standard sanitation unusable as it also breaks the diagrams. We still make an effort to sanitise the incoming code and keep refining the process but it is hard to guarantee that there are no loop holes.
As an extra level of security for sites with external users we are happy to introduce a new security level in which the diagram is rendered in a sandboxed iframe preventing javascript in the code from being executed. This is a great step forward for better security.
As an extra level of security for sites with external users we are happy to introduce a new security level in which the diagram is rendered in a sandboxed iframe preventing JavaScript in the code from being executed. This is a great step forward for better security.
*Unfortunately you can not have a cake and eat it at the same time which in this case means that some of the interactive functionality gets blocked along with the possible malicious code.*

View File

@@ -818,13 +818,13 @@ Default value: 'TB'
### entityPadding
| Parameter | Description | Type | Required | Values |
| ------------- | ----------------------------------------------------------- | ------- | -------- | ------------------ |
| entityPadding | Minimum internal padding betweentext in box and box borders | Integer | 4 | Any Positive Value |
| Parameter | Description | Type | Required | Values |
| ------------- | ------------------------------------------------------------ | ------- | -------- | ------------------ |
| entityPadding | Minimum internal padding between text in box and box borders | Integer | 4 | Any Positive Value |
**Notes:**
The minimum internal padding betweentext in an entity box and the enclosing box borders,
The minimum internal padding between text in an entity box and the enclosing box borders,
expressed in pixels.
Default value: 15
@@ -902,6 +902,81 @@ available space. If set to false, the diagram reserves its absolute width.
Default value: true
## c4
The object containing configurations specific for c4 diagrams
### diagramMarginX
| Parameter | Description | Type | Required | Values |
| -------------- | ---------------------------------------------- | ------- | -------- | ------------------ |
| diagramMarginX | Margin to the right and left of the c4 diagram | Integer | Required | Any Positive Value |
**Notes:** Default value: 50
### diagramMarginY
| Parameter | Description | Type | Required | Values |
| -------------- | ------------------------------------------- | ------- | -------- | ------------------ |
| diagramMarginY | Margin to the over and under the c4 diagram | Integer | Required | Any Positive Value |
**Notes:** Default value: 10
### c4ShapeMargin
| Parameter | Description | Type | Required | Values |
| ----------- | --------------------- | ------- | -------- | ------------------ |
| shapeMargin | Margin between shapes | Integer | Required | Any Positive Value |
**Notes:** Default value: 50
### width
| Parameter | Description | Type | Required | Values |
| --------- | --------------------- | ------- | -------- | ------------------ |
| width | Width of person boxes | Integer | Required | Any Positive Value |
**Notes:** Default value: 216
### height
| Parameter | Description | Type | Required | Values |
| --------- | ---------------------- | ------- | -------- | ------------------ |
| height | Height of person boxes | Integer | Required | Any Positive Value |
**Notes:** Default value: 60
### boxMargin
| Parameter | Description | Type | Required | Values |
| --------- | ------------------------ | ------- | -------- | ------------------ |
| boxMargin | Margin around loop boxes | Integer | Required | Any Positive Value |
**Notes:** Default value: 10
### useMaxWidth
| Parameter | Description | Type | Required | Values |
| ----------- | ----------- | ------- | -------- | ----------- |
| useMaxWidth | See Notes | boolean | Required | true, false |
**Notes:** When this flag is set to true, the height and width is set to 100% and is then
scaling with the available space. If set to false, the absolute space required is used.
Default value: true
### wrap
This sets the auto-wrap state for the diagram
**Notes:** Default value: true.
### wrapPadding
This sets the auto-wrap padding for the diagram (sides only)
**Notes:** Default value: 0.
## setSiteConfig
## setSiteConfig
@@ -1004,9 +1079,9 @@ Pushes in a directive to the configuration
## conf
| Parameter | Description | Type | Required | Values |
| --------- | ------------------------------------------------------------- | ---------- | -------- | -------------------------------------------- |
| conf | base set of values, which currentConfig coul be **reset** to. | Dictionary | Required | Any Values, with respect to the secure Array |
| Parameter | Description | Type | Required | Values |
| --------- | -------------------------------------------------------------- | ---------- | -------- | -------------------------------------------- |
| conf | base set of values, which currentConfig could be **reset** to. | Dictionary | Required | Any Values, with respect to the secure Array |
**Notes**: (default: current siteConfig ) (optional, default `getSiteConfig()`)

View File

@@ -15,6 +15,7 @@
- [Pie Chart](pie.md)
- [Requirement Diagram](requirementDiagram.md)
- [Gitgraph (Git) Diagram 🔥](gitgraph.md)
- [C4C Diagram (Context) Diagram 🦺⚠️](c4c.md)
- [Other Examples](examples.md)
- ⚙️ Deployment and Configuration

46
docs/c4c.md Normal file
View File

@@ -0,0 +1,46 @@
# C4C Diagrams
**Edit this Page** [![N|Solid](img/GitHub-Mark-32px.png)](https://github.com/mermaid-js/mermaid/blob/develop/docs/gitgraph.md)
> C4 Diagram: This is an experimental diagram for now. The syntax and properties can change in future releases. Proper documentation will be provided when the syntax is stable.
Mermaid's c4 diagram sytax is compatible with plantUML. See example below:
```mermaid-example
C4Context
title System Context diagram for Internet Banking System
Person(customerA, "Banking Customer A", "A customer of the bank, with personal bank accounts.")
Person(customerB, "Banking Customer B")
Person_Ext(customerC, "Banking Customer C")
System(SystemAA, "Internet Banking System", "Allows customers to view information about their bank accounts, and make payments.")
Person(customerD, "Banking Customer D", "A customer of the bank, <br/> with personal bank accounts.")
Enterprise_Boundary(b1, "BankBoundary") {
SystemDb_Ext(SystemE, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")
System_Boundary(b2, "BankBoundary2") {
System(SystemA, "Banking System A")
System(SystemB, "Banking System B", "A system of the bank, with personal bank accounts.")
}
System_Ext(SystemC, "E-mail system", "The internal Microsoft Exchange e-mail system.")
SystemDb(SystemD, "Banking System D Database", "A system of the bank, with personal bank accounts.")
Boundary(b3, "BankBoundary3", "boundary") {
SystemQueue(SystemF, "Banking System F Queue", "A system of the bank, with personal bank accounts.")
SystemQueue_Ext(SystemG, "Banking System G Queue", "A system of the bank, with personal bank accounts.")
}
}
BiRel(customerA, SystemAA, "Uses")
BiRel(SystemAA, SystemE, "Uses")
Rel(SystemAA, SystemC, "Sends e-mails", "SMTP")
Rel(SystemC, customerA, "Sends e-mails to")
```

View File

@@ -8,28 +8,27 @@ The class diagram is the main building block of object-oriented modeling. It is
Mermaid can render class diagrams.
```mermaid-example
classDiagram
Animal <|-- Duck
Animal <|-- Fish
Animal <|-- Zebra
Animal : +int age
Animal : +String gender
Animal: +isMammal()
Animal: +mate()
class Duck{
+String beakColor
+swim()
+quack()
}
class Fish{
-int sizeInFeet
-canEat()
}
class Zebra{
+bool is_wild
+run()
}
classDiagram
Animal <|-- Duck
Animal <|-- Fish
Animal <|-- Zebra
Animal : +int age
Animal : +String gender
Animal: +isMammal()
Animal: +mate()
class Duck{
+String beakColor
+swim()
+quack()
}
class Fish{
-int sizeInFeet
-canEat()
}
class Zebra{
+bool is_wild
+run()
}
```
## Syntax
@@ -79,12 +78,12 @@ There are two ways to define the members of a class, and regardless of whichever
- Associate a member of a class using **:** (colon) followed by member name, useful to define one member at a time. For example:
```mermaid-example
classDiagram
class BankAccount
BankAccount : +String owner
BankAccount : +BigDecimal balance
BankAccount : +deposit(amount)
BankAccount : +withdrawal(amount)
classDiagram
class BankAccount
BankAccount : +String owner
BankAccount : +BigDecimal balance
BankAccount : +deposit(amount)
BankAccount : +withdrawal(amount)
```
- Associate members of a class using **{}** brackets, where members are grouped within curly brackets. Suitable for defining multiple members at once. For example:
@@ -385,9 +384,9 @@ _URL Link:_
```mmd
classDiagram
class Shape
link Shape "http://www.github.com" "This is a tooltip for a link"
link Shape "https://www.github.com" "This is a tooltip for a link"
class Shape2
click Shape2 href "http://www.github.com" "This is a tooltip for a link"
click Shape2 href "https://www.github.com" "This is a tooltip for a link"
```
_Callback:_
@@ -402,10 +401,10 @@ click Shape2 call callbackFunction() "This is a tooltip for a callback"
```html
<script>
var callbackFunction = function(){
alert('A callback was triggered');
}
<script>
var callbackFunction = function () {
alert('A callback was triggered');
};
</script>
```
```mermaid
@@ -413,11 +412,11 @@ classDiagram
class Class01
class Class02
callback Class01 "callbackFunction" "Callback tooltip"
link Class02 "http://www.github.com" "This is a link"
link Class02 "https://www.github.com" "This is a link"
class Class03
class Class04
click Class03 call callbackFunction() "Callback tooltip"
click Class04 href "http://www.github.com" "This is a link"
click Class04 href "https://www.github.com" "This is a link"
```
> **Success** The tooltip functionality and the ability to link to urls are available from version 0.5.2.
@@ -450,18 +449,17 @@ Beginners tip, a full example using interactive links in an html context:
}
callback Duck callback "Tooltip"
link Zebra "http://www.github.com" "This is a link"
link Zebra "https://www.github.com" "This is a link"
</div>
<script>
var callback = function(){
var callback = function () {
alert('A callback was triggered');
}
var config = {
startOnLoad:true,
securityLevel:'loose',
};
var config = {
startOnLoad: true,
securityLevel: 'loose'
};
mermaid.initialize(config);
</script>
</body>

View File

@@ -1,9 +1,9 @@
# Configuration
When mermaid starts configuration is extracted to a configuration to be used for a diagram. There a 3 sources for configuration:
When mermaid starts configuration is extracted to a configuration to be used for a diagram. There are 3 sources for configuration:
* The default configuration
* Overrides on the site level, set is set by the initialize call and will be applied for all diagrams in the site/app. The term for this is the **siteConfig**.
* Overrides on the site level is set by the initialize call and will be applied to all diagrams in the site/app. The term for this is the **siteConfig**.
* Directives - diagram authors can update select configuration parameters directly in the diagram code via directives and these are applied to the render config.
**The render config** is configuration that is used when rendering by applying these configurations.

View File

@@ -1,135 +1,135 @@
# Development and Contribution 🙌
So you want to help? That's great!
![Image of happy people jumping with excitement](https://media.giphy.com/media/BlVnrxJgTGsUw/giphy.gif)
Here are a few things to know to get you started on the right path.
**The Docs Structure is dictated by [sidebar.md](https://github.com/mermaid-js/mermaid/edit/develop/docs/_sidebar.md)**
**Note: Commits and Pull Requests should be directed to the develop branch.**
## Branching
Mermaid uses a [Git Flow](https://guides.github.com/introduction/flow/)inspired approach to branching. So development is done in the `develop` branch.
Once development is done we branch a `release` branch from `develop` for testing.
Once the release happens we merge the `release` branch with `master` and kill the `release` branch.
This means that **you should branch off your pull request from develop** and direct all Pull Requests to it.
## Contributing Code
We make all changes via Pull Requests. As we have many Pull Requests from developers new to mermaid, we have put in place a process, wherein *knsv, Knut Sveidqvist* is the primary reviewer of changes and merging pull requests. The process is as follows:
* Large changes reviewed by knsv or other developer asked to review by knsv
* Smaller, low-risk changes like dependencies, documentation, etc. can be merged by active collaborators
* Documentation (we encourage updates to the docs folder; you can submit them via direct commits)
When you commit code, create a branch with the following naming convention:
Start with the type, such as **feature** or **bug**, followed by the issue number for reference, and a text that describes the issue.
**One example:**
`feature/945_state_diagrams`
**Another example:**
`bug/123_nasty_bug_branch`
## Contributing to Documentation
If it is not in the documentation, it's like it never happened. Wouldn't that be sad? With all the effort that was put into the feature?
The docs are located in the `docs` folder and are written in Markdown. Just pick the right section and start typing. If you want to propose changes to the structure of the documentation, such as adding a new section or a new file you do that via the **[sidebar](https://github.com/mermaid-js/mermaid/edit/develop/docs/_sidebar.md)**.
> **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 committed to the `master` branch are reflected in the [Mermaid Docs](https://mermaid-js.github.io/mermaid/) once released.
## How to Contribute to Documentation
We are a little less strict here, it is OK to commit directly in the `develop` branch if you are a collaborator.
The documentation is located in the `docs` directory and organized according to relevant subfolder.
We encourage contributions to the documentation at [mermaid-js/mermaid/docs](https://github.com/mermaid-js/mermaid/tree/develop/docs). We publish documentation using GitHub Pages with [Docsify](https://www.youtube.com/watch?v=TV88lp7egMw&t=3s)
### Add Unit Tests for Parsing
This is important so that, if someone that does not know about this great feature suggests a change to the grammar, they get notified early on when that change breaks the parser. Another important aspect is that, without proper parsing, tests refactoring is pretty much impossible.
### Add E2E Tests
This tests the rendering and visual apearance of the diagrams. This ensures that the rendering of that feature in the e2e will be reviewed in the release process going forward. Less chance that it breaks!
To start working with the e2e tests:
1. Run `yarn dev` to start the dev server
2. Start **Cypress** by running `cypress open` in the **mermaid** folder.
(Make sure you have path to Cypress in order, the binary is located in `node_modules/.bin`).
The rendering tests are very straightforward to create. There is a function `imgSnapshotTest`, which takes a diagram in text form and the mermaid options, and it renders that diagram in Cypress.
When running in CI it will take a snapshot of the rendered diagram and compare it with the snapshot from last build and flag it for review if it differs.
This is what a rendering test looks like:
```js
it('should render forks and joins', () => {
imgSnapshotTest(
`
stateDiagram
state fork_state &lt;&lt;fork&gt;&gt;
[*] --> fork_state
fork_state --> State2
fork_state --> State3
state join_state &lt;&lt;join&gt;&gt;
State2 --> join_state
State3 --> join_state
join_state --> State4
State4 --> [*]
`,
{ logLevel: 0 }
);
cy.get('svg');
});
```
### Any Questions or Suggestions?
After logging in at [GitHub.com](https://www.github.com), open or append to an issue [using the GitHub issue tracker of the mermaid-js repository](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue+is%3Aopen+label%3A%22Area%3A+Documentation%22).
### How to Contribute a Suggestion
Markdown is used to format the text, for more information about Markdown [see the GitHub Markdown help page](https://help.github.com/en/github/writing-on-github/basic-writing-and-formatting-syntax).
To edit Docs on your computer:
1. Find the Markdown file (.md) to edit in the [mermaid-js/mermaid/docs](https://github.com/mermaid-js/mermaid/tree/develop/docs) directory in the `develop` branch.
2. Create a fork of the develop branch.
3. Make changes or add new documentation.
4. Commit changes to your fork and push it to GitHub.
5. Create a Pull Request of your fork.
To edit Docs on GitHub:
1. Login to [GitHub.com](https://www.github.com).
2. Navigate to [mermaid-js/mermaid/docs](https://github.com/mermaid-js/mermaid/tree/develop/docs).
3. To edit a file, click the pencil icon at the top-right of the file contents panel.
4. Describe what you changed in the **Propose file change** section, located at the bottom of the page.
5. Submit your changes by clicking the button **Propose file change** at the bottom (by automatic creation of a fork and a new branch).
6. Create a Pull Request of your newly forked branch by clicking the green **Create Pull Request** button.
## Last Words
Don't get daunted if it is hard in the beginning. We have a great community with only encouraging words. So, if you get stuck, ask for help and hints in the Slack forum. If you want to show off something good, show it off there.
[Join our Slack community if you want closer contact!](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE)
![Image of superhero wishing you good luck](https://media.giphy.com/media/l49JHz7kJvl6MCj3G/giphy.gif)
# Development and Contribution 🙌
So you want to help? That's great!
![Image of happy people jumping with excitement](https://media.giphy.com/media/BlVnrxJgTGsUw/giphy.gif)
Here are a few things to know to get you started on the right path.
**The Docs Structure is dictated by [sidebar.md](https://github.com/mermaid-js/mermaid/edit/develop/docs/_sidebar.md)**
**Note: Commits and Pull Requests should be directed to the develop branch.**
## Branching
Mermaid uses a [Git Flow](https://guides.github.com/introduction/flow/)inspired approach to branching. So development is done in the `develop` branch.
Once development is done we branch a `release` branch from `develop` for testing.
Once the release happens we merge the `release` branch with `master` and kill the `release` branch.
This means that **you should branch off your pull request from develop** and direct all Pull Requests to it.
## Contributing Code
We make all changes via Pull Requests. As we have many Pull Requests from developers new to mermaid, we have put in place a process, wherein *knsv, Knut Sveidqvist* is the primary reviewer of changes and merging pull requests. The process is as follows:
* Large changes reviewed by knsv or other developer asked to review by knsv
* Smaller, low-risk changes like dependencies, documentation, etc. can be merged by active collaborators
* Documentation (we encourage updates to the docs folder; you can submit them via direct commits)
When you commit code, create a branch with the following naming convention:
Start with the type, such as **feature** or **bug**, followed by the issue number for reference, and a text that describes the issue.
**One example:**
`feature/945_state_diagrams`
**Another example:**
`bug/123_nasty_bug_branch`
## Contributing to Documentation
If it is not in the documentation, it's like it never happened. Wouldn't that be sad? With all the effort that was put into the feature?
The docs are located in the `docs` folder and are written in Markdown. Just pick the right section and start typing. If you want to propose changes to the structure of the documentation, such as adding a new section or a new file you do that via the **[sidebar](https://github.com/mermaid-js/mermaid/edit/develop/docs/_sidebar.md)**.
> **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 committed to the `master` branch are reflected in the [Mermaid Docs](https://mermaid-js.github.io/mermaid/) once released.
## How to Contribute to Documentation
We are a little less strict here, it is OK to commit directly in the `develop` branch if you are a collaborator.
The documentation is located in the `docs` directory and organized according to relevant subfolder.
We encourage contributions to the documentation at [mermaid-js/mermaid/docs](https://github.com/mermaid-js/mermaid/tree/develop/docs). We publish documentation using GitHub Pages with [Docsify](https://www.youtube.com/watch?v=TV88lp7egMw&t=3s)
### Add Unit Tests for Parsing
This is important so that, if someone that does not know about this great feature suggests a change to the grammar, they get notified early on when that change breaks the parser. Another important aspect is that, without proper parsing, tests refactoring is pretty much impossible.
### Add E2E Tests
This tests the rendering and visual appearance of the diagrams. This ensures that the rendering of that feature in the e2e will be reviewed in the release process going forward. Less chance that it breaks!
To start working with the e2e tests:
1. Run `yarn dev` to start the dev server
2. Start **Cypress** by running `cypress open` in the **mermaid** folder.
(Make sure you have path to Cypress in order, the binary is located in `node_modules/.bin`).
The rendering tests are very straightforward to create. There is a function `imgSnapshotTest`, which takes a diagram in text form and the mermaid options, and it renders that diagram in Cypress.
When running in CI it will take a snapshot of the rendered diagram and compare it with the snapshot from last build and flag it for review if it differs.
This is what a rendering test looks like:
```js
it('should render forks and joins', () => {
imgSnapshotTest(
`
stateDiagram
state fork_state &lt;&lt;fork&gt;&gt;
[*] --> fork_state
fork_state --> State2
fork_state --> State3
state join_state &lt;&lt;join&gt;&gt;
State2 --> join_state
State3 --> join_state
join_state --> State4
State4 --> [*]
`,
{ logLevel: 0 }
);
cy.get('svg');
});
```
### Any Questions or Suggestions?
After logging in at [GitHub.com](https://www.github.com), open or append to an issue [using the GitHub issue tracker of the mermaid-js repository](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue+is%3Aopen+label%3A%22Area%3A+Documentation%22).
### How to Contribute a Suggestion
Markdown is used to format the text, for more information about Markdown [see the GitHub Markdown help page](https://help.github.com/en/github/writing-on-github/basic-writing-and-formatting-syntax).
To edit Docs on your computer:
1. Find the Markdown file (.md) to edit in the [mermaid-js/mermaid/docs](https://github.com/mermaid-js/mermaid/tree/develop/docs) directory in the `develop` branch.
2. Create a fork of the develop branch.
3. Make changes or add new documentation.
4. Commit changes to your fork and push it to GitHub.
5. Create a Pull Request of your fork.
To edit Docs on GitHub:
1. Login to [GitHub.com](https://www.github.com).
2. Navigate to [mermaid-js/mermaid/docs](https://github.com/mermaid-js/mermaid/tree/develop/docs).
3. To edit a file, click the pencil icon at the top-right of the file contents panel.
4. Describe what you changed in the **Propose file change** section, located at the bottom of the page.
5. Submit your changes by clicking the button **Propose file change** at the bottom (by automatic creation of a fork and a new branch).
6. Create a Pull Request of your newly forked branch by clicking the green **Create Pull Request** button.
## Last Words
Don't get daunted if it is hard in the beginning. We have a great community with only encouraging words. So, if you get stuck, ask for help and hints in the Slack forum. If you want to show off something good, show it off there.
[Join our Slack community if you want closer contact!](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE)
![Image of superhero wishing you good luck](https://media.giphy.com/media/l49JHz7kJvl6MCj3G/giphy.gif)

View File

@@ -400,7 +400,7 @@ flowchart TB
## Interaction
It is possible to bind a click event to a node, the click can lead to either a javascript callback or to a link which will be opened in a new browser tab. **Note**: This functionality is disabled when using `securityLevel='strict'` and enabled when using `securityLevel='loose'`.
It is possible to bind a click event to a node, the click can lead to either a JavaScript callback or to a link which will be opened in a new browser tab. **Note**: This functionality is disabled when using `securityLevel='strict'` and enabled when using `securityLevel='loose'`.
```
click nodeId callback
@@ -408,15 +408,15 @@ click nodeId call callback()
```
* nodeId is the id of the node
* callback is the name of a javascript function defined on the page displaying the graph, the function will be called with the nodeId as parameter.
* callback is the name of a JavaScript function defined on the page displaying the graph, the function will be called with the nodeId as parameter.
Examples of tooltip usage below:
```html
<script>
var callback = function(){
alert('A callback was triggered');
}
var callback = function () {
alert('A callback was triggered');
};
</script>
```
@@ -428,9 +428,9 @@ graph LR;
B-->C;
C-->D;
click A callback "Tooltip for a callback"
click B "http://www.github.com" "This is a tooltip for a link"
click B "https://www.github.com" "This is a tooltip for a link"
click A call callback() "Tooltip for a callback"
click B href "http://www.github.com" "This is a tooltip for a link"
click B href "https://www.github.com" "This is a tooltip for a link"
```
> **Success** The tooltip functionality and the ability to link to urls are available from version 0.5.2.
@@ -443,13 +443,14 @@ graph LR;
B-->C;
C-->D;
D-->E;
click A "http://www.github.com" _blank
click B "http://www.github.com" "Open this in a new tab" _blank
click C href "http://www.github.com" _blank
click D href "http://www.github.com" "Open this in a new tab" _blank
click A "https://www.github.com" _blank
click B "https://www.github.com" "Open this in a new tab" _blank
click C href "https://www.github.com" _blank
click D href "https://www.github.com" "Open this in a new tab" _blank
```
Beginners tip, a full example using interactive links in a html context:
```html
<body>
<div class="mermaid">
@@ -458,25 +459,24 @@ Beginners tip, a full example using interactive links in a html context:
B-->C;
C-->D;
click A callback "Tooltip"
click B "http://www.github.com" "This is a link"
click B "https://www.github.com" "This is a link"
click C call callback() "Tooltip"
click D href "http://www.github.com" "This is a link"
click D href "https://www.github.com" "This is a link"
</div>
<script>
var callback = function(){
var callback = function () {
alert('A callback was triggered');
}
var config = {
startOnLoad:true,
flowchart:{
useMaxWidth:true,
htmlLabels:true,
curve:'cardinal',
},
securityLevel:'loose',
};
var config = {
startOnLoad: true,
flowchart: {
useMaxWidth: true,
htmlLabels: true,
curve: 'cardinal'
},
securityLevel: 'loose'
};
mermaid.initialize(config);
</script>
</body>
@@ -578,14 +578,12 @@ below:
**Example style**
```html
<style>
.cssClass > rect{
fill:#FF0000;
stroke:#FFFF00;
stroke-width:4px;
}
</style>
```css
.cssClass > rect {
fill: #FF0000;
stroke: #FFFF00;
stroke-width: 4px;
}
```
**Example definition**
@@ -649,6 +647,6 @@ mermaid.flowchartConfig can be set to a JSON string with config parameters or th
```javascript
mermaid.flowchartConfig = {
width: 100%
width: '100%'
}
```

View File

@@ -5,9 +5,9 @@
## Directives
Directives gives a diagram author the capability to alter the appearance of a diagram before rendering by changing the applied configuration.
The significance of having directives is that you have them available while writing the diagram, and can modify the defualt global and diagram specific configurations. So, directives are applied on top of the default configurations. The beauty of directives is that you can use them to alter configuration settings for a specific diagram, i.e. at an individual level.
The significance of having directives is that you have them available while writing the diagram, and can modify the default global and diagram specific configurations. So, directives are applied on top of the default configurations. The beauty of directives is that you can use them to alter configuration settings for a specific diagram, i.e. at an individual level.
While directives allow you to change most of the default configuation settings, there are some that are not available, that too for security reasons. Also, you do have the *option to define the set of configurations* that you would allow to be available to the diagram author for overriding with help of directives.
While directives allow you to change most of the default configuration settings, there are some that are not available, that too for security reasons. Also, you do have the *option to define the set of configurations* that you would allow to be available to the diagram author for overriding with help of directives.
## Types of Directives options
Mermaid basically supports two types of configuration options to be overridden by directives.
@@ -21,7 +21,7 @@ Mermaid basically supports two types of configuration options to be overridden b
2) *Diagram specific configurations* : These are the configurations that are available and applied to a specific diagram. For each diagram there are specific configuration that will alter how that particular diagram looks and behaves.
For example, `mirrroActors` is a configuration that is specific to the `SequenceDiagram` and alter whether the actors are mirrored or not. So this config is available only for the `SequenceDiagram` type.
For example, `mirrorActors` is a configuration that is specific to the `SequenceDiagram` and alter whether the actors are mirrored or not. So this config is available only for the `SequenceDiagram` type.
**NOTE:** These options listed here are not all the configuration options. To get hold of all the configuration options, please refer to the [defaultConfig.js](https://github.com/mermaid-js/mermaid/blob/develop/src/defaultConfig.js) in the source code.
```
@@ -173,7 +173,7 @@ Some common flowchart configurations are:
- *useMaxWidth*: number
For complete list of flowchart configurations, see [defaultConfig.js](https://github.com/mermaid-js/mermaid/blob/develop/src/defaultConfig.js) in the source code.
*Soon we plan to publis a complete list all diagram specific configurations updated in the docs*
*Soon we plan to publish a complete list all diagram specific configurations updated in the docs*
The following code snippet changes flowchart config:
@@ -196,15 +196,15 @@ A --> C[End]
Some common sequence configurations are:
- *width*: number
- *height*: number
- *messgageAlign*: left, center, right
- *messageAlign*: left, center, right
- *mirrorActors*: boolean
- *useMaxWidth*: boolean
- *rightAngles*: boolean
- *showSequenceNumbers*: boolean
- *wrap*: boolean
For complete list of sequeue diagram configurations, see *defaultConfig.js* in the source code.
*Soon we plan to publis a complete list all diagram specific configurations updated in the docs*
For complete list of sequence diagram configurations, see *defaultConfig.js* in the source code.
*Soon we plan to publish a complete list all diagram specific configurations updated in the docs*
So, `wrap` by default has a value of `false` for sequence diagrams.
@@ -214,12 +214,12 @@ Let us see an example:
sequenceDiagram
Alice->Bob: Hello Bob, how are you?
Bob->Alice: Fine, How did you mother like the book I suggested? And did you catch with the new book about alien invansion?
Bob->Alice: Fine, How did you mother like the book I suggested? And did you catch with the new book about alien invasion?
Alice->Bob: Good.
Bob->Alice: Cool
```
Now let us enble wrap for sequence diagrams.
Now let us enable wrap for sequence diagrams.
The following code snippet changes sequence diagram config for `wrap` to `true`:
@@ -232,7 +232,7 @@ Using in the diagram above, the wrap will be enabled.
%%{init: { "sequence": { "wrap": true, "width":300 } } }%%
sequenceDiagram
Alice->Bob: Hello Bob, how are you?
Bob->Alice: Fine, How did you mother like the book I suggested? And did you catch with the new book about alien invansion?
Bob->Alice: Fine, How did you mother like the book I suggested? And did you catch with the new book about alien invasion?
Alice->Bob: Good.
Bob->Alice: Cool
```

View File

@@ -435,9 +435,9 @@ Examples of tooltip usage below:
```html
<script>
var callback = function(){
var callback = function () {
alert('A callback was triggered');
}
};
</script>
```
@@ -449,9 +449,9 @@ flowchart LR
B-->C
C-->D
click A callback "Tooltip for a callback"
click B "http://www.github.com" "This is a tooltip for a link"
click B "https://www.github.com" "This is a tooltip for a link"
click A call callback() "Tooltip for a callback"
click B href "http://www.github.com" "This is a tooltip for a link"
click B href "https://www.github.com" "This is a tooltip for a link"
```
> **Success** The tooltip functionality and the ability to link to urls are available from version 0.5.2.
@@ -465,10 +465,10 @@ flowchart LR
B-->C
C-->D
D-->E
click A "http://www.github.com" _blank
click B "http://www.github.com" "Open this in a new tab" _blank
click C href "http://www.github.com" _blank
click D href "http://www.github.com" "Open this in a new tab" _blank
click A "https://www.github.com" _blank
click B "https://www.github.com" "Open this in a new tab" _blank
click C href "https://www.github.com" _blank
click D href "https://www.github.com" "Open this in a new tab" _blank
```
Beginners tip, a full example using interactive links in a html context:
@@ -480,25 +480,20 @@ Beginners tip, a full example using interactive links in a html context:
B-->C
C-->D
click A callback "Tooltip"
click B "http://www.github.com" "This is a link"
click B "https://www.github.com" "This is a link"
click C call callback() "Tooltip"
click D href "http://www.github.com" "This is a link"
click D href "https://www.github.com" "This is a link"
</div>
<script>
var callback = function(){
var callback = function () {
alert('A callback was triggered');
}
var config = {
startOnLoad:true,
flowchart:{
useMaxWidth:true,
htmlLabels:true,
curve:'cardinal',
},
securityLevel:'loose',
};
var config = {
startOnLoad: true,
flowchart: { useMaxWidth: true, htmlLabels: true, curve: 'cardinal' },
securityLevel:'loose'
};
mermaid.initialize(config);
</script>
</body>
@@ -520,8 +515,8 @@ flowchart LR
It is possible to style links. For instance you might want to style a link that is going backwards in the flow. As links
have no ids in the same way as nodes, some other way of deciding what style the links should be attached to is required.
Instead of ids, the order number of when the link was defined in the graph is used. In the example below the style
defined in the linkStyle statement will belong to the fourth link in the graph:
Instead of ids, the order number of when the link was defined in the graph is used, or use default to apply to all links.
In the example below the style defined in the linkStyle statement will belong to the fourth link in the graph:
```
linkStyle 3 stroke:#ff3,stroke-width:4px,color:red;

View File

@@ -28,6 +28,7 @@ gantt
Task in sec :2014-01-12 , 12d
another task : 24d
```
## Syntax
```mermaid-example
@@ -64,6 +65,7 @@ gantt
```
It is possible to set multiple dependencies separated by space:
```mermaid-example
gantt
apple :a, 2017-07-20, 1w
@@ -82,10 +84,9 @@ You can divide the chart into various sections, for example to separate differen
To do so, start a line with the `section` keyword and give it a name. (Note that unlike with the [title for the entire chart](#title), this name is *required*.
### Milestones
You can add milestones to the diagrams. Milestones differ from tasks as they represent a single instant in time and are identified by the keyword `milestone`. Below is an example on how to use milestones. As you may notice, the exact location of the milestone is determined by the initial date for the milestone and the "duration" of the task this way: *initial date*+*duration*/2.
You can add milestones to the diagrams. Milestones differ from tasks as they represent a single instant in time and are identified by the keyword `milestone`. Below is an example on how to use milestones. As you may notice, the exact location of the milestone is determined by the initial date for the milestone and the "duration" of the task this way: *initial date*+*duration*/2.
```mermaid-example
gantt
@@ -102,7 +103,6 @@ Final milestone : milestone, m2, 18:14, 2min
`dateFormat` defines the format of the date **input** of your gantt elements. How these dates are represented in the rendered chart **output** are defined by `axisFormat`.
### Input date format
The default input date format is `YYYY-MM-DD`. You can define your custom ``dateFormat``.
@@ -136,7 +136,7 @@ SSS 0..999 Thousandths of a second
Z ZZ +12:00 Offset from UTC as +-HH:mm, +-HHmm, or Z
```
More info in: http://momentjs.com/docs/#/parsing/string-format/
More info in: https://momentjs.com/docs/#/parsing/string-format/
### Output date format on the axis

View File

@@ -182,12 +182,43 @@ After this we made use of the `checkout` keyword to set the current branch as `m
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.
### Cherry Pick commit from another branch
Similar to how 'git' allows you to cherry pick a commit from **another branch** onto the **current** branch, Mermaid also suports this functionality. You can also cherry pick a commit from another branch using the `cherry-pick` keyword.
To use the `cherry-pick` keyword, you must specify the id using the `id` attribute, followed by `:` and your desired commit id within `""` quote. For example:
`cherry-pick id: "your_custom_id"`
Here, a new commt representing the cherry pick is created on the current branch, and is visually highlighted in the diagram with a **cherry** and a tag depicting the commit id from which it is cherry picked from.
Few Important rules to note here are:
1. You need to provide the `id` for an existing commit to be cherry picked. If given commit id does not exist it will result in an error. For this make use of the `commit id:$value` format of declaring commits. See the examples from above.
2. The given commit must not exist on the current branch. Cherry picked commit must always be a different branch than the current branch.
3. Current branch must have atleast one commit, before you can cherry pick a commit, otherwise it will case an error is throw.
Let see an example:
```mermaid-example
gitGraph
commit id: "ZERO"
branch develop
commit id:"A"
checkout main
commit id:"ONE"
checkout develop
commit id:"B"
checkout main
commit id:"TWO"
cherry-pick id:"A"
commit id:"THREE"
checkout develop
commit id:"C"
```
## Gitgraph specific configuration options
In Mermaid, you have the option to configure the gitgraph diagram. You can configure the following options:
- `showBranches` : Boolean, default is `true`. If set to `false`, the branches are not shown in the diagram.
- `showCommitLabel` : Boolean, default is `true`. If set to `false`, the commit labels are not shown in the diagram.
- `mainBranchName` : String, default is `main`. The name of the default/root branch.
- `mainBranchOrder` : Position of the main branch in the list of branches. default is `0`, meanig, by default `main` branch is the first in the order.
- `mainBranchOrder` : Position of the main branch in the list of branches. default is `0`, meaning, by default `main` branch is the first in the order.
Let's look at them one by one.
## Hiding Branch names and lines
@@ -240,6 +271,55 @@ Usage example:
merge release
```
## Commit labels Layout: Rotated or Horizontal
Mermaid supports two types of commit labels layout. The default layout is **rotated**, which means the labels are placed below the commit circle, rotated at 45 degress for better readability. This is particularly useful for commits with long labels.
The other option is **horizontal**, which means the labels are placed below the commit circle centred horizontally, and are not rotated. This is particularly useful for commits with short labels.
You can change the layout of the commit labels by using the `rotateCommitLabel` keyword in the directive. It defaults to `true`, which means the commit labels are rotated.
Usage example: Rotated commit labels
```mermaid-example
%%{init: { 'logLevel': 'debug', 'theme': 'base', 'gitGraph': {'rotateCommitLabel': true}} }%%
gitGraph
commit id: "feat(api): ..."
commit id: "a"
commit id: "b"
commit id: "fix(client): .extra long label.."
branch c2
commit id: "feat(modules): ..."
commit id: "test(client): ..."
checkout main
commit id: "fix(api): ..."
commit id: "ci: ..."
branch b1
commit
branch b2
commit
```
Usage example: Horizontal commit labels
```mermaid-example
%%{init: { 'logLevel': 'debug', 'theme': 'base', 'gitGraph': {'rotateCommitLabel': false}} }%%
gitGraph
commit id: "feat(api): ..."
commit id: "a"
commit id: "b"
commit id: "fix(client): .extra long label.."
branch c2
commit id: "feat(modules): ..."
commit id: "test(client): ..."
checkout main
commit id: "fix(api): ..."
commit id: "ci: ..."
branch b1
commit
branch b2
commit
```
## Hiding commit labels
Sometimes you may want to hide the commit labels from the diagram. You can do this by using the `showCommitLabel` keyword. By default its value is `true`. You can set it to `false` using directives.
@@ -321,11 +401,11 @@ Usage example:
Look at the imaginary railroad map created using Mermaid. Here, we have changed the default main branch name to `MetroLine1`.
## Customizing branch ordering
In Mermaid, by default the branches are shown in the order of their defintion or appearance in the diagram code.
In Mermaid, by default the branches are shown in the order of their definition or appearance in the diagram code.
Sometimes you may want to customize the order of the branches. You can do this by using the `order` keyword next the branch definiton. You can set it to a positive number.
Sometimes you may want to customize the order of the branches. You can do this by using the `order` keyword next the branch definition. You can set it to a positive number.
Mermaid follows the given precendence order of the `order` keyword.
Mermaid follows the given precedence order of the `order` keyword.
- Main branch is always shown first as it has default order value of `0`. (unless its order is modified and changed from `0` using the `mainBranchOrder` keyword in the config)
- Next, All branches without an `order` are shown in the order of their appearance in the diagram code.
- Next, All branches with an `order` are shown in the order of their `order` value.
@@ -357,11 +437,11 @@ Usage example:
```
Look at the diagram, here, all the branches without a specified order are drawn in their order of definition.
Then, `test4` branch is drawn becuase the order of `1`.
Then, `main` branch is drawn becuase the order of `2`.
And, lastly `test1`is drawn becuase the order of `3`.
Then, `test4` branch is drawn because the order of `1`.
Then, `main` branch is drawn because the order of `2`.
And, lastly `test1`is drawn because the order of `3`.
NOTE: Becuase we have overriden the `mainBranchOrder` to `2`, the `main` branch is not drawn in the begining, instead follows the ordering.
NOTE: Because we have overridden the `mainBranchOrder` to `2`, the `main` branch is not drawn in the beginning, instead follows the ordering.
@@ -640,7 +720,9 @@ See how the default theme is used to set the colors for the branches:
branch featureA
commit
```
> #### IMPORTANT:
> Mermaid supports the theme variables to override the default values for **up to 8 branches**, i.e., you can set the color/styling of up to 8 branches using theme variables. After this threshold of 8 branches, the theme variables are reused in the cyclic manner, i.e. 9th branch will use the color/styling of 1st branch, or branch at index position '8' will use the color/styling of branch at index position '0'.
*More on this in the next section. See examples on **Customizing branch label colors** below*
### Customizing branch colors
You can customize the branch colors using the `git0` to `git7` theme variables. Mermaid allows you to set the colors for up-to 8 branches, where `git0` variable will drive the value of the first branch, `git1` will drive the value of the second branch and so on.
@@ -685,27 +767,32 @@ Now let's override the default values for the `gitBranchLabel0` to `gitBranchLab
```mermaid-example
%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': {
'gitBranchLabel0': '#ff0000',
'gitBranchLabel1': '#00ff00',
'gitBranchLabel2': '#0000ff'
} } }%%
gitGraph
commit
branch develop
commit tag:"v1.0.0"
commit
checkout main
commit type: HIGHLIGHT
commit
merge develop
commit
branch featureA
commit
'gitBranchLabel0': '#ffffff',
'gitBranchLabel1': '#ffffff',
'gitBranchLabel2': '#ffffff',
'gitBranchLabel3': '#ffffff',
'gitBranchLabel4': '#ffffff',
'gitBranchLabel5': '#ffffff',
'gitBranchLabel6': '#ffffff',
'gitBranchLabel7': '#ffffff',
'gitBranchLabel8': '#ffffff',
'gitBranchLabel9': '#ffffff'
} } }%%
gitGraph
checkout main
branch branch1
branch branch2
branch branch3
branch branch4
branch branch5
branch branch6
branch branch7
branch branch8
branch branch9
checkout branch1
commit
```
See how the branch label colors are changed to the values specified in the theme variables.
Here, you can see that `branch8` and `branch9` colors and the styles are being picked from branch at index position `0` (`main`) and `1`(`branch1`) respectively, i.e., **branch themeVariables are repeated cyclically**.
### Customizing Commit colors
You can customize commit using the `commitLabelColor` and `commitLabelBackground` theme variables for changes in the commit label color and background color respectively.
@@ -787,3 +874,4 @@ See how the highlight commit color on the first branch is changed to the value s

View File

@@ -17,7 +17,7 @@
/>
<!-- <link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css"> -->
<link rel="stylesheet" href="theme.css" />
<script src="//cdn.jsdelivr.net/npm/mermaid@9.1.1/dist/mermaid.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/mermaid@9.1.2/dist/mermaid.min.js"></script>
<!-- <script src="http://localhost:9000/mermaid.js"></script> -->
<script>
// prettier-ignore
@@ -163,5 +163,6 @@
<script src="//cdn.jsdelivr.net/npm/docsify/lib/docsify.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/ga.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-coffeescript.min.js"></script>
</body>
</html>

View File

@@ -17,7 +17,7 @@ They also serve as proof of concept, for the variety of things that can be built
- [Joplin](https://joplinapp.org) (**Native support**)
- [Notion](https://notion.so) (**Native support**)
- [Observable](https://observablehq.com/@observablehq/mermaid) (**Native support**)
- [GitBook](http://gitbook.com)
- [GitBook](https://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)
@@ -33,7 +33,7 @@ They also serve as proof of concept, for the variety of things that can be built
## CRM/ERP/Similar
- [coreBOS](http://blog.corebos.org/blog/december2019)
- [coreBOS](https://blog.corebos.org/blog/december2019)
## Blogs
@@ -104,18 +104,18 @@ They also serve as proof of concept, for the variety of things that can be built
- [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)
- [Astah](https://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)
- [Draw.io](https://draw.io) - [Plugin](https://github.com/nopeslide/drawio_mermaid_plugin)
- [Inkdrop](https://www.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/)
- [Brackets](https://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)

View File

@@ -15,7 +15,7 @@ They also serve as proof of concept, for the variety of things that can be built
- [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)
- [GitBook](https://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)
@@ -30,7 +30,7 @@ They also serve as proof of concept, for the variety of things that can be built
## CRM/ERP/Similar
- [coreBOS](http://blog.corebos.org/blog/december2019)
- [coreBOS](https://blog.corebos.org/blog/december2019)
## Blogs
@@ -101,18 +101,18 @@ They also serve as proof of concept, for the variety of things that can be built
- [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)
- [Astah](https://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)
- [Draw.io](https://draw.io) - [Plugin](https://github.com/nopeslide/drawio_mermaid_plugin)
- [Inkdrop](https://www.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/)
- [Brackets](https://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)

View File

@@ -12,7 +12,7 @@ This section talks about the different ways to deploy Mermaid. Learning the [Syn
1. Using the Mermaid Live Editor at [mermaid.live](https://mermaid.live).
2. Using [mermaid plugins](./integrations.md) with programs you are familiar with.
3. Calling the Mermaid Javascript API.
3. Calling the Mermaid JavaScript API.
4. Deploying Mermaid as a dependency.
**Note: It is our recommendation that you review all approaches, and choose the one that is best for your project.**
@@ -63,7 +63,7 @@ You can generate mermaid diagrams from within popular applications using plug-in
**This is covered in greater detail in the [Usage section](usage.md)**
## 3. Calling the Javascript API
## 3. Calling the JavaScript API
This method can be used with any common web server like Apache, IIS, nginx, node express.

View File

@@ -12,7 +12,6 @@ For instance:
* the flowchart starts with the keyword graph.
* the sequence diagram starts with the keyword sequenceDiagram
#### Store data found during parsing
There are some jison specific sub steps here where the parser stores the data encountered when parsing the diagram, this data is later used by the renderer. You can during the parsing call a object provided to the parser by the user of the parser. This object can be called during parsing for storing data.
@@ -29,7 +28,7 @@ statement
In the extract of the grammar above, it is defined that a call to the setTitle method in the data object will be done when parsing and the title keyword is encountered.
```tip
Make sure that the `parseError` function for the parser is defined and calling `mermaidPAI.parseError`. This way a common way of detecting parse errors is provided for the end-user.
Make sure that the `parseError` function for the parser is defined and calling `mermaid.parseError`. This way a common way of detecting parse errors is provided for the end-user.
```
For more info look in the example diagram type:
@@ -38,7 +37,7 @@ The `yy` object has the following function:
```javascript
exports.parseError = function(err, hash){
mermaidAPI.parseError(err, hash)
mermaid.parseError(err, hash)
};
```
@@ -53,7 +52,7 @@ parser.yy = db
### Step 2: Rendering
Write a renderer that given the data found during parsing renders the diagram. To look at an example look at sequendeRenderer.js rather then the flowchart renderer as this is a more generic example.
Write a renderer that given the data found during parsing renders the diagram. To look at an example look at sequenceRenderer.js rather then the flowchart renderer as this is a more generic example.
Place the renderer in the diagram folder.
@@ -109,4 +108,160 @@ flow.parser.yy = graph
Look at `graphDb.js` for more details on that object.
## Layout
If you are using a dagre based layout, please use flowchart-v2 as a template and by doing that you will be using dagre-wrapper instead of dagreD3 which we are m igrating away from.
### Common parts of a diagram
There are a few features that are common between the different types of diagrams. We try to standardize the diagrams that work as similar as possible for the end user. The commonalities are:
* Directives, a way of modifying the diagram configuration from within the diagram code.
* Accessibility, a way for an author to provide additional information like titles and descriptions to people accessing a text with diagrams using a screen reader.
* Themes, there is a common way to modify the styling of diagrams in Mermaid.
* Comments should follow mermaid standards
Here some pointers on how to handle these different areas.
#### [Directives](./directives.md)
Here is example handling from flowcharts:
Jison:
```jison
/* lexial grammar */
%lex
%x open_directive
%x type_directive
%x arg_directive
%x close_directive
\%\%\{ { 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';
/* language grammar */
/* ... */
directive
: openDirective typeDirective closeDirective separator
| openDirective typeDirective ':' argDirective closeDirective separator
;
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', 'flowchart'); }
;
```
It is probably a good idea to keep the handling similar to this in your new diagram. The parseDirective function is provided by the mermaidAPI.
## Accessibility
The syntax for adding title and description looks like this:
```
accTitle: The title
accDescr: The dsscription
accDescr {
Syntax for a description text
written on multiple lines.
}
```
In a similar way to the directives the jison syntax are quite similar between the diagrams.
```jison
* lexical grammar */
%lex
%x acc_title
%x acc_descr
%x acc_descr_multiline
%%
accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; }
<acc_title>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; }
accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; }
<acc_descr>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_descr_value"; }
accDescr\s*"{"\s* { this.begin("acc_descr_multiline");}
<acc_descr_multiline>[\}] { this.popState(); }
<acc_descr_multiline>[^\}]* return "acc_descr_multiline_value";
statement
: acc_title acc_title_value { $$=$2.trim();yy.setTitle($$); }
| acc_descr acc_descr_value { $$=$2.trim();yy.setAccDescription($$); }
| acc_descr_multiline_value { $$=$1.trim();yy.setAccDescription($$); }
```
The functions for setting title and description are provided by a common module. This is the import from flowDb.js:
```
import {
setAccTitle,
getAccTitle,
getAccDescription,
setAccDescription,
clear as commonClear,
} from '../../commonDb';
```
For rendering the accessibility tags you have again an existing function you can use.
**In the renderer:**
```js
import addSVGAccessibilityFields from '../../accessibility';
/* ... */
// Adds title and description to the flow chart
addSVGAccessibilityFields(parser.yy, svg, id);
```
## Theming
Mermaid supports themes and has an integrated theming engine. You can read more about how the themes can be used [in the docs](./theming.md).
When adding themes to a diagram it comes down to a few important locations in the code.
The entry point for the styling engine is in **src/styles.js**. The getStyles function will be called by Mermaid when the styles are being applied to the diagram.
This function will in turn call a function *your diagram should provide* returning the css for the new diagram. The diagram specific, also which is commonly also called getStyles and located in the folder for your diagram under src/diagrams and should be named styles.js. The getStyles function will be called with the theme options as an argument like in the following example:
```js
const getStyles = (options) =>
`
.line {
stroke-width: 1;
stroke: ${options.lineColor};
stroke-dasharray: 2;
}
// ...
```
Note that you need to provide your function to the main getStyles by adding it into the themes object in **src/styles.js** like in the xyzDiagram in the provided example:
```js
const themes = {
flowchart,
'flowchart-v2': flowchart,
sequence,
xyzDiagram
//...
```
The actual options and values for the colors are defined in **src/theme/theme-[xyz].js**. If you provide the options your diagram needs in the existing theme files then the theming will work smoothly without hiccups.

View File

@@ -1,7 +1,5 @@
# Requirement Diagram
**Edit this Page** [![N|Solid](img/GitHub-Mark-32px.png)](https://github.com/mermaid-js/mermaid/blob/develop/docs/requirementDiagram.md)
> A Requirement diagram provides a visualization for requirements and their connections, to each other and other documented elements. The modeling specs follow those defined by SysML v1.6.
Rendering requirements is straightforward.

View File

@@ -230,6 +230,70 @@ sequenceDiagram
end
```
## Critical Region
It is possible to show actions that must happen automatically with conditional handling of circumstances.
This is done by the notation
```
critical [Action that must be performed]
... statements ...
option [Circumstance A]
... statements ...
option [Circumstance B]
... statements ...
end
```
See the example below:
```mermaid-example
sequenceDiagram
critical Establish a connection to the DB
Service-->DB: connect
option Network timeout
Service-->Service: Log error
option Credentials rejected
Service-->Service: Log different error
end
```
It is also possible to have no options at all
```mermaid-example
sequenceDiagram
critical Establish a connection to the DB
Service-->DB: connect
end
```
This critical block can also be nested, equivalently to the `par` statement as seen above.
## Break
It is possible to indicate a stop of the sequence within the flow (usually used to model exceptions).
This is done by the notation
```
break [something happened]
... statements ...
end
```
See the example below:
```mermaid-example
sequenceDiagram
Consumer-->API: Book something
API-->BookingService: Start booking process
break when the booking process fails
API-->Consumer: show failure
end
API-->BillingService: Start billing process
```
## Background Highlighting
It is possible to highlight flows by providing colored background rects. This is done by the notation

View File

@@ -9,16 +9,16 @@ The theme can be altered by changing the root level variable `theme` variable in
Themes follow and build upon the Levels of Configuration, and employ `directives` to modify and create custom configurations, as they were introduced in Version [8.6.0](./8.6.0_docs.md).
## Deployable Themes
The following are a list of **Deployable themes**, sample `%%init%%` directives and `initialize` calls.
1. **Base**- Designed to modified, as the name implies it is supposed to be used as the base for making custom themes.
The following are a list of **Deployable themes**, sample `%%init%%` directives and `initialize` calls.
1. **base**- Designed to be modified, as the name implies it is supposed to be used as the base for making custom themes.
2. **Forest**- A theme full of light greens that is easy on the eyes.
2. **forest**- A theme full of light greens that is easy on the eyes.
3. **Dark**- A theme that would go well with other dark colored elements.
3. **dark**- A theme that would go well with other dark-colored elements.
4. **Default**- The default theme for all diagrams.
4. **default**- The default theme for all diagrams.
5. **Neutral**- The theme to be used for black and white printing
5. **neutral**- The theme to be used for black and white printing.
## Site-wide Themes
@@ -116,15 +116,15 @@ Variables that are unique to some diagrams can be affected by changes in Theme V
| -------------------- | ------------------------------ | ---- | -------------------------------------------------------------------------------------------------------------------------------- |
| darkMode | false | | Boolean Value that dictates how to calculate colors. "true" will activate darkmode. |
| background | #f4f4f4 | | Used to calculate color for items that should either be background colored or contrasting to the background. |
| primaryColor | #fff4dd | | Color to be used as background in nodes, other colors will be derived from this |
| fontFamily | "trebuchet ms", verdana, arial | | |
| fontSize | 16px | | Font Size, in pixels |
| secondaryColor | based on primaryColor | * | |
| tertiaryColor | based on primaryColor | * | |
| primaryColor | #fff4dd | | Color to be used as background in nodes, other colors will be derived from this |
| primaryBorderColor | based on primaryColor | * | Color to be used as border in nodes using primaryColor |
| primaryTextColor | based on darkMode #ddd/#333 | * | Color to be used as text color in nodes using primaryColor |
| primaryTextColor | based on darkMode #ddd/#333 | * | Color to be used as text color in nodes using primaryColor
| secondaryColor | based on primaryColor | * | |
| secondaryBorderColor | based on secondaryColor | * | Color to be used as border in nodes using secondaryColor |
| secondaryTextColor | based on secondaryColor | * | Color to be used as text color in nodes using secondaryColor |
| secondaryTextColor | based on secondaryColor | * | Color to be used as text color in nodes using secondaryColor
| tertiaryColor | based on primaryColor | * | | | |
| tertiaryBorderColor | based on tertiaryColor | * | Color to be used as border in nodes using tertiaryColor |
| tertiaryTextColor | based on tertiaryColor | * | Color to be used as text color in nodes using tertiaryColor |
| noteBkgColor | #fff5ad | | Color used as background in notes |
@@ -160,9 +160,9 @@ Variables that are unique to some diagrams can be affected by changes in Theme V
| actorBkg | mainBkg | * | Actor Background Color |
| actorTextColor | primaryTextColor | * | Actor Text Color |
| actorLineColor | grey | * | Actor Line Color |
| labelBoxBkgColor | actorBkg | * | Label Box Background Color |
| signalColor | textColor | * | Signal Color |
| signalTextColor | textColor | * | Signal Text Color |
| labelBoxBkgColor | actorBkg | * | Label Box Background Color |
| labelBoxBorderColor | actorBorder | * | Label Box Border Color |
| labelTextColor | actorTextColor | * | Label Text Color |
| loopTextColor | actorTextColor | * | Loop ext Color |

View File

@@ -2,7 +2,7 @@
**Edit this Page** [![N|Solid](img/GitHub-Mark-32px.png)](https://github.com/mermaid-js/mermaid/blob/develop/docs/usage.md)
Mermaid is a Javascript tool that makes use of a markdown based syntax to render customizable diagrams, charts and visualizations.
Mermaid is a JavaScript tool that makes use of a Markdown based syntax to render customizable diagrams, charts and visualizations.
Diagrams can be re-rendered/modified by modifying their descriptions.
@@ -114,7 +114,7 @@ Values:
- **strict**: (**default**) tags in text are encoded, click functionality is disabled
- **loose**: tags in text are allowed, click functionality is enabled
- **antiscript**: html tags in text are allowed, (only script element is removed), click functionality is enabled
- **sandbox**: With this security level all rendering takes place in a sandboxed iframe. This prevent any javascript running in the context. This may hinder interactive functionality of the diagram like scripts, popups in sequence diagram or links to other tabs/targets etc.
- **sandbox**: With this security level all rendering takes place in a sandboxed iframe. This prevent any JavaScript running in the context. This may hinder interactive functionality of the diagram like scripts, popups in sequence diagram or links to other tabs/targets etc.
```note
@@ -198,10 +198,10 @@ mermaid fully supports webpack. Here is a [working demo](https://github.com/merm
## API usage
The main idea of the API is to be able to call a render function with the graph definition as a string. The render function
will render the graph and call a callback with the resulting svg code. With this approach it is up to the site creator to
will render the graph and call a callback with the resulting SVG code. With this approach it is up to the site creator to
fetch the graph definition from the site (perhaps from a textarea), render it and place the graph somewhere in the site.
The example below show an outline of how this could be used. The example just logs the resulting svg to the javascript console.
The example below show an outline of how this could be used. The example just logs the resulting SVG to the JavaScript console.
```html
<script src="mermaid.js"></script>
@@ -221,7 +221,7 @@ Sometimes the generated graph also has defined interactions like tooltip and cli
add those events after the graph has been inserted into the DOM.
The example code below is an extract of what mermaid does when using the API. The example shows how it is possible to
bind events to an svg when using the API for rendering.
bind events to an SVG when using the API for rendering.
```javascript
var insertSvg = function(svgCode, bindFunctions) {
@@ -240,14 +240,14 @@ mermaidAPI.render(id,txt,insertSvg, element);
1. The graph is generated using the render call.
2. After generation the render function calls the provided callback function, in this case it's called insertSvg.
3. The callback function is called with two parameters, the svg code of the generated graph and a function. This function binds events to the svg **after** it is inserted into the DOM.
4. Insert the svg code into the DOM for presentation.
3. The callback function is called with two parameters, the SVG code of the generated graph and a function. This function binds events to the SVG **after** it is inserted into the DOM.
4. Insert the SVG code into the DOM for presentation.
5. Call the binding function that binds the events.
## Example of a marked renderer
This is the renderer used for transforming the documentation from markdown to html with mermaid diagrams in the html.
This is the renderer used for transforming the documentation from Markdown to html with mermaid diagrams in the html.
```javascript
var renderer = new marked.Renderer();
@@ -261,7 +261,7 @@ renderer.code = function (code, language) {
};
```
Another example in coffeescript that also includes the mermaid script tag in the generated markup.
Another example in CoffeeScript that also includes the mermaid script tag in the generated markup.
```coffee
marked = require 'marked'

1051
flow.js

File diff suppressed because one or more lines are too long

View File

@@ -1,11 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "attach",
"name": "Attach",
"port": 9229
}
]
}

View File

@@ -1,6 +1,6 @@
{
"name": "mermaid",
"version": "9.1.1",
"version": "9.1.2",
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
"main": "dist/mermaid.core.js",
"module": "dist/mermaid.esm.min.mjs",
@@ -27,13 +27,14 @@
"postbuild": "documentation build src/mermaidAPI.js src/config.js src/defaultConfig.js --shallow -f md --markdown-toc false > docs/Setup.md",
"build:watch": "yarn build:development --watch",
"release": "yarn build",
"lint": "eslint ./ --ext js,html",
"lint": "eslint ./ --ext .js,.json,.html",
"lint:fix": "yarn lint --fix",
"e2e:depr": "yarn lint && jest e2e --config e2e/jest.config.js",
"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",
"ci": "jest src/.*",
"test": "yarn lint && jest src/.*",
"test:watch": "jest --watch src",
"prepublishOnly": "yarn build && yarn test",
@@ -61,7 +62,7 @@
"d3": "^7.0.0",
"dagre": "^0.8.5",
"dagre-d3": "^0.6.4",
"dompurify": "2.3.6",
"dompurify": "2.3.8",
"graphlib": "^2.1.8",
"khroma": "^2.0.0",
"moment-mini": "^2.24.0",
@@ -73,31 +74,32 @@
"@babel/eslint-parser": "^7.14.7",
"@babel/preset-env": "^7.14.7",
"@babel/register": "^7.14.5",
"@commitlint/cli": "^16.0.0",
"@commitlint/config-conventional": "^16.0.0",
"@commitlint/cli": "^17.0.0",
"@commitlint/config-conventional": "^17.0.0",
"babel-jest": "^28.0.3",
"babel-loader": "^8.2.2",
"concurrently": "^7.0.0",
"coveralls": "^3.0.2",
"css-to-string-loader": "^0.1.3",
"cypress": "9.6.0",
"cypress": "9.7.0",
"cypress-image-snapshot": "^4.0.1",
"documentation": "13.2.0",
"eslint": "^8.2.0",
"eslint": "^8.4.1",
"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": "^39.1.0",
"eslint-plugin-json": "^3.1.0",
"eslint-plugin-markdown": "^2.2.1",
"eslint-plugin-prettier": "^4.0.0",
"husky": "^7.0.1",
"husky": "^8.0.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^28.0.3",
"jest-environment-jsdom": "^28.0.2",
"jison": "^0.4.18",
"js-base64": "3.7.2",
"lint-staged": "^12.1.2",
"lint-staged": "^13.0.0",
"moment": "^2.23.0",
"path-browserify": "^1.0.1",
"prettier": "^2.3.2",

675
pie.js
View File

@@ -1,675 +0,0 @@
/* parser generated by jison 0.4.18 */
/*
Returns a Parser object of the following structure:
Parser: {
yy: {}
}
Parser.prototype: {
yy: {},
trace: function(),
symbols_: {associative list: name ==> number},
terminals_: {associative list: number ==> name},
productions_: [...],
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),
table: [...],
defaultActions: {...},
parseError: function(str, hash),
parse: function(input),
lexer: {
EOF: 1,
parseError: function(str, hash),
setInput: function(input),
input: function(),
unput: function(str),
more: function(),
less: function(n),
pastInput: function(),
upcomingInput: function(),
showPosition: function(),
test_match: function(regex_match_array, rule_index),
next: function(),
lex: function(),
begin: function(condition),
popState: function(),
_currentRules: function(),
topState: function(),
pushState: function(condition),
options: {
ranges: boolean (optional: true ==> token location info will include a .range[] member)
flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)
backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code)
},
performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),
rules: [...],
conditions: {associative list: name ==> set},
}
}
token location info (@$, _$, etc.): {
first_line: n,
last_line: n,
first_column: n,
last_column: n,
range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based)
}
the parseError function receives a 'hash' object with these members for lexer and parser errors: {
text: (matched text)
token: (the produced terminal token, if any)
line: (yylineno)
}
while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {
loc: (yylloc)
expected: (string describing the set of expected tokens)
recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
}
*/
var pie = (function(){
var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[1,4],$V1=[1,5],$V2=[1,6],$V3=[1,7],$V4=[1,9],$V5=[1,11,13,15,22,23,24,25],$V6=[2,5],$V7=[1,6,11,13,15,22,23,24,25],$V8=[22,23,24],$V9=[2,8],$Va=[1,18],$Vb=[1,19],$Vc=[1,20],$Vd=[1,25],$Ve=[6,22,23,24,25];
var parser = {trace: function trace () { },
yy: {},
symbols_: {"error":2,"start":3,"eol":4,"directive":5,"PIE":6,"document":7,"showData":8,"line":9,"statement":10,"txt":11,"value":12,"title":13,"title_value":14,"accDescription":15,"description_value":16,"openDirective":17,"typeDirective":18,"closeDirective":19,":":20,"argDirective":21,"NEWLINE":22,";":23,"EOF":24,"open_directive":25,"type_directive":26,"arg_directive":27,"close_directive":28,"$accept":0,"$end":1},
terminals_: {2:"error",6:"PIE",8:"showData",11:"txt",12:"value",13:"title",14:"title_value",15:"accDescription",16:"description_value",20:":",22:"NEWLINE",23:";",24:"EOF",25:"open_directive",26:"type_directive",27:"arg_directive",28:"close_directive"},
productions_: [0,[3,2],[3,2],[3,2],[3,3],[7,0],[7,2],[9,2],[10,0],[10,2],[10,2],[10,2],[10,1],[5,3],[5,5],[4,1],[4,1],[4,1],[17,1],[18,1],[21,1],[19,1]],
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
/* this == yyval */
var $0 = $$.length - 1;
switch (yystate) {
case 4:
yy.setShowData(true);
break;
case 7:
this.$ = $$[$0-1]
break;
case 9:
yy.addSection($$[$0-1],yy.cleanupValue($$[$0]));
break;
case 10:
this.$=$$[$0].trim();yy.setTitle(this.$);
break;
case 11:
this.$=$$[$0].trim();yy.setAccDescription(this.$);
break;
case 18:
yy.parseDirective('%%{', 'open_directive');
break;
case 19:
yy.parseDirective($$[$0], 'type_directive');
break;
case 20:
$$[$0] = $$[$0].trim().replace(/'/g, '"'); yy.parseDirective($$[$0], 'arg_directive');
break;
case 21:
yy.parseDirective('}%%', 'close_directive', 'pie');
break;
}
},
table: [{3:1,4:2,5:3,6:$V0,17:8,22:$V1,23:$V2,24:$V3,25:$V4},{1:[3]},{3:10,4:2,5:3,6:$V0,17:8,22:$V1,23:$V2,24:$V3,25:$V4},{3:11,4:2,5:3,6:$V0,17:8,22:$V1,23:$V2,24:$V3,25:$V4},o($V5,$V6,{7:12,8:[1,13]}),o($V7,[2,15]),o($V7,[2,16]),o($V7,[2,17]),{18:14,26:[1,15]},{26:[2,18]},{1:[2,1]},{1:[2,2]},o($V8,$V9,{17:8,9:16,10:17,5:21,1:[2,3],11:$Va,13:$Vb,15:$Vc,25:$V4}),o($V5,$V6,{7:22}),{19:23,20:[1,24],28:$Vd},o([20,28],[2,19]),o($V5,[2,6]),{4:26,22:$V1,23:$V2,24:$V3},{12:[1,27]},{14:[1,28]},{16:[1,29]},o($V8,[2,12]),o($V8,$V9,{17:8,9:16,10:17,5:21,1:[2,4],11:$Va,13:$Vb,15:$Vc,25:$V4}),o($Ve,[2,13]),{21:30,27:[1,31]},o($Ve,[2,21]),o($V5,[2,7]),o($V8,[2,9]),o($V8,[2,10]),o($V8,[2,11]),{19:32,28:$Vd},{28:[2,20]},o($Ve,[2,14])],
defaultActions: {9:[2,18],10:[2,1],11:[2,2],31:[2,20]},
parseError: function parseError (str, hash) {
if (hash.recoverable) {
this.trace(str);
} else {
var error = new Error(str);
error.hash = hash;
throw error;
}
},
parse: function parse(input) {
var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
var args = lstack.slice.call(arguments, 1);
var lexer = Object.create(this.lexer);
var sharedState = { yy: {} };
for (var k in this.yy) {
if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
sharedState.yy[k] = this.yy[k];
}
}
lexer.setInput(input, sharedState.yy);
sharedState.yy.lexer = lexer;
sharedState.yy.parser = this;
if (typeof lexer.yylloc == 'undefined') {
lexer.yylloc = {};
}
var yyloc = lexer.yylloc;
lstack.push(yyloc);
var ranges = lexer.options && lexer.options.ranges;
if (typeof sharedState.yy.parseError === 'function') {
this.parseError = sharedState.yy.parseError;
} else {
this.parseError = Object.getPrototypeOf(this).parseError;
}
function popStack(n) {
stack.length = stack.length - 2 * n;
vstack.length = vstack.length - n;
lstack.length = lstack.length - n;
}
_token_stack:
var lex = function () {
var token;
token = lexer.lex() || EOF;
if (typeof token !== 'number') {
token = self.symbols_[token] || token;
}
return token;
};
var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
while (true) {
state = stack[stack.length - 1];
if (this.defaultActions[state]) {
action = this.defaultActions[state];
} else {
if (symbol === null || typeof symbol == 'undefined') {
symbol = lex();
}
action = table[state] && table[state][symbol];
}
if (typeof action === 'undefined' || !action.length || !action[0]) {
var errStr = '';
expected = [];
for (p in table[state]) {
if (this.terminals_[p] && p > TERROR) {
expected.push('\'' + this.terminals_[p] + '\'');
}
}
if (lexer.showPosition) {
errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
} else {
errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
}
this.parseError(errStr, {
text: lexer.match,
token: this.terminals_[symbol] || symbol,
line: lexer.yylineno,
loc: yyloc,
expected: expected
});
}
if (action[0] instanceof Array && action.length > 1) {
throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
}
switch (action[0]) {
case 1:
stack.push(symbol);
vstack.push(lexer.yytext);
lstack.push(lexer.yylloc);
stack.push(action[1]);
symbol = null;
if (!preErrorSymbol) {
yyleng = lexer.yyleng;
yytext = lexer.yytext;
yylineno = lexer.yylineno;
yyloc = lexer.yylloc;
if (recovering > 0) {
recovering--;
}
} else {
symbol = preErrorSymbol;
preErrorSymbol = null;
}
break;
case 2:
len = this.productions_[action[1]][1];
yyval.$ = vstack[vstack.length - len];
yyval._$ = {
first_line: lstack[lstack.length - (len || 1)].first_line,
last_line: lstack[lstack.length - 1].last_line,
first_column: lstack[lstack.length - (len || 1)].first_column,
last_column: lstack[lstack.length - 1].last_column
};
if (ranges) {
yyval._$.range = [
lstack[lstack.length - (len || 1)].range[0],
lstack[lstack.length - 1].range[1]
];
}
r = this.performAction.apply(yyval, [
yytext,
yyleng,
yylineno,
sharedState.yy,
action[1],
vstack,
lstack
].concat(args));
if (typeof r !== 'undefined') {
return r;
}
if (len) {
stack = stack.slice(0, -1 * len * 2);
vstack = vstack.slice(0, -1 * len);
lstack = lstack.slice(0, -1 * len);
}
stack.push(this.productions_[action[1]][0]);
vstack.push(yyval.$);
lstack.push(yyval._$);
newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
stack.push(newState);
break;
case 3:
return true;
}
}
return true;
}};
/* generated by jison-lex 0.3.4 */
var lexer = (function(){
var lexer = ({
EOF:1,
parseError:function parseError(str, hash) {
if (this.yy.parser) {
this.yy.parser.parseError(str, hash);
} else {
throw new Error(str);
}
},
// resets the lexer, sets new input
setInput:function (input, yy) {
this.yy = yy || this.yy || {};
this._input = input;
this._more = this._backtrack = this.done = false;
this.yylineno = this.yyleng = 0;
this.yytext = this.matched = this.match = '';
this.conditionStack = ['INITIAL'];
this.yylloc = {
first_line: 1,
first_column: 0,
last_line: 1,
last_column: 0
};
if (this.options.ranges) {
this.yylloc.range = [0,0];
}
this.offset = 0;
return this;
},
// consumes and returns one char from the input
input:function () {
var ch = this._input[0];
this.yytext += ch;
this.yyleng++;
this.offset++;
this.match += ch;
this.matched += ch;
var lines = ch.match(/(?:\r\n?|\n).*/g);
if (lines) {
this.yylineno++;
this.yylloc.last_line++;
} else {
this.yylloc.last_column++;
}
if (this.options.ranges) {
this.yylloc.range[1]++;
}
this._input = this._input.slice(1);
return ch;
},
// unshifts one char (or a string) into the input
unput:function (ch) {
var len = ch.length;
var lines = ch.split(/(?:\r\n?|\n)/g);
this._input = ch + this._input;
this.yytext = this.yytext.substr(0, this.yytext.length - len);
//this.yyleng -= len;
this.offset -= len;
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
this.match = this.match.substr(0, this.match.length - 1);
this.matched = this.matched.substr(0, this.matched.length - 1);
if (lines.length - 1) {
this.yylineno -= lines.length - 1;
}
var r = this.yylloc.range;
this.yylloc = {
first_line: this.yylloc.first_line,
last_line: this.yylineno + 1,
first_column: this.yylloc.first_column,
last_column: lines ?
(lines.length === oldLines.length ? this.yylloc.first_column : 0)
+ oldLines[oldLines.length - lines.length].length - lines[0].length :
this.yylloc.first_column - len
};
if (this.options.ranges) {
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
}
this.yyleng = this.yytext.length;
return this;
},
// When called from action, caches matched text and appends it on next action
more:function () {
this._more = true;
return this;
},
// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
reject:function () {
if (this.options.backtrack_lexer) {
this._backtrack = true;
} else {
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
text: "",
token: null,
line: this.yylineno
});
}
return this;
},
// retain first n characters of the match
less:function (n) {
this.unput(this.match.slice(n));
},
// displays already matched input, i.e. for error messages
pastInput:function () {
var past = this.matched.substr(0, this.matched.length - this.match.length);
return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
},
// displays upcoming input, i.e. for error messages
upcomingInput:function () {
var next = this.match;
if (next.length < 20) {
next += this._input.substr(0, 20-next.length);
}
return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
},
// displays the character position where the lexing error occurred, i.e. for error messages
showPosition:function () {
var pre = this.pastInput();
var c = new Array(pre.length + 1).join("-");
return pre + this.upcomingInput() + "\n" + c + "^";
},
// test the lexed token: return FALSE when not a match, otherwise return token
test_match:function(match, indexed_rule) {
var token,
lines,
backup;
if (this.options.backtrack_lexer) {
// save context
backup = {
yylineno: this.yylineno,
yylloc: {
first_line: this.yylloc.first_line,
last_line: this.last_line,
first_column: this.yylloc.first_column,
last_column: this.yylloc.last_column
},
yytext: this.yytext,
match: this.match,
matches: this.matches,
matched: this.matched,
yyleng: this.yyleng,
offset: this.offset,
_more: this._more,
_input: this._input,
yy: this.yy,
conditionStack: this.conditionStack.slice(0),
done: this.done
};
if (this.options.ranges) {
backup.yylloc.range = this.yylloc.range.slice(0);
}
}
lines = match[0].match(/(?:\r\n?|\n).*/g);
if (lines) {
this.yylineno += lines.length;
}
this.yylloc = {
first_line: this.yylloc.last_line,
last_line: this.yylineno + 1,
first_column: this.yylloc.last_column,
last_column: lines ?
lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length :
this.yylloc.last_column + match[0].length
};
this.yytext += match[0];
this.match += match[0];
this.matches = match;
this.yyleng = this.yytext.length;
if (this.options.ranges) {
this.yylloc.range = [this.offset, this.offset += this.yyleng];
}
this._more = false;
this._backtrack = false;
this._input = this._input.slice(match[0].length);
this.matched += match[0];
token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
if (this.done && this._input) {
this.done = false;
}
if (token) {
return token;
} else if (this._backtrack) {
// recover context
for (var k in backup) {
this[k] = backup[k];
}
return false; // rule action called reject() implying the next rule should be tested instead.
}
return false;
},
// return next match in input
next:function () {
if (this.done) {
return this.EOF;
}
if (!this._input) {
this.done = true;
}
var token,
match,
tempMatch,
index;
if (!this._more) {
this.yytext = '';
this.match = '';
}
var rules = this._currentRules();
for (var i = 0; i < rules.length; i++) {
tempMatch = this._input.match(this.rules[rules[i]]);
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
match = tempMatch;
index = i;
if (this.options.backtrack_lexer) {
token = this.test_match(tempMatch, rules[i]);
if (token !== false) {
return token;
} else if (this._backtrack) {
match = false;
continue; // rule action called reject() implying a rule MISmatch.
} else {
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
return false;
}
} else if (!this.options.flex) {
break;
}
}
}
if (match) {
token = this.test_match(match, rules[index]);
if (token !== false) {
return token;
}
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
return false;
}
if (this._input === "") {
return this.EOF;
} else {
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
text: "",
token: null,
line: this.yylineno
});
}
},
// return next match that has a token
lex:function lex () {
var r = this.next();
if (r) {
return r;
} else {
return this.lex();
}
},
// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
begin:function begin (condition) {
this.conditionStack.push(condition);
},
// pop the previously active lexer condition state off the condition stack
popState:function popState () {
var n = this.conditionStack.length - 1;
if (n > 0) {
return this.conditionStack.pop();
} else {
return this.conditionStack[0];
}
},
// produce the lexer rule set which is active for the currently active lexer condition state
_currentRules:function _currentRules () {
if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
} else {
return this.conditions["INITIAL"].rules;
}
},
// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
topState:function topState (n) {
n = this.conditionStack.length - 1 - Math.abs(n || 0);
if (n >= 0) {
return this.conditionStack[n];
} else {
return "INITIAL";
}
},
// alias for begin(condition)
pushState:function pushState (condition) {
this.begin(condition);
},
// return the number of states currently on the stack
stateStackSize:function stateStackSize() {
return this.conditionStack.length;
},
options: {"case-insensitive":true},
performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
var YYSTATE=YY_START;
switch($avoiding_name_collisions) {
case 0: this.begin('open_directive'); return 25;
break;
case 1: this.begin('type_directive'); return 26;
break;
case 2: this.popState(); this.begin('arg_directive'); return 20;
break;
case 3: this.popState(); this.popState(); return 28;
break;
case 4:return 27;
break;
case 5:/* skip comments */
break;
case 6:/* skip comments */{ /*console.log('');*/ }
break;
case 7:return 22;
break;
case 8:/* do nothing */
break;
case 9:/* ignore */
break;
case 10: this.begin("title");return 13;
break;
case 11: this.popState(); return "title_value";
break;
case 12: this.begin("acc_title");return 'acc_title';
break;
case 13: this.popState(); return "acc_title_value";
break;
case 14: this.begin("acc_descr");return 'acc_descr';
break;
case 15: this.popState(); return "acc_descr_value";
break;
case 16: this.begin("acc_descr_multiline");
break;
case 17: this.popState();
break;
case 18:return "acc_descr_multiline_value";
break;
case 19: this.begin("string");
break;
case 20: this.popState();
break;
case 21: return "txt";
break;
case 22:return 6;
break;
case 23:return 8;
break;
case 24:return "value";
break;
case 25:return 24;
break;
}
},
rules: [/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:%%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[\n\r]+)/i,/^(?:%%[^\n]*)/i,/^(?:[\s]+)/i,/^(?:title\b)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:[\}])/i,/^(?:[^\}]*)/i,/^(?:["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:pie\b)/i,/^(?:showData\b)/i,/^(?::[\s]*[\d]+(?:\.[\d]+)?)/i,/^(?:$)/i],
conditions: {"acc_descr_multiline":{"rules":[17,18],"inclusive":false},"acc_descr":{"rules":[15],"inclusive":false},"acc_title":{"rules":[13],"inclusive":false},"close_directive":{"rules":[],"inclusive":false},"arg_directive":{"rules":[3,4],"inclusive":false},"type_directive":{"rules":[2,3],"inclusive":false},"open_directive":{"rules":[1],"inclusive":false},"title":{"rules":[11],"inclusive":false},"string":{"rules":[20,21],"inclusive":false},"INITIAL":{"rules":[0,5,6,7,8,9,10,12,14,16,19,22,23,24,25],"inclusive":true}}
});
return lexer;
})();
parser.lexer = lexer;
function Parser () {
this.yy = {};
}
Parser.prototype = parser;parser.Parser = Parser;
return new Parser;
})();
if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
exports.parser = pie;
exports.Parser = pie.Parser;
exports.parse = function () { return pie.parse.apply(pie, arguments); };
exports.main = function commonjsMain (args) {
if (!args[1]) {
console.log('Usage: '+args[0]+' FILE');
process.exit(1);
}
var source = require('fs').readFileSync(require('path').normalize(args[1]), "utf8");
return exports.parser.parse(source);
};
if (typeof module !== 'undefined' && require.main === module) {
exports.main(process.argv.slice(1));
}
}

View File

@@ -1,3 +1,6 @@
import c4Db from './diagrams/c4/c4Db';
import c4Renderer from './diagrams/c4/c4Renderer';
import c4Parser from './diagrams/c4/parser/c4Diagram';
import classDb from './diagrams/class/classDb';
import classRenderer from './diagrams/class/classRenderer';
import classRendererV2 from './diagrams/class/classRenderer-v2';
@@ -49,6 +52,12 @@ class Diagram {
this.type = utils.detectType(txt, cnf);
log.debug('Type ' + this.type);
switch (this.type) {
case 'c4':
this.parser = c4Parser;
this.parser.parser.yy = c4Db;
this.db = c4Db;
this.renderer = c4Renderer;
break;
case 'gitGraph':
this.parser = gitGraphParser;
this.parser.parser.yy = gitGraphAst;

View File

@@ -1,6 +1,6 @@
/**
* This method will add a basic title and description element to a chart. The yy parser will need to
* respond to getTitle and getAccDescription, where the title is the title element on the chart,
* respond to getAccTitle and getAccDescription, where the title is the title element on the chart,
* which is generally not displayed and the accDescription is the description element on the chart,
* which is never displayed.
*
@@ -15,7 +15,7 @@ export default function addSVGAccessibilityFields(yy_parser, svg, id) {
return;
}
let title_string = yy_parser.getTitle();
let title_string = yy_parser.getAccTitle();
let description = yy_parser.getAccDescription();
svg.attr('role', 'img').attr('aria-labelledby', 'chart-title-' + id + ' chart-desc-' + id);
svg

View File

@@ -1,20 +1,22 @@
import { sanitizeText as _sanitizeText } from './diagrams/common/common';
import { getConfig } from './config';
let title = '';
let diagramTitle = '';
let description = '';
const sanitizeText = (txt) => _sanitizeText(txt, getConfig());
export const clear = function () {
title = '';
description = '';
diagramTitle = '';
};
export const setTitle = function (txt) {
export const setAccTitle = function (txt) {
title = sanitizeText(txt).replace(/^\s+/g, '');
};
export const getTitle = function () {
return title;
export const getAccTitle = function () {
return title || diagramTitle;
};
export const setAccDescription = function (txt) {
@@ -25,9 +27,19 @@ export const getAccDescription = function () {
return description;
};
export const setDiagramTitle = function (txt) {
diagramTitle = sanitizeText(txt);
};
export const getDiagramTitle = function () {
return diagramTitle;
};
export default {
setTitle,
getTitle,
setAccTitle,
getAccTitle,
setDiagramTitle,
getDiagramTitle: getDiagramTitle,
getAccDescription,
setAccDescription,
clear,

View File

@@ -209,9 +209,9 @@ export const addDirective = (directive) => {
*
* ## conf
*
* | Parameter | Description | Type | Required | Values |
* | --------- | ------------------------------------------------------------- | ---------- | -------- | -------------------------------------------- |
* | conf | base set of values, which currentConfig coul be **reset** to. | Dictionary | Required | Any Values, with respect to the secure Array |
* | Parameter | Description | Type | Required | Values |
* | --------- | -------------------------------------------------------------- | ---------- | -------- | -------------------------------------------- |
* | conf | base set of values, which currentConfig could be **reset** to. | Dictionary | Required | Any Values, with respect to the secure Array |
*
* **Notes**: (default: current siteConfig ) (optional, default `getSiteConfig()`)
*/

View File

@@ -40,7 +40,7 @@ const rect = (parent, node) => {
const width = node.width <= bbox.width + padding ? bbox.width + padding : node.width;
if (node.width <= bbox.width + padding) {
node.diff = (bbox.width - node.width) / 2;
node.diff = (bbox.width - node.width) / 2 - node.padding / 2;
} else {
node.diff = -node.padding / 2;
}

View File

@@ -192,19 +192,6 @@ export const positionEdgeLabel = (edge, paths) => {
}
};
// const getRelationType = function(type) {
// switch (type) {
// case stateDb.relationType.AGGREGATION:
// return 'aggregation';
// case stateDb.relationType.EXTENSION:
// return 'extension';
// case stateDb.relationType.COMPOSITION:
// return 'composition';
// case stateDb.relationType.DEPENDENCY:
// return 'dependency';
// }
// };
const outsideNode = (node, point) => {
// log.warn('Checking bounds ', node, point);
const x = node.x;
@@ -415,45 +402,7 @@ export const insertEdge = function (elem, e, edge, clusterDb, diagramType, graph
if (edge.fromCluster) {
log.info('from cluster abc88', clusterDb[edge.fromCluster]);
points = cutPathAtIntersect(points.reverse(), clusterDb[edge.fromCluster].node).reverse();
// log.warn('edge', edge);
// log.warn('from cluster', clusterDb[edge.fromCluster], points);
// const updatedPoints = [];
// let lastPointOutside = edge.points[edge.points.length - 1];
// let isInside = false;
// for (let i = points.length - 1; i >= 0; i--) {
// const point = points[i];
// const node = clusterDb[edge.fromCluster].node;
// log.warn('checking to', edge.fromCluster, point, node);
// if (!outsideNode(node, point) && !isInside) {
// log.warn('inside', edge.fromCluster, point, node);
// // First point inside the rect
// const inter = intersection(node, lastPointOutside, point);
// log.warn('intersect', intersection(node, lastPointOutside, point));
// let pointPresent = false;
// points.forEach(p => {
// pointPresent = pointPresent || (p.x === inter.x && p.y === inter.y);
// });
// // if (!pointPresent) {
// if (!points.find(e => e.x === inter.x && e.y === inter.y)) {
// updatedPoints.unshift(inter);
// log.warn('Adding point -updated = ', updatedPoints);
// } else {
// log.warn('no intersect', inter, points);
// }
// // points.push(insterection);
// isInside = true;
// } else {
// // at the outside
// // if (!isInside) updatedPoints.unshift(point);
// updatedPoints.unshift(point);
// log.warn('Outside point', point, updatedPoints);
// }
// lastPointOutside = point;
// }
// points = updatedPoints;
// points = edge.points;
pointsHasChanged = true;
}

View File

@@ -5,7 +5,7 @@
* @param point
*/
function intersectEllipse(node, rx, ry, point) {
// Formulae from: http://mathworld.wolfram.com/Ellipse-LineIntersection.html
// Formulae from: https://mathworld.wolfram.com/Ellipse-LineIntersection.html
var cx = node.x;
var cy = node.y;

View File

@@ -3,7 +3,7 @@ const intersectRect = (node, point) => {
var y = node.y;
// Rectangle intersection algorithm from:
// http://math.stackexchange.com/questions/108113/find-edge-between-two-boxes
// https://math.stackexchange.com/questions/108113/find-edge-between-two-boxes
var dx = point.x - x;
var dy = point.y - y;
var w = node.width / 2;

View File

@@ -277,7 +277,33 @@ export const adjustClustersAndEdges = (graph, depth) => {
' --- ',
clusterDb[e.w]
);
if (clusterDb[e.v] || clusterDb[e.w]) {
if (clusterDb[e.v] && clusterDb[e.w] && clusterDb[e.v] === clusterDb[e.w]) {
log.warn('Fixing and trixing link to self - removing XXX', e.v, e.w, e.name);
log.warn('Fixing and trixing - removing XXX', e.v, e.w, e.name);
v = getAnchorId(e.v);
w = getAnchorId(e.w);
graph.removeEdge(e.v, e.w, e.name);
const specialId = e.w + '---' + e.v;
graph.setNode(specialId, {
domId: specialId,
id: specialId,
labelStyle: '',
labelText: edge.label,
padding: 0,
shape: 'labelRect',
style: '',
});
const edge1 = JSON.parse(JSON.stringify(edge));
const edge2 = JSON.parse(JSON.stringify(edge));
edge1.label = '';
edge1.arrowTypeEnd = 'none';
edge2.label = '';
edge1.fromCluster = e.v;
edge2.toCluster = e.v;
graph.setEdge(v, specialId, edge1, e.name + '-cyclic-special');
graph.setEdge(specialId, w, edge2, e.name + '-cyclic-special');
} else if (clusterDb[e.v] || clusterDb[e.w]) {
log.warn('Fixing and trixing - removing XXX', e.v, e.w, e.name);
v = getAnchorId(e.v);
w = getAnchorId(e.w);

View File

@@ -347,6 +347,39 @@ const rect = (parent, node) => {
return shapeSvg;
};
const labelRect = (parent, node) => {
const { shapeSvg, bbox, halfPadding } = labelHelper(parent, node, 'label', true);
log.trace('Classes = ', node.classes);
// add the rect
const rect = shapeSvg.insert('rect', ':first-child');
// Hide the rect we are only after the label
const totalWidth = 0;
const totalHeight = 0;
rect.attr('width', totalWidth).attr('height', totalHeight);
shapeSvg.attr('class', 'label edgeLabel');
if (node.props) {
const propKeys = new Set(Object.keys(node.props));
if (node.props.borders) {
applyNodePropertyBorders(rect, node.props.borders, totalWidth, totalHeight);
propKeys.delete('borders');
}
propKeys.forEach((propKey) => {
log.warn(`Unknown node property ${propKey}`);
});
}
updateNodeBounds(node, rect);
node.intersect = function (point) {
return intersect.rect(node, point);
};
return shapeSvg;
};
/**
* @param rect
* @param borders
@@ -976,6 +1009,7 @@ const class_box = (parent, node) => {
const shapes = {
question,
rect,
labelRect,
rectWithTitle,
choice,
circle,

View File

@@ -942,13 +942,13 @@ const config = {
minEntityHeight: 75,
/**
* | Parameter | Description | Type | Required | Values |
* | ------------- | ----------------------------------------------------------- | ------- | -------- | ------------------ |
* | entityPadding | Minimum internal padding betweentext in box and box borders | Integer | 4 | Any Positive Value |
* | Parameter | Description | Type | Required | Values |
* | ------------- | ------------------------------------------------------------ | ------- | -------- | ------------------ |
* | entityPadding | Minimum internal padding between text in box and box borders | Integer | 4 | Any Positive Value |
*
* **Notes:**
*
* The minimum internal padding betweentext in an entity box and the enclosing box borders,
* The minimum internal padding between text in an entity box and the enclosing box borders,
* expressed in pixels.
*
* Default value: 15
@@ -1058,6 +1058,406 @@ const config = {
mainBranchOrder: 0,
showCommitLabel: true,
showBranches: true,
rotateCommitLabel: true,
},
/** The object containing configurations specific for c4 diagrams */
c4: {
useWidth: undefined,
/**
* | Parameter | Description | Type | Required | Values |
* | -------------- | ---------------------------------------------- | ------- | -------- | ------------------ |
* | diagramMarginX | Margin to the right and left of the c4 diagram | Integer | Required | Any Positive Value |
*
* **Notes:** Default value: 50
*/
diagramMarginX: 50,
/**
* | Parameter | Description | Type | Required | Values |
* | -------------- | ------------------------------------------- | ------- | -------- | ------------------ |
* | diagramMarginY | Margin to the over and under the c4 diagram | Integer | Required | Any Positive Value |
*
* **Notes:** Default value: 10
*/
diagramMarginY: 10,
/**
* | Parameter | Description | Type | Required | Values |
* | ----------- | --------------------- | ------- | -------- | ------------------ |
* | shapeMargin | Margin between shapes | Integer | Required | Any Positive Value |
*
* **Notes:** Default value: 50
*/
c4ShapeMargin: 50,
c4ShapePadding: 20,
/**
* | Parameter | Description | Type | Required | Values |
* | --------- | --------------------- | ------- | -------- | ------------------ |
* | width | Width of person boxes | Integer | Required | Any Positive Value |
*
* **Notes:** Default value: 216
*/
width: 216,
/**
* | Parameter | Description | Type | Required | Values |
* | --------- | ---------------------- | ------- | -------- | ------------------ |
* | height | Height of person boxes | Integer | Required | Any Positive Value |
*
* **Notes:** Default value: 60
*/
height: 60,
/**
* | Parameter | Description | Type | Required | Values |
* | --------- | ------------------------ | ------- | -------- | ------------------ |
* | boxMargin | Margin around loop boxes | Integer | Required | Any Positive Value |
*
* **Notes:** Default value: 10
*/
boxMargin: 10,
/**
* | Parameter | Description | Type | Required | Values |
* | ----------- | ----------- | ------- | -------- | ----------- |
* | useMaxWidth | See Notes | boolean | Required | true, false |
*
* **Notes:** When this flag is set to true, the height and width is set to 100% and is then
* scaling with the available space. If set to false, the absolute space required is used.
*
* Default value: true
*/
useMaxWidth: true,
c4ShapeInRow: 4,
nextLinePaddingX: 0,
c4BoundaryInRow: 2,
personFontSize: 14,
personFontFamily: '"Open Sans", sans-serif',
personFontWeight: 'normal',
external_personFontSize: 14,
external_personFontFamily: '"Open Sans", sans-serif',
external_personFontWeight: 'normal',
systemFontSize: 14,
systemFontFamily: '"Open Sans", sans-serif',
systemFontWeight: 'normal',
external_systemFontSize: 14,
external_systemFontFamily: '"Open Sans", sans-serif',
external_systemFontWeight: 'normal',
system_dbFontSize: 14,
system_dbFontFamily: '"Open Sans", sans-serif',
system_dbFontWeight: 'normal',
external_system_dbFontSize: 14,
external_system_dbFontFamily: '"Open Sans", sans-serif',
external_system_dbFontWeight: 'normal',
system_queueFontSize: 14,
system_queueFontFamily: '"Open Sans", sans-serif',
system_queueFontWeight: 'normal',
external_system_queueFontSize: 14,
external_system_queueFontFamily: '"Open Sans", sans-serif',
external_system_queueFontWeight: 'normal',
boundaryFontSize: 14,
boundaryFontFamily: '"Open Sans", sans-serif',
boundaryFontWeight: 'normal',
messageFontSize: 12,
messageFontFamily: '"Open Sans", sans-serif',
messageFontWeight: 'normal',
containerFontSize: 14,
containerFontFamily: '"Open Sans", sans-serif',
containerFontWeight: 'normal',
external_containerFontSize: 14,
external_containerFontFamily: '"Open Sans", sans-serif',
external_containerFontWeight: 'normal',
container_dbFontSize: 14,
container_dbFontFamily: '"Open Sans", sans-serif',
container_dbFontWeight: 'normal',
external_container_dbFontSize: 14,
external_container_dbFontFamily: '"Open Sans", sans-serif',
external_container_dbFontWeight: 'normal',
container_queueFontSize: 14,
container_queueFontFamily: '"Open Sans", sans-serif',
container_queueFontWeight: 'normal',
external_container_queueFontSize: 14,
external_container_queueFontFamily: '"Open Sans", sans-serif',
external_container_queueFontWeight: 'normal',
componentFontSize: 14,
componentFontFamily: '"Open Sans", sans-serif',
componentFontWeight: 'normal',
external_componentFontSize: 14,
external_componentFontFamily: '"Open Sans", sans-serif',
external_componentFontWeight: 'normal',
component_dbFontSize: 14,
component_dbFontFamily: '"Open Sans", sans-serif',
component_dbFontWeight: 'normal',
external_component_dbFontSize: 14,
external_component_dbFontFamily: '"Open Sans", sans-serif',
external_component_dbFontWeight: 'normal',
component_queueFontSize: 14,
component_queueFontFamily: '"Open Sans", sans-serif',
component_queueFontWeight: 'normal',
external_component_queueFontSize: 14,
external_component_queueFontFamily: '"Open Sans", sans-serif',
external_component_queueFontWeight: 'normal',
/**
* This sets the auto-wrap state for the diagram
*
* **Notes:** Default value: true.
*/
wrap: true,
/**
* This sets the auto-wrap padding for the diagram (sides only)
*
* **Notes:** Default value: 0.
*/
wrapPadding: 10,
personFont: function () {
return {
fontFamily: this.personFontFamily,
fontSize: this.personFontSize,
fontWeight: this.personFontWeight,
};
},
external_personFont: function () {
return {
fontFamily: this.external_personFontFamily,
fontSize: this.external_personFontSize,
fontWeight: this.external_personFontWeight,
};
},
systemFont: function () {
return {
fontFamily: this.systemFontFamily,
fontSize: this.systemFontSize,
fontWeight: this.systemFontWeight,
};
},
external_systemFont: function () {
return {
fontFamily: this.external_systemFontFamily,
fontSize: this.external_systemFontSize,
fontWeight: this.external_systemFontWeight,
};
},
system_dbFont: function () {
return {
fontFamily: this.system_dbFontFamily,
fontSize: this.system_dbFontSize,
fontWeight: this.system_dbFontWeight,
};
},
external_system_dbFont: function () {
return {
fontFamily: this.external_system_dbFontFamily,
fontSize: this.external_system_dbFontSize,
fontWeight: this.external_system_dbFontWeight,
};
},
system_queueFont: function () {
return {
fontFamily: this.system_queueFontFamily,
fontSize: this.system_queueFontSize,
fontWeight: this.system_queueFontWeight,
};
},
external_system_queueFont: function () {
return {
fontFamily: this.external_system_queueFontFamily,
fontSize: this.external_system_queueFontSize,
fontWeight: this.external_system_queueFontWeight,
};
},
containerFont: function () {
return {
fontFamily: this.containerFontFamily,
fontSize: this.containerFontSize,
fontWeight: this.containerFontWeight,
};
},
external_containerFont: function () {
return {
fontFamily: this.external_containerFontFamily,
fontSize: this.external_containerFontSize,
fontWeight: this.external_containerFontWeight,
};
},
container_dbFont: function () {
return {
fontFamily: this.container_dbFontFamily,
fontSize: this.container_dbFontSize,
fontWeight: this.container_dbFontWeight,
};
},
external_container_dbFont: function () {
return {
fontFamily: this.external_container_dbFontFamily,
fontSize: this.external_container_dbFontSize,
fontWeight: this.external_container_dbFontWeight,
};
},
container_queueFont: function () {
return {
fontFamily: this.container_queueFontFamily,
fontSize: this.container_queueFontSize,
fontWeight: this.container_queueFontWeight,
};
},
external_container_queueFont: function () {
return {
fontFamily: this.external_container_queueFontFamily,
fontSize: this.external_container_queueFontSize,
fontWeight: this.external_container_queueFontWeight,
};
},
componentFont: function () {
return {
fontFamily: this.componentFontFamily,
fontSize: this.componentFontSize,
fontWeight: this.componentFontWeight,
};
},
external_componentFont: function () {
return {
fontFamily: this.external_componentFontFamily,
fontSize: this.external_componentFontSize,
fontWeight: this.external_componentFontWeight,
};
},
component_dbFont: function () {
return {
fontFamily: this.component_dbFontFamily,
fontSize: this.component_dbFontSize,
fontWeight: this.component_dbFontWeight,
};
},
external_component_dbFont: function () {
return {
fontFamily: this.external_component_dbFontFamily,
fontSize: this.external_component_dbFontSize,
fontWeight: this.external_component_dbFontWeight,
};
},
component_queueFont: function () {
return {
fontFamily: this.component_queueFontFamily,
fontSize: this.component_queueFontSize,
fontWeight: this.component_queueFontWeight,
};
},
external_component_queueFont: function () {
return {
fontFamily: this.external_component_queueFontFamily,
fontSize: this.external_component_queueFontSize,
fontWeight: this.external_component_queueFontWeight,
};
},
boundaryFont: function () {
return {
fontFamily: this.boundaryFontFamily,
fontSize: this.boundaryFontSize,
fontWeight: this.boundaryFontWeight,
};
},
messageFont: function () {
return {
fontFamily: this.messageFontFamily,
fontSize: this.messageFontSize,
fontWeight: this.messageFontWeight,
};
},
// ' Colors
// ' ##################################
person_bg_color: '#08427B',
person_border_color: '#073B6F',
external_person_bg_color: '#686868',
external_person_border_color: '#8A8A8A',
system_bg_color: '#1168BD',
system_border_color: '#3C7FC0',
system_db_bg_color: '#1168BD',
system_db_border_color: '#3C7FC0',
system_queue_bg_color: '#1168BD',
system_queue_border_color: '#3C7FC0',
external_system_bg_color: '#999999',
external_system_border_color: '#8A8A8A',
external_system_db_bg_color: '#999999',
external_system_db_border_color: '#8A8A8A',
external_system_queue_bg_color: '#999999',
external_system_queue_border_color: '#8A8A8A',
container_bg_color: '#438DD5',
container_border_color: '#3C7FC0',
container_db_bg_color: '#438DD5',
container_db_border_color: '#3C7FC0',
container_queue_bg_color: '#438DD5',
container_queue_border_color: '#3C7FC0',
external_container_bg_color: '#B3B3B3',
external_container_border_color: '#A6A6A6',
external_container_db_bg_color: '#B3B3B3',
external_container_db_border_color: '#A6A6A6',
external_container_queue_bg_color: '#B3B3B3',
external_container_queue_border_color: '#A6A6A6',
component_bg_color: '#85BBF0',
component_border_color: '#78A8D8',
component_db_bg_color: '#85BBF0',
component_db_border_color: '#78A8D8',
component_queue_bg_color: '#85BBF0',
component_queue_border_color: '#78A8D8',
external_component_bg_color: '#CCCCCC',
external_component_border_color: '#BFBFBF',
external_component_db_bg_color: '#CCCCCC',
external_component_db_border_color: '#BFBFBF',
external_component_queue_bg_color: '#CCCCCC',
external_component_queue_border_color: '#BFBFBF',
},
};

480
src/diagrams/c4/c4Db.js Normal file
View File

@@ -0,0 +1,480 @@
import mermaidAPI from '../../mermaidAPI';
import * as configApi from '../../config';
import { log } from '../../logger';
import { sanitizeText } from '../common/common';
import { setAccTitle, getAccTitle, getAccDescription, setAccDescription } from '../../commonDb';
let c4ShapeArray = [];
let boundaryParseStack = [''];
let currentBoundaryParse = 'global';
let parentBoundaryParse = '';
let boundarys = [
{
alias: 'global',
label: { text: 'global' },
type: { text: 'global' },
tags: null,
link: null,
parentBoundary: '',
},
];
let rels = [];
let title = '';
let wrapEnabled = false;
let description = '';
var c4Type;
export const getC4Type = function () {
return c4Type;
};
export const setC4Type = function (c4TypeParam) {
let sanitizedText = sanitizeText(c4TypeParam, configApi.getConfig());
c4Type = sanitizedText;
};
export const parseDirective = function (statement, context, type) {
mermaidAPI.parseDirective(this, statement, context, type);
};
//type, from, to, label, ?techn, ?descr, ?sprite, ?tags, $link
export const addRel = function (type, from, to, label, techn, descr, sprite, tags, link) {
// Don't allow label nulling
if (
type === undefined ||
type === null ||
from === undefined ||
from === null ||
to === undefined ||
to === null ||
label === undefined ||
label === null
)
return;
let rel = {};
const old = rels.find((rel) => rel.from === from && rel.to === to);
if (old) {
rel = old;
} else {
rels.push(rel);
}
rel.type = type;
rel.from = from;
rel.to = to;
rel.label = { text: label };
if (descr === undefined || descr === null) {
rel.descr = { text: '' };
} else {
rel.descr = { text: descr };
}
if (techn === undefined || techn === null) {
rel.techn = { text: '' };
} else {
rel.techn = { text: techn };
}
// rel.techn = techn;
rel.sprite = sprite;
rel.tags = tags;
rel.link = link;
rel.wrap = autoWrap();
};
//type, alias, label, ?descr, ?sprite, ?tags, $link
export const addPersonOrSystem = function (typeC4Shape, alias, label, descr, sprite, tags, link) {
// Don't allow label nulling
if (alias === null || label === null) return;
let personOrSystem = {};
const old = c4ShapeArray.find((personOrSystem) => personOrSystem.alias === alias);
if (old && alias === old.alias) {
personOrSystem = old;
} else {
personOrSystem.alias = alias;
c4ShapeArray.push(personOrSystem);
}
// Don't allow null labels, either
if (label === undefined || label === null) {
personOrSystem.label = { text: '' };
} else {
personOrSystem.label = { text: label };
}
if (descr === undefined || descr === null) {
personOrSystem.descr = { text: '' };
} else {
personOrSystem.descr = { text: descr };
}
personOrSystem.wrap = autoWrap();
personOrSystem.sprite = sprite;
personOrSystem.tags = tags;
personOrSystem.link = link;
personOrSystem.typeC4Shape = { text: typeC4Shape };
personOrSystem.parentBoundary = currentBoundaryParse;
};
//type, alias, label, ?techn, ?descr ?sprite, ?tags, $link
export const addContainer = function (typeC4Shape, alias, label, techn, descr, sprite, tags, link) {
// Don't allow label nulling
if (alias === null || label === null) return;
let container = {};
const old = c4ShapeArray.find((container) => container.alias === alias);
if (old && alias === old.alias) {
container = old;
} else {
container.alias = alias;
c4ShapeArray.push(container);
}
// Don't allow null labels, either
if (label === undefined || label === null) {
container.label = { text: '' };
} else {
container.label = { text: label };
}
if (techn === undefined || techn === null) {
container.techn = { text: '' };
} else {
container.techn = { text: techn };
}
if (descr === undefined || descr === null) {
container.descr = { text: '' };
} else {
container.descr = { text: descr };
}
container.sprite = sprite;
container.tags = tags;
container.link = link;
container.wrap = autoWrap();
container.typeC4Shape = { text: typeC4Shape };
container.parentBoundary = currentBoundaryParse;
};
//type, alias, label, ?techn, ?descr ?sprite, ?tags, $link
export const addComponent = function (typeC4Shape, alias, label, techn, descr, sprite, tags, link) {
// Don't allow label nulling
if (alias === null || label === null) return;
let component = {};
const old = c4ShapeArray.find((component) => component.alias === alias);
if (old && alias === old.alias) {
component = old;
} else {
component.alias = alias;
c4ShapeArray.push(component);
}
// Don't allow null labels, either
if (label === undefined || label === null) {
component.label = { text: '' };
} else {
component.label = { text: label };
}
if (techn === undefined || techn === null) {
component.techn = { text: '' };
} else {
component.techn = { text: techn };
}
if (descr === undefined || descr === null) {
component.descr = { text: '' };
} else {
component.descr = { text: descr };
}
component.sprite = sprite;
component.tags = tags;
component.link = link;
component.wrap = autoWrap();
component.typeC4Shape = { text: typeC4Shape };
component.parentBoundary = currentBoundaryParse;
};
//alias, label, ?type, ?tags, $link
export const addPersonOrSystemBoundary = function (alias, label, type, tags, link) {
// if (parentBoundary === null) return;
// Don't allow label nulling
if (alias === null || label === null) return;
let boundary = {};
const old = boundarys.find((boundary) => boundary.alias === alias);
if (old && alias === old.alias) {
boundary = old;
} else {
boundary.alias = alias;
boundarys.push(boundary);
}
// Don't allow null labels, either
if (label === undefined || label === null) {
boundary.label = { text: '' };
} else {
boundary.label = { text: label };
}
if (type === undefined || type === null) {
boundary.type = { text: 'system' };
} else {
boundary.type = { text: type };
}
boundary.tags = tags;
boundary.link = link;
boundary.parentBoundary = currentBoundaryParse;
boundary.wrap = autoWrap();
parentBoundaryParse = currentBoundaryParse;
currentBoundaryParse = alias;
boundaryParseStack.push(parentBoundaryParse);
};
//alias, label, ?type, ?tags, $link
export const addContainerBoundary = function (alias, label, type, tags, link) {
// if (parentBoundary === null) return;
// Don't allow label nulling
if (alias === null || label === null) return;
let boundary = {};
const old = boundarys.find((boundary) => boundary.alias === alias);
if (old && alias === old.alias) {
boundary = old;
} else {
boundary.alias = alias;
boundarys.push(boundary);
}
// Don't allow null labels, either
if (label === undefined || label === null) {
boundary.label = { text: '' };
} else {
boundary.label = { text: label };
}
if (type === undefined || type === null) {
boundary.type = { text: 'container' };
} else {
boundary.type = { text: type };
}
boundary.tags = tags;
boundary.link = link;
boundary.parentBoundary = currentBoundaryParse;
boundary.wrap = autoWrap();
parentBoundaryParse = currentBoundaryParse;
currentBoundaryParse = alias;
boundaryParseStack.push(parentBoundaryParse);
};
//alias, label, ?type, ?descr, ?sprite, ?tags, $link
export const addDeploymentNode = function (
nodeType,
alias,
label,
type,
descr,
sprite,
tags,
link
) {
// if (parentBoundary === null) return;
// Don't allow label nulling
if (alias === null || label === null) return;
let boundary = {};
const old = boundarys.find((boundary) => boundary.alias === alias);
if (old && alias === old.alias) {
boundary = old;
} else {
boundary.alias = alias;
boundarys.push(boundary);
}
// Don't allow null labels, either
if (label === undefined || label === null) {
boundary.label = { text: '' };
} else {
boundary.label = { text: label };
}
if (type === undefined || type === null) {
boundary.type = { text: 'node' };
} else {
boundary.type = { text: type };
}
if (descr === undefined || descr === null) {
boundary.descr = { text: '' };
} else {
boundary.descr = { text: type };
}
boundary.tags = tags;
boundary.link = link;
boundary.nodeType = nodeType;
boundary.parentBoundary = currentBoundaryParse;
boundary.wrap = autoWrap();
parentBoundaryParse = currentBoundaryParse;
currentBoundaryParse = alias;
boundaryParseStack.push(parentBoundaryParse);
};
export const popBoundaryParseStack = function () {
currentBoundaryParse = parentBoundaryParse;
boundaryParseStack.pop();
parentBoundaryParse = boundaryParseStack.pop();
boundaryParseStack.push(parentBoundaryParse);
};
export const getCurrentBoundaryParse = function () {
return currentBoundaryParse;
};
export const getParentBoundaryParse = function () {
return parentBoundaryParse;
};
export const getC4ShapeArray = function (parentBoundary) {
if (parentBoundary === undefined || parentBoundary === null) return c4ShapeArray;
else
return c4ShapeArray.filter((personOrSystem) => {
return personOrSystem.parentBoundary === parentBoundary;
});
};
export const getC4Shape = function (alias) {
return c4ShapeArray.find((personOrSystem) => personOrSystem.alias === alias);
};
export const getC4ShapeKeys = function (parentBoundary) {
return Object.keys(getC4ShapeArray(parentBoundary));
};
export const getBoundarys = function (parentBoundary) {
if (parentBoundary === undefined || parentBoundary === null) return boundarys;
else return boundarys.filter((boundary) => boundary.parentBoundary === parentBoundary);
};
export const getRels = function () {
return rels;
};
export const getTitle = function () {
return title;
};
export const setWrap = function (wrapSetting) {
wrapEnabled = wrapSetting;
};
export const autoWrap = function () {
return wrapEnabled;
};
export const clear = function () {
c4ShapeArray = [];
boundarys = [
{
alias: 'global',
label: { text: 'global' },
type: { text: 'global' },
tags: null,
link: null,
parentBoundary: '',
},
];
parentBoundaryParse = '';
currentBoundaryParse = 'global';
boundaryParseStack = [''];
rels = [];
};
export const LINETYPE = {
SOLID: 0,
DOTTED: 1,
NOTE: 2,
SOLID_CROSS: 3,
DOTTED_CROSS: 4,
SOLID_OPEN: 5,
DOTTED_OPEN: 6,
LOOP_START: 10,
LOOP_END: 11,
ALT_START: 12,
ALT_ELSE: 13,
ALT_END: 14,
OPT_START: 15,
OPT_END: 16,
ACTIVE_START: 17,
ACTIVE_END: 18,
PAR_START: 19,
PAR_AND: 20,
PAR_END: 21,
RECT_START: 22,
RECT_END: 23,
SOLID_POINT: 24,
DOTTED_POINT: 25,
};
export const ARROWTYPE = {
FILLED: 0,
OPEN: 1,
};
export const PLACEMENT = {
LEFTOF: 0,
RIGHTOF: 1,
OVER: 2,
};
export const setTitle = function (txt) {
let sanitizedText = sanitizeText(txt, configApi.getConfig());
title = sanitizedText;
};
export default {
addPersonOrSystem,
addPersonOrSystemBoundary,
addContainer,
addContainerBoundary,
addComponent,
addDeploymentNode,
popBoundaryParseStack,
addRel,
autoWrap,
setWrap,
getC4ShapeArray,
getC4Shape,
getC4ShapeKeys,
getBoundarys,
getCurrentBoundaryParse,
getParentBoundaryParse,
getRels,
getTitle,
getC4Type,
setAccTitle,
getAccTitle,
getAccDescription,
setAccDescription,
parseDirective,
getConfig: () => configApi.getConfig().c4,
clear,
LINETYPE,
ARROWTYPE,
PLACEMENT,
setTitle,
setC4Type,
// apply,
};

View File

@@ -0,0 +1,670 @@
import { select } from 'd3';
import svgDraw, { drawText, fixLifeLineHeights } from './svgDraw';
import { log } from '../../logger';
import { parser } from './parser/c4Diagram';
import common from '../common/common';
import c4Db from './c4Db';
import * as configApi from '../../config';
import utils, {
wrapLabel,
calculateTextWidth,
calculateTextHeight,
assignWithDepth,
configureSvgSize,
} from '../../utils';
import addSVGAccessibilityFields from '../../accessibility';
let globalBoundaryMaxX = 0,
globalBoundaryMaxY = 0;
parser.yy = c4Db;
let conf = {};
class Bounds {
constructor() {
this.name = '';
this.data = {};
this.data.startx = undefined;
this.data.stopx = undefined;
this.data.starty = undefined;
this.data.stopy = undefined;
this.data.widthLimit = undefined;
this.nextData = {};
this.nextData.startx = undefined;
this.nextData.stopx = undefined;
this.nextData.starty = undefined;
this.nextData.stopy = undefined;
this.nextData.cnt = 0;
setConf(parser.yy.getConfig());
}
setData(startx, stopx, starty, stopy) {
this.nextData.startx = this.data.startx = startx;
this.nextData.stopx = this.data.stopx = stopx;
this.nextData.starty = this.data.starty = starty;
this.nextData.stopy = this.data.stopy = stopy;
}
updateVal(obj, key, val, fun) {
if (typeof obj[key] === 'undefined') {
obj[key] = val;
} else {
obj[key] = fun(val, obj[key]);
}
}
insert(c4Shape) {
this.nextData.cnt = this.nextData.cnt + 1;
let _startx =
this.nextData.startx === this.nextData.stopx
? this.nextData.stopx + c4Shape.margin
: this.nextData.stopx + c4Shape.margin * 2;
let _stopx = _startx + c4Shape.width;
let _starty = this.nextData.starty + c4Shape.margin * 2;
let _stopy = _starty + c4Shape.height;
if (
_startx >= this.data.widthLimit ||
_stopx >= this.data.widthLimit ||
this.nextData.cnt > conf.c4ShapeInRow
) {
_startx = this.nextData.startx + c4Shape.margin + conf.nextLinePaddingX;
_starty = this.nextData.stopy + c4Shape.margin * 2;
this.nextData.stopx = _stopx = _startx + c4Shape.width;
this.nextData.starty = this.nextData.stopy;
this.nextData.stopy = _stopy = _starty + c4Shape.height;
this.nextData.cnt = 1;
}
c4Shape.x = _startx;
c4Shape.y = _starty;
this.updateVal(this.data, 'startx', _startx, Math.min);
this.updateVal(this.data, 'starty', _starty, Math.min);
this.updateVal(this.data, 'stopx', _stopx, Math.max);
this.updateVal(this.data, 'stopy', _stopy, Math.max);
this.updateVal(this.nextData, 'startx', _startx, Math.min);
this.updateVal(this.nextData, 'starty', _starty, Math.min);
this.updateVal(this.nextData, 'stopx', _stopx, Math.max);
this.updateVal(this.nextData, 'stopy', _stopy, Math.max);
}
init() {
this.name = '';
this.data = {
startx: undefined,
stopx: undefined,
starty: undefined,
stopy: undefined,
widthLimit: undefined,
};
this.nextData = {
startx: undefined,
stopx: undefined,
starty: undefined,
stopy: undefined,
cnt: 0,
};
setConf(parser.yy.getConfig());
}
bumpLastMargin(margin) {
this.data.stopx += margin;
this.data.stopy += margin;
}
}
export const setConf = function (cnf) {
assignWithDepth(conf, cnf);
if (cnf.fontFamily) {
conf.personFontFamily = conf.systemFontFamily = conf.messageFontFamily = cnf.fontFamily;
}
if (cnf.fontSize) {
conf.personFontSize = conf.systemFontSize = conf.messageFontSize = cnf.fontSize;
}
if (cnf.fontWeight) {
conf.personFontWeight = conf.systemFontWeight = conf.messageFontWeight = cnf.fontWeight;
}
};
const c4ShapeFont = (cnf, typeC4Shape) => {
return {
fontFamily: cnf[typeC4Shape + 'FontFamily'],
fontSize: cnf[typeC4Shape + 'FontSize'],
fontWeight: cnf[typeC4Shape + 'FontWeight'],
};
};
const boundaryFont = (cnf) => {
return {
fontFamily: cnf.boundaryFontFamily,
fontSize: cnf.boundaryFontSize,
fontWeight: cnf.boundaryFontWeight,
};
};
const messageFont = (cnf) => {
return {
fontFamily: cnf.messageFontFamily,
fontSize: cnf.messageFontSize,
fontWeight: cnf.messageFontWeight,
};
};
/**
* @param textType
* @param c4Shape
* @param c4ShapeTextWrap
* @param textConf
* @param textLimitWidth
*/
function calcC4ShapeTextWH(textType, c4Shape, c4ShapeTextWrap, textConf, textLimitWidth) {
if (!c4Shape[textType].width) {
if (c4ShapeTextWrap) {
c4Shape[textType].text = wrapLabel(c4Shape[textType].text, textLimitWidth, textConf);
c4Shape[textType].textLines = c4Shape[textType].text.split(common.lineBreakRegex).length;
// c4Shape[textType].width = calculateTextWidth(c4Shape[textType].text, textConf);
c4Shape[textType].width = textLimitWidth;
// c4Shape[textType].height = c4Shape[textType].textLines * textConf.fontSize;
c4Shape[textType].height = calculateTextHeight(c4Shape[textType].text, textConf);
} else {
let lines = c4Shape[textType].text.split(common.lineBreakRegex);
c4Shape[textType].textLines = lines.length;
let lineHeight = 0;
c4Shape[textType].height = 0;
c4Shape[textType].width = 0;
for (let i = 0; i < lines.length; i++) {
c4Shape[textType].width = Math.max(
calculateTextWidth(lines[i], textConf),
c4Shape[textType].width
);
lineHeight = calculateTextHeight(lines[i], textConf);
c4Shape[textType].height = c4Shape[textType].height + lineHeight;
}
// c4Shapes[textType].height = c4Shapes[textType].textLines * textConf.fontSize;
}
}
}
export const drawBoundary = function (diagram, boundary, bounds) {
boundary.x = bounds.data.startx;
boundary.y = bounds.data.starty;
boundary.width = bounds.data.stopx - bounds.data.startx;
boundary.height = bounds.data.stopy - bounds.data.starty;
boundary.label.y = conf.c4ShapeMargin - 35;
let boundaryTextWrap = boundary.wrap && conf.wrap;
let boundaryLabelConf = boundaryFont(conf);
boundaryLabelConf.fontSize = boundaryLabelConf.fontSize + 2;
boundaryLabelConf.fontWeight = 'bold';
let textLimitWidth = calculateTextWidth(boundary.label.text, boundaryLabelConf);
calcC4ShapeTextWH('label', boundary, boundaryTextWrap, boundaryLabelConf, textLimitWidth);
svgDraw.drawBoundary(diagram, boundary, conf);
};
export const drawC4ShapeArray = function (currentBounds, diagram, c4ShapeArray, c4ShapeKeys) {
// Upper Y is relative point
let Y = 0;
// Draw the c4ShapeArray
for (let i = 0; i < c4ShapeKeys.length; i++) {
Y = 0;
const c4Shape = c4ShapeArray[c4ShapeKeys[i]];
// calc c4 shape type width and height
let c4ShapeTypeConf = c4ShapeFont(conf, c4Shape.typeC4Shape.text);
c4ShapeTypeConf.fontSize = c4ShapeTypeConf.fontSize - 2;
c4Shape.typeC4Shape.width = calculateTextWidth(
'<<' + c4Shape.typeC4Shape.text + '>>',
c4ShapeTypeConf
);
c4Shape.typeC4Shape.height = c4ShapeTypeConf.fontSize + 2;
c4Shape.typeC4Shape.Y = conf.c4ShapePadding;
Y = c4Shape.typeC4Shape.Y + c4Shape.typeC4Shape.height - 4;
// set image width and height c4Shape.x + c4Shape.width / 2 - 24, c4Shape.y + 28
// let imageWidth = 0,
// imageHeight = 0,
// imageY = 0;
//
c4Shape.image = { width: 0, height: 0, Y: 0 };
switch (c4Shape.typeC4Shape.text) {
case 'person':
case 'external_person':
c4Shape.image.width = 48;
c4Shape.image.height = 48;
c4Shape.image.Y = Y;
Y = c4Shape.image.Y + c4Shape.image.height;
break;
}
if (c4Shape.sprite) {
c4Shape.image.width = 48;
c4Shape.image.height = 48;
c4Shape.image.Y = Y;
Y = c4Shape.image.Y + c4Shape.image.height;
}
// Y = conf.c4ShapePadding + c4Shape.image.height;
let c4ShapeTextWrap = c4Shape.wrap && conf.wrap;
let textLimitWidth = conf.width - conf.c4ShapePadding * 2;
let c4ShapeLabelConf = c4ShapeFont(conf, c4Shape.typeC4Shape.text);
c4ShapeLabelConf.fontSize = c4ShapeLabelConf.fontSize + 2;
c4ShapeLabelConf.fontWeight = 'bold';
calcC4ShapeTextWH('label', c4Shape, c4ShapeTextWrap, c4ShapeLabelConf, textLimitWidth);
c4Shape['label'].Y = Y + 8;
Y = c4Shape['label'].Y + c4Shape['label'].height;
if (c4Shape.type && c4Shape.type.text !== '') {
c4Shape.type.text = '[' + c4Shape.type.text + ']';
let c4ShapeTypeConf = c4ShapeFont(conf, c4Shape.typeC4Shape.text);
calcC4ShapeTextWH('type', c4Shape, c4ShapeTextWrap, c4ShapeTypeConf, textLimitWidth);
c4Shape['type'].Y = Y + 5;
Y = c4Shape['type'].Y + c4Shape['type'].height;
} else if (c4Shape.techn && c4Shape.techn.text !== '') {
c4Shape.techn.text = '[' + c4Shape.techn.text + ']';
let c4ShapeTechnConf = c4ShapeFont(conf, c4Shape.techn.text);
calcC4ShapeTextWH('techn', c4Shape, c4ShapeTextWrap, c4ShapeTechnConf, textLimitWidth);
c4Shape['techn'].Y = Y + 5;
Y = c4Shape['techn'].Y + c4Shape['techn'].height;
}
let rectHeight = Y;
let rectWidth = c4Shape.label.width;
if (c4Shape.descr && c4Shape.descr.text !== '') {
let c4ShapeDescrConf = c4ShapeFont(conf, c4Shape.typeC4Shape.text);
calcC4ShapeTextWH('descr', c4Shape, c4ShapeTextWrap, c4ShapeDescrConf, textLimitWidth);
c4Shape['descr'].Y = Y + 20;
Y = c4Shape['descr'].Y + c4Shape['descr'].height;
rectWidth = Math.max(c4Shape.label.width, c4Shape.descr.width);
rectHeight = Y - c4Shape['descr'].textLines * 5;
}
rectWidth = rectWidth + conf.c4ShapePadding;
// let rectHeight =
c4Shape.width = Math.max(c4Shape.width || conf.width, rectWidth, conf.width);
c4Shape.height = Math.max(c4Shape.height || conf.height, rectHeight, conf.height);
c4Shape.margin = c4Shape.margin || conf.c4ShapeMargin;
currentBounds.insert(c4Shape);
const height = svgDraw.drawC4Shape(diagram, c4Shape, conf);
}
currentBounds.bumpLastMargin(conf.c4ShapeMargin);
};
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
/* * *
* Get the intersection of the line between the center point of a rectangle and a point outside the rectangle.
* Algorithm idea.
* Using a point outside the rectangle as the coordinate origin, the graph is divided into four quadrants, and each quadrant is divided into two cases, with separate treatment on the coordinate axes
* 1. The case of coordinate axes.
* 1. The case of the negative x-axis
* 2. The case of the positive x-axis
* 3. The case of the positive y-axis
* 4. The negative y-axis case
* 2. Quadrant cases.
* 2.1. first quadrant: the case where the line intersects the left side of the rectangle; the case where it intersects the lower side of the rectangle
* 2.2. second quadrant: the case where the line intersects the right side of the rectangle; the case where it intersects the lower edge of the rectangle
* 2.3. third quadrant: the case where the line intersects the right side of the rectangle; the case where it intersects the upper edge of the rectangle
* 2.4. fourth quadrant: the case where the line intersects the left side of the rectangle; the case where it intersects the upper side of the rectangle
*
*/
let getIntersectPoint = function (fromNode, endPoint) {
let x1 = fromNode.x;
let y1 = fromNode.y;
let x2 = endPoint.x;
let y2 = endPoint.y;
let fromCenterX = x1 + fromNode.width / 2;
let fromCenterY = y1 + fromNode.height / 2;
let dx = Math.abs(x1 - x2);
let dy = Math.abs(y1 - y2);
let tanDYX = dy / dx;
let fromDYX = fromNode.height / fromNode.width;
let returnPoint = null;
if (y1 == y2 && x1 < x2) {
returnPoint = new Point(x1 + fromNode.width, fromCenterY);
} else if (y1 == y2 && x1 > x2) {
returnPoint = new Point(x1, fromCenterY);
} else if (x1 == x2 && y1 < y2) {
returnPoint = new Point(fromCenterX, y1 + fromNode.height);
} else if (x1 == x2 && y1 > y2) {
returnPoint = new Point(fromCenterX, y1);
}
if (x1 > x2 && y1 < y2) {
if (fromDYX >= tanDYX) {
returnPoint = new Point(x1, fromCenterY + (tanDYX * fromNode.width) / 2);
} else {
returnPoint = new Point(
fromCenterX - ((dx / dy) * fromNode.height) / 2,
y1 + fromNode.height
);
}
} else if (x1 < x2 && y1 < y2) {
//
if (fromDYX >= tanDYX) {
returnPoint = new Point(x1 + fromNode.width, fromCenterY + (tanDYX * fromNode.width) / 2);
} else {
returnPoint = new Point(
fromCenterX + ((dx / dy) * fromNode.height) / 2,
y1 + fromNode.height
);
}
} else if (x1 < x2 && y1 > y2) {
if (fromDYX >= tanDYX) {
returnPoint = new Point(x1 + fromNode.width, fromCenterY - (tanDYX * fromNode.width) / 2);
} else {
returnPoint = new Point(fromCenterX + ((fromNode.height / 2) * dx) / dy, y1);
}
} else if (x1 > x2 && y1 > y2) {
if (fromDYX >= tanDYX) {
returnPoint = new Point(x1, fromCenterY - (fromNode.width / 2) * tanDYX);
} else {
returnPoint = new Point(fromCenterX - ((fromNode.height / 2) * dx) / dy, y1);
}
}
return returnPoint;
};
let getIntersectPoints = function (fromNode, endNode) {
let endIntersectPoint = { x: 0, y: 0 };
endIntersectPoint.x = endNode.x + endNode.width / 2;
endIntersectPoint.y = endNode.y + endNode.height / 2;
let startPoint = getIntersectPoint(fromNode, endIntersectPoint);
endIntersectPoint.x = fromNode.x + fromNode.width / 2;
endIntersectPoint.y = fromNode.y + fromNode.height / 2;
let endPoint = getIntersectPoint(endNode, endIntersectPoint);
return { startPoint: startPoint, endPoint: endPoint };
};
export const drawRels = function (diagram, rels, getC4ShapeObj) {
let i = 0;
for (let rel of rels) {
i = i + 1;
let relTextWrap = rel.wrap && conf.wrap;
let relConf = messageFont(conf);
let diagramType = parser.yy.getC4Type();
if (diagramType === 'C4Dynamic') rel.label.text = i + ': ' + rel.label.text;
let textLimitWidth = calculateTextWidth(rel.label.text, relConf);
calcC4ShapeTextWH('label', rel, relTextWrap, relConf, textLimitWidth);
if (rel.techn && rel.techn.text !== '') {
textLimitWidth = calculateTextWidth(rel.techn.text, relConf);
calcC4ShapeTextWH('techn', rel, relTextWrap, relConf, textLimitWidth);
}
if (rel.descr && rel.descr.text !== '') {
textLimitWidth = calculateTextWidth(rel.descr.text, relConf);
calcC4ShapeTextWH('descr', rel, relTextWrap, relConf, textLimitWidth);
}
let fromNode = getC4ShapeObj(rel.from);
let endNode = getC4ShapeObj(rel.to);
let points = getIntersectPoints(fromNode, endNode);
rel.startPoint = points.startPoint;
rel.endPoint = points.endPoint;
}
svgDraw.drawRels(diagram, rels, conf);
};
/**
* @param diagram
* @param parentBoundaryAlias
* @param parentBounds
* @param currentBoundarys
*/
function drawInsideBoundary(diagram, parentBoundaryAlias, parentBounds, currentBoundarys) {
let currentBounds = new Bounds();
// Calculate the width limit of the boundar. label/type 的长度,
currentBounds.data.widthLimit =
parentBounds.data.widthLimit / Math.min(conf.c4BoundaryInRow, currentBoundarys.length);
// Math.min(
// conf.width * conf.c4ShapeInRow + conf.c4ShapeMargin * conf.c4ShapeInRow * 2,
// parentBounds.data.widthLimit / Math.min(conf.c4BoundaryInRow, currentBoundarys.length)
// );
for (let i = 0; i < currentBoundarys.length; i++) {
let currentBoundary = currentBoundarys[i];
let Y = 0;
currentBoundary.image = { width: 0, height: 0, Y: 0 };
if (currentBoundary.sprite) {
currentBoundary.image.width = 48;
currentBoundary.image.height = 48;
currentBoundary.image.Y = Y;
Y = currentBoundary.image.Y + currentBoundary.image.height;
}
let currentBoundaryTextWrap = currentBoundary.wrap && conf.wrap;
let currentBoundaryLabelConf = boundaryFont(conf);
currentBoundaryLabelConf.fontSize = currentBoundaryLabelConf.fontSize + 2;
currentBoundaryLabelConf.fontWeight = 'bold';
calcC4ShapeTextWH(
'label',
currentBoundary,
currentBoundaryTextWrap,
currentBoundaryLabelConf,
currentBounds.data.widthLimit
);
currentBoundary['label'].Y = Y + 8;
Y = currentBoundary['label'].Y + currentBoundary['label'].height;
if (currentBoundary.type && currentBoundary.type.text !== '') {
currentBoundary.type.text = '[' + currentBoundary.type.text + ']';
let currentBoundaryTypeConf = boundaryFont(conf);
calcC4ShapeTextWH(
'type',
currentBoundary,
currentBoundaryTextWrap,
currentBoundaryTypeConf,
currentBounds.data.widthLimit
);
currentBoundary['type'].Y = Y + 5;
Y = currentBoundary['type'].Y + currentBoundary['type'].height;
}
if (currentBoundary.descr && currentBoundary.descr.text !== '') {
let currentBoundaryDescrConf = boundaryFont(conf);
currentBoundaryDescrConf.fontSize = currentBoundaryDescrConf.fontSize - 2;
calcC4ShapeTextWH(
'descr',
currentBoundary,
currentBoundaryTextWrap,
currentBoundaryDescrConf,
currentBounds.data.widthLimit
);
currentBoundary['descr'].Y = Y + 20;
Y = currentBoundary['descr'].Y + currentBoundary['descr'].height;
}
if (i == 0 || i % conf.c4BoundaryInRow === 0) {
// Calculate the drawing start point of the currentBoundarys.
let _x = parentBounds.data.startx + conf.diagramMarginX;
let _y = parentBounds.data.stopy + conf.diagramMarginY + Y;
currentBounds.setData(_x, _x, _y, _y);
} else {
// Calculate the drawing start point of the currentBoundarys.
let _x =
currentBounds.data.stopx !== currentBounds.data.startx
? currentBounds.data.stopx + conf.diagramMarginX
: currentBounds.data.startx;
let _y = currentBounds.data.starty;
currentBounds.setData(_x, _x, _y, _y);
}
currentBounds.name = currentBoundary.alias;
let currentPersonOrSystemArray = parser.yy.getC4ShapeArray(currentBoundary.alias);
let currentPersonOrSystemKeys = parser.yy.getC4ShapeKeys(currentBoundary.alias);
if (currentPersonOrSystemKeys.length > 0) {
drawC4ShapeArray(
currentBounds,
diagram,
currentPersonOrSystemArray,
currentPersonOrSystemKeys
);
}
parentBoundaryAlias = currentBoundary.alias;
let nextCurrentBoundarys = parser.yy.getBoundarys(parentBoundaryAlias);
if (nextCurrentBoundarys.length > 0) {
// draw boundary inside currentBoundary
// bounds.init();
// parentBoundaryWidthLimit = bounds.data.stopx - bounds.startx;
drawInsideBoundary(diagram, parentBoundaryAlias, currentBounds, nextCurrentBoundarys);
}
// draw boundary
if (currentBoundary.alias !== 'global') drawBoundary(diagram, currentBoundary, currentBounds);
parentBounds.data.stopy = Math.max(
currentBounds.data.stopy + conf.c4ShapeMargin,
parentBounds.data.stopy
);
parentBounds.data.stopx = Math.max(
currentBounds.data.stopx + conf.c4ShapeMargin,
parentBounds.data.stopx
);
globalBoundaryMaxX = Math.max(globalBoundaryMaxX, parentBounds.data.stopx);
globalBoundaryMaxY = Math.max(globalBoundaryMaxY, parentBounds.data.stopy);
}
}
/**
* Draws a sequenceDiagram in the tag with id: id based on the graph definition in text.
*
* @param {any} text
* @param {any} id
*/
export const draw = function (text, id) {
conf = configApi.getConfig().c4;
const securityLevel = configApi.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;
parser.yy.clear();
parser.yy.setWrap(conf.wrap);
parser.parse(text + '\n');
log.debug(`C:${JSON.stringify(conf, null, 2)}`);
const diagram =
securityLevel === 'sandbox' ? root.select(`[id="${id}"]`) : select(`[id="${id}"]`);
svgDraw.insertComputerIcon(diagram);
svgDraw.insertDatabaseIcon(diagram);
svgDraw.insertClockIcon(diagram);
let screenBounds = new Bounds();
screenBounds.setData(
conf.diagramMarginX,
conf.diagramMarginX,
conf.diagramMarginY,
conf.diagramMarginY
);
screenBounds.data.widthLimit = screen.availWidth;
globalBoundaryMaxX = conf.diagramMarginX;
globalBoundaryMaxY = conf.diagramMarginY;
const title = parser.yy.getTitle();
const c4type = parser.yy.getC4Type();
let currentBoundarys = parser.yy.getBoundarys('');
// switch (c4type) {
// case 'C4Context':
drawInsideBoundary(diagram, '', screenBounds, currentBoundarys);
// break;
// }
// The arrow head definition is attached to the svg once
svgDraw.insertArrowHead(diagram);
svgDraw.insertArrowEnd(diagram);
svgDraw.insertArrowCrossHead(diagram);
svgDraw.insertArrowFilledHead(diagram);
drawRels(diagram, parser.yy.getRels(), parser.yy.getC4Shape);
screenBounds.data.stopx = globalBoundaryMaxX;
screenBounds.data.stopy = globalBoundaryMaxY;
const box = screenBounds.data;
// Make sure the height of the diagram supports long menus.
let boxHeight = box.stopy - box.starty;
let height = boxHeight + 2 * conf.diagramMarginY;
// Make sure the width of the diagram supports wide menus.
let boxWidth = box.stopx - box.startx;
const width = boxWidth + 2 * conf.diagramMarginX;
if (title) {
diagram
.append('text')
.text(title)
.attr('x', (box.stopx - box.startx) / 2 - 4 * conf.diagramMarginX)
.attr('y', box.starty + conf.diagramMarginY);
}
configureSvgSize(diagram, height, width, conf.useMaxWidth);
const extraVertForTitle = title ? 60 : 0;
diagram.attr(
'viewBox',
box.startx -
conf.diagramMarginX +
' -' +
(conf.diagramMarginY + extraVertForTitle) +
' ' +
width +
' ' +
(height + extraVertForTitle)
);
addSVGAccessibilityFields(parser.yy, diagram, id);
log.debug(`models:`, box);
};
export default {
drawPersonOrSystemArray: drawC4ShapeArray,
drawBoundary,
setConf,
draw,
};

View File

@@ -0,0 +1,312 @@
/** mermaid
* https://mermaidjs.github.io/
* (c) 2022 mzhx.meng@gmail.com
* MIT license.
*/
/* lexical grammar */
%lex
/* context */
%x person
%x person_ext
%x system
%x system_db
%x system_queue
%x system_ext
%x system_ext_db
%x system_ext_queue
%x boundary
%x enterprise_boundary
%x system_boundary
%x rel
%x birel
%x rel_u
%x rel_d
%x rel_l
%x rel_r
/* container */
%x container
%x container_db
%x container_queue
%x container_ext
%x container_ext_db
%x container_ext_queue
%x container_boundary
/* component */
%x component
%x component_db
%x component_queue
%x component_ext
%x component_ext_db
%x component_ext_queue
/* Dynamic diagram */
%x rel_index
%x index
/* Deployment diagram */
%x node
%x node_l
%x node_r
/* Relationship Types */
%x rel
%x rel_bi
%x rel_u
%x rel_d
%x rel_l
%x rel_r
%x rel_b
%x attribute
%x string
%x open_directive
%x type_directive
%x arg_directive
%%
\%\%\{ { this.begin('open_directive'); return 'open_directive'; }
.*direction\s+TB[^\n]* return 'direction_tb';
.*direction\s+BT[^\n]* return 'direction_bt';
.*direction\s+RL[^\n]* return 'direction_rl';
.*direction\s+LR[^\n]* return 'direction_lr';
<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';
\%\%(?!\{)*[^\n]*(\r?\n?)+ /* skip comments */
\%\%[^\n]*(\r?\n)* c /* skip comments */
"title"\s[^#\n;]+ return 'title';
"accDescription"\s[^#\n;]+ return 'accDescription';
\s*(\r?\n)+ return 'NEWLINE';
\s+ /* skip whitespace */
"C4Context" return 'C4_CONTEXT';
"C4Container" return 'C4_CONTAINER';
"C4Component" return 'C4_COMPONENT';
"C4Dynamic" return 'C4_DYNAMIC';
"C4Deployment" return 'C4_DEPLOYMENT';
"Person_Ext" { this.begin("person_ext"); console.log('begin person_ext'); return 'PERSON_EXT';}
"Person" { this.begin("person"); console.log('begin person'); return 'PERSON';}
"SystemQueue_Ext" { this.begin("system_ext_queue"); console.log('begin system_ext_queue'); return 'SYSTEM_EXT_QUEUE';}
"SystemDb_Ext" { this.begin("system_ext_db"); console.log('begin system_ext_db'); return 'SYSTEM_EXT_DB';}
"System_Ext" { this.begin("system_ext"); console.log('begin system_ext'); return 'SYSTEM_EXT';}
"SystemQueue" { this.begin("system_queue"); console.log('begin system_queue'); return 'SYSTEM_QUEUE';}
"SystemDb" { this.begin("system_db"); console.log('begin system_db'); return 'SYSTEM_DB';}
"System" { this.begin("system"); console.log('begin system'); return 'SYSTEM';}
"Boundary" { this.begin("boundary"); console.log('begin boundary'); return 'BOUNDARY';}
"Enterprise_Boundary" { this.begin("enterprise_boundary"); console.log('begin enterprise_boundary'); return 'ENTERPRISE_BOUNDARY';}
"System_Boundary" { this.begin("system_boundary"); console.log('begin system_boundary'); return 'SYSTEM_BOUNDARY';}
"ContainerQueue_Ext" { this.begin("container_ext_queue"); console.log('begin container_ext_queue'); return 'CONTAINER_EXT_QUEUE';}
"ContainerDb_Ext" { this.begin("container_ext_db"); console.log('begin container_ext_db'); return 'CONTAINER_EXT_DB';}
"Container_Ext" { this.begin("container_ext"); console.log('begin container_ext'); return 'CONTAINER_EXT';}
"ContainerQueue" { this.begin("container_queue"); console.log('begin container_queue'); return 'CONTAINER_QUEUE';}
"ContainerDb" { this.begin("container_db"); console.log('begin container_db'); return 'CONTAINER_DB';}
"Container" { this.begin("container"); console.log('begin container'); return 'CONTAINER';}
"Container_Boundary" { this.begin("container_boundary"); console.log('begin container_boundary'); return 'CONTAINER_BOUNDARY';}
"ComponentQueue_Ext" { this.begin("component_ext_queue"); console.log('begin component_ext_queue'); return 'COMPONENT_EXT_QUEUE';}
"ComponentDb_Ext" { this.begin("component_ext_db"); console.log('begin component_ext_db'); return 'COMPONENT_EXT_DB';}
"Component_Ext" { this.begin("component_ext"); console.log('begin component_ext'); return 'COMPONENT_EXT';}
"ComponentQueue" { this.begin("component_queue"); console.log('begin component_queue'); return 'COMPONENT_QUEUE';}
"ComponentDb" { this.begin("component_db"); console.log('begin component_db'); return 'COMPONENT_DB';}
"Component" { this.begin("component"); console.log('begin component'); return 'COMPONENT';}
"Deployment_Node" { this.begin("node"); console.log('begin node'); return 'NODE';}
"Node" { this.begin("node"); console.log('begin node'); return 'NODE';}
"Node_L" { this.begin("node_l"); console.log('begin node_l'); return 'NODE_L';}
"Node_R" { this.begin("node_r"); console.log('begin node_r'); return 'NODE_R';}
"Rel" { this.begin("rel"); console.log('begin rel'); return 'REL';}
"BiRel" { this.begin("birel"); console.log('begin birel'); return 'BIREL';}
"Rel_Up" { this.begin("rel_u"); console.log('begin rel_u'); return 'REL_U';}
"Rel_U" { this.begin("rel_u"); console.log('begin rel_u'); return 'REL_U';}
"Rel_Down" { this.begin("rel_d"); console.log('begin rel_d'); return 'REL_D';}
"Rel_D" { this.begin("rel_d"); console.log('begin rel_d'); return 'REL_D';}
"Rel_Left" { this.begin("rel_l"); console.log('begin rel_l'); return 'REL_L';}
"Rel_L" { this.begin("rel_l"); console.log('begin rel_l'); return 'REL_L';}
"Rel_Right" { this.begin("rel_r"); console.log('begin rel_r'); return 'REL_R';}
"Rel_R" { this.begin("rel_r"); console.log('begin rel_r'); return 'REL_R';}
"Rel_Back" { this.begin("rel_b"); console.log('begin rel_b'); return 'REL_B';}
"RelIndex" { this.begin("rel_index"); console.log('begin rel_index'); return 'REL_INDEX';}
<person,person_ext,system_ext_queue,system_ext_db,system_ext,system_queue,system_db,system,boundary,enterprise_boundary,system_boundary,container_ext_db,container_ext,container_queue,container_db,container,container_boundary,component_ext_db,component_ext,component_queue,component_db,component,node,node_l,node_r,rel,birel,rel_u,rel_d,rel_l,rel_r,rel_b,rel_index><<EOF>> return "EOF_IN_STRUCT";
<person,person_ext,system_ext_queue,system_ext_db,system_ext,system_queue,system_db,system,boundary,enterprise_boundary,system_boundary,container_ext_db,container_ext,container_queue,container_db,container,container_boundary,component_ext_db,component_ext,component_queue,component_db,component,node,node_l,node_r,rel,birel,rel_u,rel_d,rel_l,rel_r,rel_b,rel_index>[(][ ]*[,] { console.log('begin attribute with ATTRIBUTE_EMPTY'); this.begin("attribute"); return "ATTRIBUTE_EMPTY";}
<person,person_ext,system_ext_queue,system_ext_db,system_ext,system_queue,system_db,system,boundary,enterprise_boundary,system_boundary,container_ext_db,container_ext,container_queue,container_db,container,container_boundary,component_ext_db,component_ext,component_queue,component_db,component,node,node_l,node_r,rel,birel,rel_u,rel_d,rel_l,rel_r,rel_b,rel_index>[(] { console.log('begin attribute'); this.begin("attribute"); }
<person,person_ext,system_ext_queue,system_ext_db,system_ext,system_queue,system_db,system,boundary,enterprise_boundary,system_boundary,container_ext_db,container_ext,container_queue,container_db,container,container_boundary,component_ext_db,component_ext,component_queue,component_db,component,node,node_l,node_r,rel,birel,rel_u,rel_d,rel_l,rel_r,rel_b,rel_index,attribute>[)] { console.log('STOP attribute'); this.popState();console.log('STOP diagram'); this.popState();}
<attribute>",," { console.log(',,'); return 'ATTRIBUTE_EMPTY';}
<attribute>"," { console.log(','); }
<attribute>[ ]*["]["] { console.log('ATTRIBUTE_EMPTY'); return 'ATTRIBUTE_EMPTY';}
<attribute>[ ]*["] { console.log('begin string'); this.begin("string");}
<string>["] { console.log('STOP string'); this.popState(); }
<string>[^"]* { console.log('STR'); return "STR";}
<attribute>[^,]+ { console.log('not STR'); return "STR";}
'{' { /* this.begin("lbrace"); */ console.log('begin boundary block'); return "LBRACE";}
'}' { /* this.popState(); */ console.log('STOP boundary block'); return "RBRACE";}
[\s]+ return 'SPACE';
[\n\r]+ return 'EOL';
<<EOF>> return 'EOF';
/lex
/* operator associations and precedence */
%left '^'
%start start
%% /* language grammar */
start
: mermaidDoc
| direction
| directive start
;
direction
: direction_tb
{ yy.setDirection('TB');}
| direction_bt
{ yy.setDirection('BT');}
| direction_rl
{ yy.setDirection('RL');}
| direction_lr
{ yy.setDirection('LR');}
;
mermaidDoc
: graphConfig
;
directive
: openDirective typeDirective closeDirective NEWLINE
| openDirective typeDirective ':' argDirective closeDirective NEWLINE
;
openDirective
: open_directive { console.log("open_directive: ", $1); yy.parseDirective('%%{', 'open_directive'); }
;
typeDirective
: type_directive { }
;
argDirective
: arg_directive { $1 = $1.trim().replace(/'/g, '"'); console.log("arg_directive: ", $1); yy.parseDirective($1, 'arg_directive'); }
;
closeDirective
: close_directive { console.log("close_directive: ", $1); yy.parseDirective('}%%', 'close_directive', 'c4Context'); }
;
graphConfig
: C4_CONTEXT NEWLINE statements EOF {yy.setC4Type($1)}
| C4_CONTAINER NEWLINE statements EOF {yy.setC4Type($1)}
| C4_COMPONENT NEWLINE statements EOF {yy.setC4Type($1)}
| C4_DYNAMIC NEWLINE statements EOF {yy.setC4Type($1)}
| C4_DEPLOYMENT NEWLINE statements EOF {yy.setC4Type($1)}
;
statements
: otherStatements
| diagramStatements
| otherStatements diagramStatements
;
otherStatements
: otherStatement
| otherStatement NEWLINE
| otherStatement NEWLINE otherStatements
;
otherStatement
: title {yy.setTitle($1.substring(6));$$=$1.substring(6);}
| accDescription {yy.setAccDescription($1.substring(15));$$=$1.substring(15);}
;
boundaryStatement
: boundaryStartStatement diagramStatements boundaryStopStatement
;
boundaryStartStatement
: boundaryStart LBRACE NEWLINE
| boundaryStart NEWLINE LBRACE
| boundaryStart NEWLINE LBRACE NEWLINE
;
boundaryStart
: ENTERPRISE_BOUNDARY attributes {console.log($1,JSON.stringify($2)); $2.splice(2, 0, 'ENTERPRISE'); yy.addPersonOrSystemBoundary(...$2); $$=$2;}
| SYSTEM_BOUNDARY attributes {console.log($1,JSON.stringify($2)); $2.splice(2, 0, 'ENTERPRISE'); yy.addPersonOrSystemBoundary(...$2); $$=$2;}
| BOUNDARY attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystemBoundary(...$2); $$=$2;}
| CONTAINER_BOUNDARY attributes {console.log($1,JSON.stringify($2)); $2.splice(2, 0, 'CONTAINER'); yy.addContainerBoundary(...$2); $$=$2;}
| NODE attributes {console.log($1,JSON.stringify($2)); yy.addDeploymentNode('node', ...$2); $$=$2;}
| NODE_L attributes {console.log($1,JSON.stringify($2)); yy.addDeploymentNode('nodeL', ...$2); $$=$2;}
| NODE_R attributes {console.log($1,JSON.stringify($2)); yy.addDeploymentNode('nodeR', ...$2); $$=$2;}
;
boundaryStopStatement
: RBRACE { yy.popBoundaryParseStack() }
;
diagramStatements
: diagramStatement
| diagramStatement NEWLINE
| diagramStatement NEWLINE statements
;
diagramStatement
: PERSON attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('person', ...$2); $$=$2;}
| PERSON_EXT attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('external_person', ...$2); $$=$2;}
| SYSTEM attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('system', ...$2); $$=$2;}
| SYSTEM_DB attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('system_db', ...$2); $$=$2;}
| SYSTEM_QUEUE attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('system_queue', ...$2); $$=$2;}
| SYSTEM_EXT attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('external_system', ...$2); $$=$2;}
| SYSTEM_EXT_DB attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('external_system_db', ...$2); $$=$2;}
| SYSTEM_EXT_QUEUE attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('external_system_queue', ...$2); $$=$2;}
| CONTAINER attributes {console.log($1,JSON.stringify($2)); yy.addContainer('container', ...$2); $$=$2;}
| CONTAINER_DB attributes {console.log($1,JSON.stringify($2)); yy.addContainer('container_db', ...$2); $$=$2;}
| CONTAINER_QUEUE attributes {console.log($1,JSON.stringify($2)); yy.addContainer('container_queue', ...$2); $$=$2;}
| CONTAINER_EXT attributes {console.log($1,JSON.stringify($2)); yy.addContainer('external_container', ...$2); $$=$2;}
| CONTAINER_EXT_DB attributes {console.log($1,JSON.stringify($2)); yy.addContainer('external_container_db', ...$2); $$=$2;}
| CONTAINER_EXT_QUEUE attributes {console.log($1,JSON.stringify($2)); yy.addContainer('external_container_queue', ...$2); $$=$2;}
| COMPONENT attributes {console.log($1,JSON.stringify($2)); yy.addComponent('component', ...$2); $$=$2;}
| COMPONENT_DB attributes {console.log($1,JSON.stringify($2)); yy.addComponent('component_db', ...$2); $$=$2;}
| COMPONENT_QUEUE attributes {console.log($1,JSON.stringify($2)); yy.addComponent('component_queue', ...$2); $$=$2;}
| COMPONENT_EXT attributes {console.log($1,JSON.stringify($2)); yy.addComponent('external_component', ...$2); $$=$2;}
| COMPONENT_EXT_DB attributes {console.log($1,JSON.stringify($2)); yy.addComponent('external_component_db', ...$2); $$=$2;}
| COMPONENT_EXT_QUEUE attributes {console.log($1,JSON.stringify($2)); yy.addComponent('external_component_queue', ...$2); $$=$2;}
| boundaryStatement
| REL attributes {console.log($1,JSON.stringify($2)); yy.addRel('rel', ...$2); $$=$2;}
| BIREL attributes {console.log($1,JSON.stringify($2)); yy.addRel('birel', ...$2); $$=$2;}
| REL_U attributes {console.log($1,JSON.stringify($2)); yy.addRel('rel_u', ...$2); $$=$2;}
| REL_D attributes {console.log($1,JSON.stringify($2)); yy.addRel('rel_d', ...$2); $$=$2;}
| REL_L attributes {console.log($1,JSON.stringify($2)); yy.addRel('rel_l', ...$2); $$=$2;}
| REL_R attributes {console.log($1,JSON.stringify($2)); yy.addRel('rel_r', ...$2); $$=$2;}
| REL_B attributes {console.log($1,JSON.stringify($2)); yy.addRel('rel_b', ...$2); $$=$2;}
| REL_INDEX attributes {console.log($1,JSON.stringify($2)); $2.splice(0, 1); yy.addRel('rel', ...$2); $$=$2;}
;
attributes
: attribute { console.log('PUSH ATTRIBUTE: ', $1); $$ = [$1]; }
| attribute attributes { console.log('PUSH ATTRIBUTE: ', $1); $2.unshift($1); $$=$2;}
;
attribute
: STR { $$ = $1.trim(); }
| ATTRIBUTE { $$ = $1.trim(); }
| ATTRIBUTE_EMPTY { $$ = ""; }
;

View File

@@ -0,0 +1,8 @@
const getStyles = (options) =>
`.person {
stroke: ${options.personBorder};
fill: ${options.personBkg};
}
`;
export default getStyles;

884
src/diagrams/c4/svgDraw.js Normal file

File diff suppressed because one or more lines are too long

View File

@@ -5,8 +5,8 @@ import common from '../common/common';
import utils from '../../utils';
import mermaidAPI from '../../mermaidAPI';
import {
setTitle,
getTitle,
setAccTitle,
getAccTitle,
getAccDescription,
setAccDescription,
clear as commonClear,
@@ -142,7 +142,6 @@ export const addAnnotation = function (className, annotation) {
* @public
*/
export const addMember = function (className, member) {
console.log(className, member);
const validatedClassName = splitClassNameAndType(className).className;
const theClass = classes[validatedClassName];
@@ -356,8 +355,8 @@ const setDirection = (dir) => {
export default {
parseDirective,
setTitle,
getTitle,
setAccTitle,
getAccTitle,
getAccDescription,
setAccDescription,
getConfig: () => configApi.getConfig().class,

View File

@@ -110,14 +110,13 @@ describe('class diagram, ', function () {
' flightNumber : Integer\n' +
' departureTime : Date\n' +
'}';
let testPased = false;
let testPassed = false;
try {
parser.parse(str);
} catch (error) {
console.log(error.name);
testPased = true;
testPassed = true;
}
expect(testPased).toBe(true);
expect(testPassed).toBe(true);
});
it('should break when EOF is encountered before closing the first `{` while defining generic class with brackets', function () {
@@ -129,14 +128,13 @@ describe('class diagram, ', function () {
'}\n' +
'\n' +
'class Dummy_Class {\n';
let testPased = false;
let testPassed = false;
try {
parser.parse(str);
} catch (error) {
console.log(error.name);
testPased = true;
testPassed = true;
}
expect(testPased).toBe(true);
expect(testPassed).toBe(true);
});
it('should handle generic class with brackets', function () {
@@ -552,7 +550,7 @@ foo()
`;
parser.parse(str);
expect(parser.yy.getTitle()).toBe('My Title');
expect(parser.yy.getAccTitle()).toBe('My Title');
expect(parser.yy.getAccDescription()).toBe('My Description');
});
it('should handle accTitle and multiline accDescr', function () {
@@ -567,7 +565,7 @@ foo()
`;
parser.parse(str);
expect(parser.yy.getTitle()).toBe('My Title');
expect(parser.yy.getAccTitle()).toBe('My Title');
expect(parser.yy.getAccDescription()).toBe('This is mu multi\nline description');
});

View File

@@ -9,7 +9,7 @@ import { getConfig } from '../../config';
import { render } from '../../dagre-wrapper/index.js';
// import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js';
import { curveLinear } from 'd3';
import { interpolateToCurve, getStylesFromArray, configureSvgSize } from '../../utils';
import { interpolateToCurve, getStylesFromArray, setupGraphViewbox } from '../../utils';
import common from '../common/common';
import addSVGAccessibilityFields from '../../accessibility';
@@ -322,16 +322,6 @@ export const draw = function (text, id) {
const relations = classDb.getRelations();
log.info(relations);
// let i = 0;
// for (i = subGraphs.length - 1; i >= 0; i--) {
// subG = subGraphs[i];
// selectAll('cluster').append('text');
// for (let j = 0; j < subG.nodes.length; j++) {
// g.setParent(subG.nodes[j], subG.id);
// }
// }
addClasses(classes, g, id);
addRelations(relations, g);
@@ -354,28 +344,7 @@ export const draw = function (text, id) {
const element = root.select('#' + id + ' g');
render(element, g, ['aggregation', 'extension', 'composition', 'dependency'], 'classDiagram', id);
// element.selectAll('g.node').attr('title', function() {
// return flowDb.getTooltip(this.id);
// });
const padding = 8;
const svgBounds = svg.node().getBBox();
const width = svgBounds.width + padding * 2;
const height = svgBounds.height + padding * 2;
log.debug(
`new ViewBox 0 0 ${width} ${height}`,
`translate(${padding - g._label.marginx}, ${padding - g._label.marginy})`
);
configureSvgSize(svg, height, width, conf.useMaxWidth);
svg.attr('viewBox', `0 0 ${width} ${height}`);
svg
.select('g')
.attr('transform', `translate(${padding - g._label.marginx}, ${padding - svgBounds.y})`);
// Index nodes
// flowDb.indexNodes('subGraph' + i);
setupGraphViewbox(g, svg, conf.diagramPadding, conf.useMaxWidth);
// Add label rects for non html labels
if (!conf.htmlLabels) {

View File

@@ -263,7 +263,7 @@ statement
| cssClassStatement
| directive
| direction
| acc_title acc_title_value { $$=$2.trim();yy.setTitle($$); }
| acc_title acc_title_value { $$=$2.trim();yy.setAccTitle($$); }
| acc_descr acc_descr_value { $$=$2.trim();yy.setAccDescription($$); }
| acc_descr_multiline_value { $$=$1.trim();yy.setAccDescription($$); }
;

View File

@@ -100,7 +100,6 @@ describe('Sanitize text', function () {
securityLevel: 'strict',
flowchart: { htmlLabels: true },
});
console.log('result', result);
expect(result).not.toContain('javascript:alert(1)');
});
});

View File

@@ -3,8 +3,8 @@ import mermaidAPI from '../../mermaidAPI';
import * as configApi from '../../config';
import common from '../common/common';
import {
setTitle,
getTitle,
setAccTitle,
getAccTitle,
getAccDescription,
setAccDescription,
clear as commonClear,
@@ -93,8 +93,8 @@ export default {
addRelationship,
getRelationships,
clear,
setTitle,
getTitle,
setAccTitle,
getAccTitle,
setAccDescription,
getAccDescription,
};

View File

@@ -94,14 +94,15 @@ statement
}
| entityName BLOCK_START BLOCK_STOP { yy.addEntity($1); }
| entityName { yy.addEntity($1); }
| title title_value { $$=$2.trim();yy.setTitle($$); }
| acc_title acc_title_value { $$=$2.trim();yy.setTitle($$); }
| title title_value { $$=$2.trim();yy.setAccTitle($$); }
| acc_title acc_title_value { $$=$2.trim();yy.setAccTitle($$); }
| acc_descr acc_descr_value { $$=$2.trim();yy.setAccDescription($$); }
| acc_descr_multiline_value { $$=$1.trim();yy.setAccDescription($$); }
;
entityName
: 'ALPHANUM' { $$ = $1; /*console.log('Entity: ' + $1);*/ }
| 'ALPHANUM' '.' entityName { $$ = $1 + $2 + $3; }
;
attributes

View File

@@ -191,7 +191,7 @@ describe('when parsing ER diagram it...', function () {
accDescr: this graph is about stuff
${line1}`
);
expect(erDb.getTitle()).toBe('graph title');
expect(erDb.getAccTitle()).toBe('graph title');
expect(erDb.getAccDescription()).toBe('this graph is about stuff');
});
@@ -207,7 +207,7 @@ describe('when parsing ER diagram it...', function () {
}\n
${line1}`
);
expect(erDb.getTitle()).toBe('graph title');
expect(erDb.getAccTitle()).toBe('graph title');
expect(erDb.getAccDescription()).toBe('this graph is about stuff');
});
@@ -426,4 +426,10 @@ describe('when parsing ER diagram it...', function () {
const rels = erDb.getRelationships();
expect(rels[0].roleA).toBe('places');
});
it('should allow an entity name with a dot', function () {
erDiagram.parser.parse('erDiagram\nCUSTOMER.PROP ||--|{ ORDER : places');
const rels = erDb.getRelationships();
expect(rels[0].entityA).toBe('CUSTOMER.PROP');
});
});

View File

@@ -5,8 +5,8 @@ import common from '../common/common';
import mermaidAPI from '../../mermaidAPI';
import { log } from '../../logger';
import {
setTitle,
getTitle,
setAccTitle,
getAccTitle,
getAccDescription,
setAccDescription,
clear as commonClear,
@@ -746,8 +746,8 @@ const makeUniq = (sg, allSubgraphs) => {
export default {
parseDirective,
defaultConfig: () => configApi.defaultConfig.flowchart,
setTitle,
getTitle,
setAccTitle,
getAccTitle,
getAccDescription,
setAccDescription,
addVertex,

View File

@@ -9,7 +9,7 @@ import { render } from '../../dagre-wrapper/index.js';
import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js';
import { log } from '../../logger';
import common, { evaluate } from '../common/common';
import { interpolateToCurve, getStylesFromArray, configureSvgSize } from '../../utils';
import { interpolateToCurve, getStylesFromArray, setupGraphViewbox } from '../../utils';
import addSVGAccessibilityFields from '../../accessibility';
const conf = {};
@@ -452,21 +452,7 @@ export const draw = function (text, id) {
const element = root.select('#' + id + ' g');
render(element, g, ['point', 'circle', 'cross'], 'flowchart', id);
const padding = conf.diagramPadding;
const svgBounds = svg.node().getBBox();
const width = svgBounds.width + padding * 2;
const height = svgBounds.height + padding * 2;
log.debug(
`new ViewBox 0 0 ${width} ${height}`,
`translate(${padding - g._label.marginx}, ${padding - g._label.marginy})`
);
configureSvgSize(svg, height, width, conf.useMaxWidth);
svg.attr('viewBox', `0 0 ${width} ${height}`);
svg
.select('g')
.attr('transform', `translate(${padding - g._label.marginx}, ${padding - svgBounds.y})`);
setupGraphViewbox(g, svg, conf.diagramPadding, conf.useMaxWidth);
// Index nodes
flowDb.indexNodes('subGraph' + i);

View File

@@ -9,7 +9,7 @@ import dagreD3 from 'dagre-d3';
import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js';
import { log } from '../../logger';
import common, { evaluate } from '../common/common';
import { interpolateToCurve, getStylesFromArray, configureSvgSize } from '../../utils';
import { interpolateToCurve, getStylesFromArray, setupGraphViewbox } from '../../utils';
import flowChartShapes from './flowChartShapes';
import addSVGAccessibilityFields from '../../accessibility';
@@ -427,8 +427,6 @@ export const draw = function (text, id) {
const svg = root.select(`[id="${id}"]`);
svg.attr('xmlns:xlink', 'http://www.w3.org/1999/xlink');
log.warn(g);
// Adds title and description to the flow chart
addSVGAccessibilityFields(parser.yy, svg, id);
@@ -440,18 +438,6 @@ export const draw = function (text, id) {
return flowDb.getTooltip(this.id);
});
const padding = conf.diagramPadding;
const svgBounds = svg.node().getBBox();
const width = svgBounds.width + padding * 2;
const height = svgBounds.height + padding * 2;
configureSvgSize(svg, height, width, conf.useMaxWidth);
// Ensure the viewBox includes the whole svgBounds area with extra space for padding
const vBox = `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`;
log.debug(`viewBox ${vBox}`);
svg.attr('viewBox', vBox);
// Index nodes
flowDb.indexNodes('subGraph' + i);
@@ -468,10 +454,10 @@ export const draw = function (text, id) {
const xPos = clusterRects[0].x.baseVal.value;
const yPos = clusterRects[0].y.baseVal.value;
const width = clusterRects[0].width.baseVal.value;
const _width = clusterRects[0].width.baseVal.value;
const cluster = select(clusterEl[0]);
const te = cluster.select('.label');
te.attr('transform', `translate(${xPos + width / 2}, ${yPos + 14})`);
te.attr('transform', `translate(${xPos + _width / 2}, ${yPos + 14})`);
te.attr('id', id + 'Text');
for (let j = 0; j < subG.classes.length; j++) {
@@ -499,6 +485,7 @@ export const draw = function (text, id) {
label.insertBefore(rect, label.firstChild);
}
}
setupGraphViewbox(g, svg, conf.diagramPadding, conf.useMaxWidth);
// If node has a link, wrap it in an anchor SVG object.
const keys = Object.keys(vert);

Some files were not shown because too many files have changed in this diff Show More