Merge branch next into add-pie-langium-parser

This commit is contained in:
Reda Al Sulais 2023-11-14 20:04:16 +03:00
commit 4c43bae92d
166 changed files with 5498 additions and 1704 deletions

View File

@ -17,6 +17,7 @@ const MERMAID_CONFIG_DIAGRAM_KEYS = [
'er', 'er',
'pie', 'pie',
'quadrantChart', 'quadrantChart',
'xyChart',
'requirement', 'requirement',
'mindmap', 'mindmap',
'timeline', 'timeline',
@ -34,7 +35,7 @@ const MERMAID_CONFIG_DIAGRAM_KEYS = [
* @param mermaidConfigSchema - The Mermaid JSON Schema to use. * @param mermaidConfigSchema - The Mermaid JSON Schema to use.
* @returns The default mermaid config object. * @returns The default mermaid config object.
*/ */
export function generateDefaults(mermaidConfigSchema: JSONSchemaType<MermaidConfig>) { function generateDefaults(mermaidConfigSchema: JSONSchemaType<MermaidConfig>) {
const ajv = new Ajv2019({ const ajv = new Ajv2019({
useDefaults: true, useDefaults: true,
allowUnionTypes: true, allowUnionTypes: true,

View File

@ -16,12 +16,12 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v2
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
cache: pnpm cache: pnpm
node-version: 18 node-version: 18
@ -29,7 +29,7 @@ jobs:
- name: Install Packages - name: Install Packages
run: pnpm install --frozen-lockfile run: pnpm install --frozen-lockfile
- name: Verify release verion - name: Verify release version
if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release')) }} if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release')) }}
run: pnpm --filter mermaid run docs:verify-version run: pnpm --filter mermaid run docs:verify-version

View File

@ -19,13 +19,13 @@ jobs:
matrix: matrix:
node-version: [18.x] node-version: [18.x]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json # uses version from "packageManager" field in package.json
- name: Setup Node.js ${{ matrix.node-version }} - name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
cache: pnpm cache: pnpm
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}

View File

@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Check for difference in README.md and docs/README.md - name: Check for difference in README.md and docs/README.md
run: | run: |

View File

@ -15,7 +15,7 @@ jobs:
name: check tests name: check tests
if: github.repository_owner == 'mermaid-js' if: github.repository_owner == 'mermaid-js'
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: testomatio/check-tests@stable - uses: testomatio/check-tests@stable

View File

@ -29,7 +29,7 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v3 uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL

View File

@ -1,6 +1,6 @@
# Dependency Review Action # Dependency Review Action
# #
# This Action will scan dependency manifest files that change as part of a Pull Reqest, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging. # This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging.
# #
# Source repository: https://github.com/actions/dependency-review-action # Source repository: https://github.com/actions/dependency-review-action
# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement # Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement
@ -15,6 +15,6 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: 'Checkout Repository' - name: 'Checkout Repository'
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: 'Dependency Review' - name: 'Dependency Review'
uses: actions/dependency-review-action@v3 uses: actions/dependency-review-action@v3

View File

@ -30,13 +30,13 @@ jobs:
run: | run: |
echo "::error,title=Not using Applitols::APPLITOOLS_API_KEY is empty, disabling Applitools for this run." echo "::error,title=Not using Applitols::APPLITOOLS_API_KEY is empty, disabling Applitools for this run."
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json # uses version from "packageManager" field in package.json
- name: Setup Node.js ${{ matrix.node-version }} - name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}

View File

@ -17,13 +17,13 @@ jobs:
node-version: [18.x] node-version: [18.x]
containers: [1, 2, 3, 4] containers: [1, 2, 3, 4]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json # uses version from "packageManager" field in package.json
- name: Setup Node.js ${{ matrix.node-version }} - name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}

View File

@ -26,7 +26,7 @@ jobs:
# lychee only uses the GITHUB_TOKEN to avoid rate-limiting # lychee only uses the GITHUB_TOKEN to avoid rate-limiting
contents: read contents: read
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Restore lychee cache - name: Restore lychee cache
uses: actions/cache@v3 uses: actions/cache@v3

View File

@ -20,13 +20,13 @@ jobs:
matrix: matrix:
node-version: [18.x] node-version: [18.x]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json # uses version from "packageManager" field in package.json
- name: Setup Node.js ${{ matrix.node-version }} - name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
cache: pnpm cache: pnpm
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}

View File

@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout Repository - name: Checkout Repository
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Validate Configuration - name: Validate Configuration
uses: Yash-Singh1/pr-labeler-config-validator@releases/v0.0.3 uses: Yash-Singh1/pr-labeler-config-validator@releases/v0.0.3
with: with:

View File

@ -23,12 +23,12 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v2
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
cache: pnpm cache: pnpm
node-version: 18 node-version: 18

View File

@ -9,14 +9,14 @@ jobs:
publish-preview: publish-preview:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v2
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
cache: pnpm cache: pnpm
node-version: 18.x node-version: 18.x

View File

@ -8,14 +8,14 @@ jobs:
publish: publish:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: fregante/setup-git-user@v2 - uses: fregante/setup-git-user@v2
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json # uses version from "packageManager" field in package.json
- name: Setup Node.js v18 - name: Setup Node.js v18
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
cache: pnpm cache: pnpm
node-version: 18.x node-version: 18.x

View File

@ -12,13 +12,13 @@ jobs:
matrix: matrix:
node-version: [18.x] node-version: [18.x]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json # uses version from "packageManager" field in package.json
- name: Setup Node.js ${{ matrix.node-version }} - name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
cache: pnpm cache: pnpm
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}

View File

@ -8,7 +8,7 @@ jobs:
update-browser-list: update-browser-list:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- run: npx browserslist@latest --update-db - run: npx browserslist@latest --update-db
- name: Commit changes - name: Commit changes
uses: EndBug/add-and-commit@v9 uses: EndBug/add-and-commit@v9

View File

@ -68,7 +68,7 @@ try {
### Init deprecated and InitThrowsErrors removed ### Init deprecated and InitThrowsErrors removed
The config passed to `init` was not being used eariler. The config passed to `init` was not being used earlier.
It will now be used. It will now be used.
The `init` function is deprecated and will be removed in the next major release. The `init` function is deprecated and will be removed in the next major release.
init currently works as a wrapper to `initialize` and `run`. init currently works as a wrapper to `initialize` and `run`.
@ -195,7 +195,7 @@ mermaid.run({
- "Cannot activate" in sequenceDiagram [\#647](https://github.com/knsv/mermaid/issues/647) - "Cannot activate" in sequenceDiagram [\#647](https://github.com/knsv/mermaid/issues/647)
- Link \("click" statement\) in flowchart does not work in exported SVG [\#646](https://github.com/knsv/mermaid/issues/646) - Link \("click" statement\) in flowchart does not work in exported SVG [\#646](https://github.com/knsv/mermaid/issues/646)
- How to pass styling [\#639](https://github.com/knsv/mermaid/issues/639) - How to pass styling [\#639](https://github.com/knsv/mermaid/issues/639)
- The live editor cant show seq diagram with notes for 8.0.0-alpha.3 [\#638](https://github.com/knsv/mermaid/issues/638) - The live editor can't show seq diagram with notes for 8.0.0-alpha.3 [\#638](https://github.com/knsv/mermaid/issues/638)
- import mermaid.css with ES6 + NPM [\#634](https://github.com/knsv/mermaid/issues/634) - import mermaid.css with ES6 + NPM [\#634](https://github.com/knsv/mermaid/issues/634)
- Actor line cuts through other elements [\#633](https://github.com/knsv/mermaid/issues/633) - Actor line cuts through other elements [\#633](https://github.com/knsv/mermaid/issues/633)
- Graph TD line out of the picture \(left side\) [\#630](https://github.com/knsv/mermaid/issues/630) - Graph TD line out of the picture \(left side\) [\#630](https://github.com/knsv/mermaid/issues/630)
@ -504,7 +504,7 @@ mermaid.run({
- Docs css: code hard to read [\#324](https://github.com/knsv/mermaid/issues/324) - Docs css: code hard to read [\#324](https://github.com/knsv/mermaid/issues/324)
- About Markpad integration [\#323](https://github.com/knsv/mermaid/issues/323) - About Markpad integration [\#323](https://github.com/knsv/mermaid/issues/323)
- How to link backwords in flowchat? [\#321](https://github.com/knsv/mermaid/issues/321) - How to link backwards in flowchat? [\#321](https://github.com/knsv/mermaid/issues/321)
- Help with editor [\#310](https://github.com/knsv/mermaid/issues/310) - Help with editor [\#310](https://github.com/knsv/mermaid/issues/310)
- +1 [\#293](https://github.com/knsv/mermaid/issues/293) - +1 [\#293](https://github.com/knsv/mermaid/issues/293)
- Basic chart does not render on Chome, but does in Firefox [\#290](https://github.com/knsv/mermaid/issues/290) - Basic chart does not render on Chome, but does in Firefox [\#290](https://github.com/knsv/mermaid/issues/290)
@ -619,7 +619,7 @@ mermaid.run({
- render to png from the cli does not display the marker-end arrow heads [\#181](https://github.com/knsv/mermaid/issues/181) - render to png from the cli does not display the marker-end arrow heads [\#181](https://github.com/knsv/mermaid/issues/181)
- Links in sequence diagrams [\#159](https://github.com/knsv/mermaid/issues/159) - Links in sequence diagrams [\#159](https://github.com/knsv/mermaid/issues/159)
- comment characters `%%` cause parse error [\#141](https://github.com/knsv/mermaid/issues/141) - comment characters `%%` cause parse error [\#141](https://github.com/knsv/mermaid/issues/141)
- Add a reversed assymetric shape [\#124](https://github.com/knsv/mermaid/issues/124) - Add a reversed asymmetric shape [\#124](https://github.com/knsv/mermaid/issues/124)
- Add syntax for double headed arrows [\#123](https://github.com/knsv/mermaid/issues/123) - Add syntax for double headed arrows [\#123](https://github.com/knsv/mermaid/issues/123)
- Support for font-awesome [\#49](https://github.com/knsv/mermaid/issues/49) - Support for font-awesome [\#49](https://github.com/knsv/mermaid/issues/49)
@ -659,7 +659,7 @@ mermaid.run({
- Auto linewrap for notes in sequence diagrams [\#178](https://github.com/knsv/mermaid/issues/178) - Auto linewrap for notes in sequence diagrams [\#178](https://github.com/knsv/mermaid/issues/178)
- Execute code after initialize [\#176](https://github.com/knsv/mermaid/issues/176) - Execute code after initialize [\#176](https://github.com/knsv/mermaid/issues/176)
- Autoscaling for all diagram types [\#175](https://github.com/knsv/mermaid/issues/175) - Autoscaling for all diagram types [\#175](https://github.com/knsv/mermaid/issues/175)
- Problem wit click event callback [\#174](https://github.com/knsv/mermaid/issues/174) - Problem with click event callback [\#174](https://github.com/knsv/mermaid/issues/174)
- How to escape characters? [\#170](https://github.com/knsv/mermaid/issues/170) - How to escape characters? [\#170](https://github.com/knsv/mermaid/issues/170)
- it can not work [\#167](https://github.com/knsv/mermaid/issues/167) - it can not work [\#167](https://github.com/knsv/mermaid/issues/167)
- UML Class diagram [\#154](https://github.com/knsv/mermaid/issues/154) - UML Class diagram [\#154](https://github.com/knsv/mermaid/issues/154)
@ -762,7 +762,7 @@ mermaid.run({
- subgraph background is black in rendered flowchart PNG via CLI [\#121](https://github.com/knsv/mermaid/issues/121) - subgraph background is black in rendered flowchart PNG via CLI [\#121](https://github.com/knsv/mermaid/issues/121)
- Integrate editor at https://github.com/naseer/mermaid-webapp [\#110](https://github.com/knsv/mermaid/issues/110) - Integrate editor at https://github.com/naseer/mermaid-webapp [\#110](https://github.com/knsv/mermaid/issues/110)
- Internet Explorer Support [\#99](https://github.com/knsv/mermaid/issues/99) - Internet Explorer Support [\#99](https://github.com/knsv/mermaid/issues/99)
- Assymetric shapes not documented [\#82](https://github.com/knsv/mermaid/issues/82) - Asymmetric shapes not documented [\#82](https://github.com/knsv/mermaid/issues/82)
- NoModificationAllowedError [\#23](https://github.com/knsv/mermaid/issues/23) - NoModificationAllowedError [\#23](https://github.com/knsv/mermaid/issues/23)
- Improve arrows [\#3](https://github.com/knsv/mermaid/issues/3) - Improve arrows [\#3](https://github.com/knsv/mermaid/issues/3)
@ -908,7 +908,7 @@ mermaid.run({
- Question marks don't render properly with /dist/mermaid.full.min.js [\#30](https://github.com/knsv/mermaid/issues/30) - Question marks don't render properly with /dist/mermaid.full.min.js [\#30](https://github.com/knsv/mermaid/issues/30)
- Error with some characters [\#25](https://github.com/knsv/mermaid/issues/25) - Error with some characters [\#25](https://github.com/knsv/mermaid/issues/25)
- Provide parse function in browser widthout `require`? [\#21](https://github.com/knsv/mermaid/issues/21) - Provide parse function in browser without `require`? [\#21](https://github.com/knsv/mermaid/issues/21)
- Better label text support [\#18](https://github.com/knsv/mermaid/issues/18) - Better label text support [\#18](https://github.com/knsv/mermaid/issues/18)
- Cap-cased words break parser [\#8](https://github.com/knsv/mermaid/issues/8) - Cap-cased words break parser [\#8](https://github.com/knsv/mermaid/issues/8)

View File

@ -34,7 +34,7 @@ Try Live Editor previews of future releases: <a href="https://develop.git.mermai
[![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid) [![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid)
[![NPM Downloads](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid) [![NPM Downloads](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid)
[![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE)
[![Twitter Follow](https://img.shields.io/badge/Social-mermaidjs__-blue?style=social&logo=twitter)](https://twitter.com/mermaidjs_) [![Twitter Follow](https://img.shields.io/badge/Social-mermaidjs__-blue?style=social&logo=X)](https://twitter.com/mermaidjs_)
<img src="./img/header.png" alt="" /> <img src="./img/header.png" alt="" />
@ -44,6 +44,22 @@ Try Live Editor previews of future releases: <a href="https://develop.git.mermai
<a href="https://mermaid-js.github.io/mermaid/landing/"><img src="https://github.com/mermaid-js/mermaid/blob/master/docs/intro/img/book-banner-post-release.jpg" alt="Explore Mermaid.js in depth, with real-world examples, tips & tricks from the creator... The first official book on Mermaid is available for purchase. Check it out!"></a> <a href="https://mermaid-js.github.io/mermaid/landing/"><img src="https://github.com/mermaid-js/mermaid/blob/master/docs/intro/img/book-banner-post-release.jpg" alt="Explore Mermaid.js in depth, with real-world examples, tips & tricks from the creator... The first official book on Mermaid is available for purchase. Check it out!"></a>
## Table of content
<details>
<summary>Expand contents</summary>
- [About](#about)
- [Examples](#examples)
- [Release](#release)
- [Related projects](#related-projects)
- [Contributors](#contributors)
- [Security and safe diagrams](#security-and-safe-diagrams)
- [Reporting vulnerabilities](#reporting-vulnerabilities)
- [Appreciation](#appreciation)
</details>
## About ## About
<!-- <Main description> --> <!-- <Main description> -->
@ -58,7 +74,7 @@ Mermaid addresses this problem by enabling users to create easily modifiable dia
<br/> <br/>
Mermaid allows even non-programmers to easily create detailed diagrams through the [Mermaid Live Editor](https://mermaid.live/).<br/> Mermaid allows even non-programmers to easily create detailed diagrams through the [Mermaid Live Editor](https://mermaid.live/).<br/>
[Tutorials](./docs/config/Tutorials.md) has video tutorials. For video tutorials, visit our [Tutorials](./docs/config/Tutorials.md) page.
Use Mermaid with your favorite applications, check out the list of [Integrations and Usages of Mermaid](./docs/ecosystem/integrations-community.md). Use Mermaid with your favorite applications, check out the list of [Integrations and Usages of Mermaid](./docs/ecosystem/integrations-community.md).
You can also use Mermaid within [GitHub](https://github.blog/2022-02-14-include-diagrams-markdown-files-mermaid/) as well many of your other favorite applications—check out the list of [Integrations and Usages of Mermaid](./docs/ecosystem/integrations-community.md). You can also use Mermaid within [GitHub](https://github.blog/2022-02-14-include-diagrams-markdown-files-mermaid/) as well many of your other favorite applications—check out the list of [Integrations and Usages of Mermaid](./docs/ecosystem/integrations-community.md).

View File

@ -35,7 +35,7 @@ Mermaid
[![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid) [![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid)
[![NPM Downloads](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid) [![NPM Downloads](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid)
[![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE)
[![Twitter Follow](https://img.shields.io/badge/Social-mermaidjs__-blue?style=social&logo=twitter)](https://twitter.com/mermaidjs_) [![Twitter Follow](https://img.shields.io/badge/Social-mermaidjs__-blue?style=social&logo=X)](https://twitter.com/mermaidjs_)
<img src="./img/header.png" alt="" /> <img src="./img/header.png" alt="" />

View File

@ -160,6 +160,7 @@
"vitepress", "vitepress",
"vueuse", "vueuse",
"xlink", "xlink",
"xychart",
"yash", "yash",
"yokozuna", "yokozuna",
"zenuml", "zenuml",

View File

@ -501,4 +501,16 @@ describe('Class diagram', () => {
B : -methods() B : -methods()
`); `);
}); });
it('should handle notes with anchor tag having target attribute', () => {
renderGraph(
`classDiagram
class test { }
note for test "<a href='https://mermaid.js.org/' target="_blank"><code>note about mermaid</code></a>"`
);
cy.get('svg').then((svg) => {
cy.get('a').should('have.attr', 'target', '_blank').should('have.attr', 'rel', 'noopener');
});
});
}); });

View File

@ -26,7 +26,7 @@ describe('Git Graph diagram', () => {
`gitGraph `gitGraph
commit id: "Normal Commit" commit id: "Normal Commit"
commit id: "Reverse Commit" type: REVERSE commit id: "Reverse Commit" type: REVERSE
commit id: "Hightlight Commit" type: HIGHLIGHT commit id: "Highlight Commit" type: HIGHLIGHT
`, `,
{} {}
); );
@ -36,7 +36,7 @@ describe('Git Graph diagram', () => {
`gitGraph `gitGraph
commit id: "Normal Commit with tag" tag: "v1.0.0" commit id: "Normal Commit with tag" tag: "v1.0.0"
commit id: "Reverse Commit with tag" type: REVERSE tag: "RC_1" commit id: "Reverse Commit with tag" type: REVERSE tag: "RC_1"
commit id: "Hightlight Commit" type: HIGHLIGHT tag: "8.8.4" commit id: "Highlight Commit" type: HIGHLIGHT tag: "8.8.4"
`, `,
{} {}
); );
@ -102,7 +102,7 @@ describe('Git Graph diagram', () => {
{} {}
); );
}); });
it('8: should render a simple gitgraph with more than 8 branchs & overriding variables', () => { it('8: should render a simple gitgraph with more than 8 branches & overriding variables', () => {
imgSnapshotTest( imgSnapshotTest(
`%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': { `%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': {
'gitBranchLabel0': '#ffffff', 'gitBranchLabel0': '#ffffff',
@ -358,7 +358,7 @@ gitGraph
`gitGraph TB: `gitGraph TB:
commit id: "Normal Commit" commit id: "Normal Commit"
commit id: "Reverse Commit" type: REVERSE commit id: "Reverse Commit" type: REVERSE
commit id: "Hightlight Commit" type: HIGHLIGHT commit id: "Highlight Commit" type: HIGHLIGHT
`, `,
{} {}
); );
@ -368,7 +368,7 @@ gitGraph
`gitGraph TB: `gitGraph TB:
commit id: "Normal Commit with tag" tag: "v1.0.0" commit id: "Normal Commit with tag" tag: "v1.0.0"
commit id: "Reverse Commit with tag" type: REVERSE tag: "RC_1" commit id: "Reverse Commit with tag" type: REVERSE tag: "RC_1"
commit id: "Hightlight Commit" type: HIGHLIGHT tag: "8.8.4" commit id: "Highlight Commit" type: HIGHLIGHT tag: "8.8.4"
`, `,
{} {}
); );
@ -434,7 +434,7 @@ gitGraph
{} {}
); );
}); });
it('22: should render a simple gitgraph with more than 8 branchs & overriding variables | Vertical Branch', () => { it('22: should render a simple gitgraph with more than 8 branches & overriding variables | Vertical Branch', () => {
imgSnapshotTest( imgSnapshotTest(
`%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': { `%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': {
'gitBranchLabel0': '#ffffff', 'gitBranchLabel0': '#ffffff',

View File

@ -57,7 +57,7 @@ describe('Timeline diagram', () => {
{} {}
); );
}); });
it('5: should render a simple timeline with directive overriden colors', () => { it('5: should render a simple timeline with directive overridden colors', () => {
imgSnapshotTest( imgSnapshotTest(
` %%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': { ` %%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': {
'cScale0': '#ff0000', 'cScale0': '#ff0000',

View File

@ -0,0 +1,322 @@
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
describe('XY Chart', () => {
it('should render the simplest possible chart', () => {
imgSnapshotTest(
`
xychart-beta
line [10, 30, 20]
`,
{}
);
cy.get('svg');
});
it('Should render a complete chart', () => {
imgSnapshotTest(
`
xychart-beta
title "Sales Revenue"
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`,
{}
);
});
it('Should render a chart without title', () => {
imgSnapshotTest(
`
xychart-beta
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`,
{}
);
cy.get('svg');
});
it('y-axis title not required', () => {
imgSnapshotTest(
`
xychart-beta
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`,
{}
);
cy.get('svg');
});
it('Should render a chart without y-axis with different range', () => {
imgSnapshotTest(
`
xychart-beta
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
bar [5000, 6000, 7500, 8200, 9500, 10500, 14000, 3200, 9200, 9900, 3400, 6000]
line [2000, 7000, 6500, 9200, 9500, 7500, 11000, 10200, 3200, 8500, 7000, 8800]
`,
{}
);
cy.get('svg');
});
it('x axis title not required', () => {
imgSnapshotTest(
`
xychart-beta
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
bar [5000, 6000, 7500, 8200, 9500, 10500, 14000, 3200, 9200, 9900, 3400, 6000]
line [2000, 7000, 6500, 9200, 9500, 7500, 11000, 10200, 3200, 8500, 7000, 8800]
`,
{}
);
cy.get('svg');
});
it('Multiple plots can be rendered', () => {
imgSnapshotTest(
`
xychart-beta
line [23, 46, 77, 34]
line [45, 32, 33, 12]
bar [87, 54, 99, 85]
line [78, 88, 22, 4]
line [22, 29, 75, 33]
bar [52, 96, 35, 10]
`,
{}
);
cy.get('svg');
});
it('Decimals and negative numbers are supported', () => {
imgSnapshotTest(
`
xychart-beta
y-axis -2.4 --> 3.5
line [+1.3, .6, 2.4, -.34]
`,
{}
);
cy.get('svg');
});
it('Render spark line with "plotReservedSpacePercent"', () => {
imgSnapshotTest(
`
---
config:
theme: dark
xyChart:
width: 200
height: 20
plotReservedSpacePercent: 100
---
xychart-beta
line [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800]
`,
{}
);
cy.get('svg');
});
it('Render spark bar without displaying other property', () => {
imgSnapshotTest(
`
---
config:
theme: dark
xyChart:
width: 200
height: 20
xAxis:
showLabel: false
showTitle: false
showTick: false
showAxisLine: false
yAxis:
showLabel: false
showTitle: false
showTick: false
showAxisLine: false
---
xychart-beta
bar [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800]
`,
{}
);
cy.get('svg');
});
it('Should use all the config from directive', () => {
imgSnapshotTest(
`
%%{init: {"xyChart": {"width": 1000, "height": 600, "titlePadding": 5, "titleFontSize": 10, "xAxis": {"labelFontSize": "20", "labelPadding": 10, "titleFontSize": 30, "titlePadding": 20, "tickLength": 10, "tickWidth": 5}, "yAxis": {"labelFontSize": "20", "labelPadding": 10, "titleFontSize": 30, "titlePadding": 20, "tickLength": 10, "tickWidth": 5}, "plotBorderWidth": 5, "chartOrientation": "horizontal", "plotReservedSpacePercent": 60 }}}%%
xychart-beta
title "Sales Revenue"
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`,
{}
);
cy.get('svg');
});
it('Should use all the config from yaml', () => {
imgSnapshotTest(
`
---
config:
theme: forest
xyChart:
width: 1000
height: 600
titlePadding: 5
titleFontSize: 10
xAxis:
labelFontSize: 20
labelPadding: 10
titleFontSize: 30
titlePadding: 20
tickLength: 10
tickWidth: 5
axisLineWidth: 5
yAxis:
labelFontSize: 20
labelPadding: 10
titleFontSize: 30
titlePadding: 20
tickLength: 10
tickWidth: 5
axisLineWidth: 5
chartOrientation: horizontal
plotReservedSpacePercent: 60
---
xychart-beta
title "Sales Revenue"
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`,
{}
);
cy.get('svg');
});
it('Render with show axis title false', () => {
imgSnapshotTest(
`
---
config:
xyChart:
xAxis:
showTitle: false
yAxis:
showTitle: false
---
xychart-beta
title "Sales Revenue"
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`,
{}
);
cy.get('svg');
});
it('Render with show axis label false', () => {
imgSnapshotTest(
`
---
config:
xyChart:
xAxis:
showLabel: false
yAxis:
showLabel: false
---
xychart-beta
title "Sales Revenue"
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`,
{}
);
cy.get('svg');
});
it('Render with show axis tick false', () => {
imgSnapshotTest(
`
---
config:
xyChart:
xAxis:
showTick: false
yAxis:
showTick: false
---
xychart-beta
title "Sales Revenue"
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`,
{}
);
cy.get('svg');
});
it('Render with show axis line false', () => {
imgSnapshotTest(
`
---
config:
xyChart:
xAxis:
showAxisLine: false
yAxis:
showAxisLine: false
---
xychart-beta
title "Sales Revenue"
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`,
{}
);
cy.get('svg');
});
it('Render all the theme color', () => {
imgSnapshotTest(
`
---
config:
themeVariables:
xyChart:
titleColor: "#ff0000"
backgroundColor: "#f0f8ff"
yAxisLabelColor: "#ee82ee"
yAxisTitleColor: "#7fffd4"
yAxisTickColor: "#87ceeb"
yAxisLineColor: "#ff6347"
xAxisLabelColor: "#7fffd4"
xAxisTitleColor: "#ee82ee"
xAxisTickColor: "#ff6347"
xAxisLineColor: "#87ceeb"
plotColorPalette: "#008000, #faba63"
---
xychart-beta
title "Sales Revenue"
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`,
{}
);
cy.get('svg');
});
});

View File

@ -58,8 +58,19 @@
</head> </head>
<body> <body>
<pre id="diagram" class="mermaid"> <pre id="diagram" class="mermaid">
classDiagram flowchart TB
`Class<img src=x onerror=alert(1)>` <|-- `Class2<img src=x onerror=alert(2)>` C & D & E & F & G & H & I & J & K & L & M & N & O & P & Q & R & S & T & U & V & W & X & Y & Z & A1 & A2 & A3 & A4 & A5 & A6 & A7 & A8
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------->
C & D & E & F & G & H & I & J & K & L & M & N & O & P & Q & R & S & T & U & V & W & X & Y & Z & A1 & A2 & A3 & A4 & A5 & A6 & A7 & A8
</pre>
<pre id="diagram" class="mermaid2">
flowchart TB
A & A & A & A & A & A & A & A ---> C & D & E & F & G & H & I & J & K & L & M & N & O & P & Q & R & S & T & U & V & W & X & Y & Z
</pre>
<pre id="diagram" class="mermaid2">
flowchart TB
A1 & A2 & A3 & A4 & A5 & A6 & A7 & A8 --> C & D & E & F & G & H & I & J & K & L & M & N & O & P & Q & R & S & T & U & V & W & X & Y & Z
</pre> </pre>
<pre id="diagram" class="mermaid2"> <pre id="diagram" class="mermaid2">
flowchart flowchart
@ -439,6 +450,7 @@ mindmap
messageFontFamily: 'courier', messageFontFamily: 'courier',
}, },
fontSize: 16, fontSize: 16,
logLevel: 0,
}); });
function callback() { function callback() {
alert('It worked'); alert('It worked');

View File

@ -173,7 +173,7 @@
Container(mobile, "Mobile App", "Xamarin", "Provides a limited subset of the Internet Banking functionality to customers via their mobile device.") 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(comp, "Customer's computer", "Microsoft Windows or Apple macOS"){
Deployment_Node(browser, "Web Browser", "Google Chrome, Mozilla Firefox,<br/> Apple Safari or Microsoft Edge"){ 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.") Container(spa, "Single Page Application", "JavaScript and Angular", "Provides all of the Internet Banking functionality to customers via their web browser.")
} }

View File

@ -22,7 +22,7 @@
--- ---
graph LR graph LR
accTitle: This is a complicated flow accTitle: This is a complicated flow
accDescr: This is the descriptoin for the complicated flow. accDescr: This is the description for the complicated flow.
sid-B3655226-6C29-4D00-B685-3D5C734DC7E1[" sid-B3655226-6C29-4D00-B685-3D5C734DC7E1["

View File

@ -60,6 +60,9 @@
<li> <li>
<h2><a href="./quadrantchart.html">Quadrant charts</a></h2> <h2><a href="./quadrantchart.html">Quadrant charts</a></h2>
</li> </li>
<li>
<h2><a href="./xychart.html">XY charts</a></h2>
</li>
<li> <li>
<h2><a href="./requirements.html">Requirements</a></h2> <h2><a href="./requirements.html">Requirements</a></h2>
</li> </li>

View File

@ -17,7 +17,7 @@
<h1>Requirement diagram demos</h1> <h1>Requirement diagram demos</h1>
<pre class="mermaid"> <pre class="mermaid">
requirementDiagram requirementDiagram
accTitle: Requirments demo in black and white accTitle: Requirements demo in black and white
accDescr: A series of requirement boxes showing relationships among them. Has meaningless task names accDescr: A series of requirement boxes showing relationships among them. Has meaningless task names
requirement test_req { requirement test_req {

View File

@ -164,6 +164,13 @@
end end
</pre> </pre>
<pre class="mermaid">
sequenceDiagram
actor Alice
actor John
Alice-xJohn: Hello John, how are you?
John--xAlice: Great!
</pre>
<script type="module"> <script type="module">
import mermaid from './mermaid.esm.mjs'; import mermaid from './mermaid.esm.mjs';
mermaid.initialize({ mermaid.initialize({

View File

@ -183,7 +183,7 @@
</pre> </pre>
<hr /> <hr />
<h2>Compsite states can link to themselves</h2> <h2>Composite states can link to themselves</h2>
<pre class="mermaid"> <pre class="mermaid">
stateDiagram-v2 stateDiagram-v2
state Active { state Active {
@ -199,7 +199,7 @@
stateDiagram-v2 stateDiagram-v2
[*] --> S1 [*] --> S1
S1 --> S2: This long line uses a br tag<br />to create multiple<br />lines. S1 --> S2: This long line uses a br tag<br />to create multiple<br />lines.
S1 --> S3: This transition descripton uses \na newline character\nto create multiple\nlines. S1 --> S3: This transition description uses \na newline character\nto create multiple\nlines.
</pre> </pre>
<hr /> <hr />

184
demos/xychart.html Normal file
View File

@ -0,0 +1,184 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Mermaid Quick Test Page</title>
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=" />
<style>
div.mermaid {
/* font-family: 'trebuchet ms', verdana, arial; */
font-family: 'Courier New', Courier, monospace !important;
}
</style>
</head>
<body>
<h1>XY Charts demos</h1>
<pre class="mermaid">
xychart-beta
title "Sales Revenue (in $)"
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
</pre>
<hr />
<h1>XY Charts horizontal</h1>
<pre class="mermaid">
xychart-beta horizontal
title "Basic xychart"
x-axis "this is x axis" [category1, "category 2", category3, category4]
y-axis yaxisText 10 --> 150
bar "sample bat" [52, 96, 35, 10]
line [23, 46, 75, 43]
</pre>
<hr />
<h1>XY Charts only lines and bar</h1>
<pre class="mermaid">
xychart-beta
line [23, 46, 77, 34]
line [45, 32, 33, 12]
line [87, 54, 99, 85]
line [78, 88, 22, 4]
line [22, 29, 75, 33]
bar [52, 96, 35, 10]
</pre>
<hr />
<h1>XY Charts with +ve and -ve numbers</h1>
<pre class="mermaid">
xychart-beta
line [+1.3, .6, 2.4, -.34]
</pre>
<h1>XY Charts Bar with multiple category</h1>
<pre class="mermaid">
xychart-beta
title "Basic xychart with many categories"
x-axis "this is x axis" [category1, "category 2", category3, category4, category5, category6, category7]
y-axis yaxisText 10 --> 150
bar "sample bar" [52, 96, 35, 10, 87, 34, 67, 99]
</pre>
<h1>XY Charts line with multiple category</h1>
<pre class="mermaid">
xychart-beta
title "Line chart with many category"
x-axis "this is x axis" [category1, "category 2", category3, category4, category5, category6, category7]
y-axis yaxisText 10 --> 150
line "sample line" [52, 96, 35, 10, 87, 34, 67, 99]
</pre>
<h1>XY Charts category with large text</h1>
<pre class="mermaid">
xychart-beta
title "Basic xychart with many categories with category overlap"
x-axis "this is x axis" [category1, "Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.", category3, category4, category5, category6, category7]
y-axis yaxisText 10 --> 150
bar "sample bar" [52, 96, 35, 10, 87, 34, 67, 99]
</pre>
<h1>sparkline demo</h1>
<pre class="mermaid">
---
config:
theme: dark
xyChart:
width: 200
height: 20
plotReservedSpacePercent: 100
---
xychart-beta
line [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800]
</pre>
<h1>sparkBar demo</h1>
<pre class="mermaid">
---
config:
theme: dark
xyChart:
width: 200
height: 20
plotReservedSpacePercent: 100
---
xychart-beta
bar [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800]
</pre>
<h1>XY Charts demos with all configs</h1>
<pre class="mermaid">
---
config:
theme: forest
xyChart:
width: 1000
height: 600
titlePadding: 5
titleFontSize: 10
xAxis:
labelFontSize: 20
labelPadding: 10
titleFontSize: 30
titlePadding: 20
tickLength: 10
tickWidth: 5
axisLineWidth: 5
yAxis:
labelFontSize: 20
labelPadding: 10
titleFontSize: 30
titlePadding: 20
tickLength: 10
tickWidth: 5
axisLineWidth: 5
chartOrientation: horizontal
plotReservedSpacePercent: 60
---
xychart-beta
title "Sales Revene"
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
</pre>
<h1>XY Charts demos with all theme config</h1>
<pre class="mermaid">
---
config:
themeVariables:
xyChart:
titleColor: "#ff0000"
backgroundColor: "#f0f8ff"
yAxisLabelColor: "#ee82ee"
yAxisTitleColor: "#7fffd4"
yAxisTickColor: "#87ceeb"
yAxisLineColor: "#ff6347"
xAxisLabelColor: "#7fffd4"
xAxisTitleColor: "#ee82ee"
xAxisTickColor: "#ff6347"
xAxisLineColor: "#87ceeb"
plotColorPalette: "#008000, #faba63"
---
xychart-beta
title "Sales Revene"
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
</pre>
<hr />
<script type="module">
import mermaid from './mermaid.esm.mjs';
mermaid.initialize({
theme: 'default',
logLevel: 3,
securityLevel: 'loose',
});
</script>
</body>
</html>

View File

@ -1,7 +1,7 @@
version: '3.9' version: '3.9'
services: services:
mermaid: mermaid:
image: node:18.18.0-alpine3.18 image: node:18.18.2-alpine3.18
stdin_open: true stdin_open: true
tty: true tty: true
working_dir: /mermaid working_dir: /mermaid

View File

@ -10,9 +10,8 @@
## First search to see if someone has already asked (and hopefully been answered) or suggested the same thing. ## First search to see if someone has already asked (and hopefully been answered) or suggested the same thing.
- Search in Discussions - [Search in Discussions](https://github.com/orgs/mermaid-js/discussions)
- Search in open Issues - [Search in Issues (Open & Closed)](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue)
- Search in closed Issues
If you find an open issue or discussion thread that is similar to your question but isn't answered, you can let us know that you are also interested in it. If you find an open issue or discussion thread that is similar to your question but isn't answered, you can let us know that you are also interested in it.
Use the GitHub reactions to add a thumbs-up to the issue or discussion thread. Use the GitHub reactions to add a thumbs-up to the issue or discussion thread.

View File

@ -97,7 +97,7 @@ See [the accTitle and accDescr usage examples](#acctitle-and-accdescr-usage-exam
graph LR graph LR
accTitle: Big Decisions accTitle: Big Decisions
accDescr: Bob's Burgers process for making big decisions accDescr: Bob's Burgers process for making big decisions
A[Identify Big Descision] --> B{Make Big Decision} A[Identify Big Decision] --> B{Make Big Decision}
B --> D[Be done] B --> D[Be done]
``` ```
@ -105,7 +105,7 @@ See [the accTitle and accDescr usage examples](#acctitle-and-accdescr-usage-exam
graph LR graph LR
accTitle: Big Decisions accTitle: Big Decisions
accDescr: Bob's Burgers process for making big decisions accDescr: Bob's Burgers process for making big decisions
A[Identify Big Descision] --> B{Make Big Decision} A[Identify Big Decision] --> B{Make Big Decision}
B --> D[Be done] B --> D[Be done]
``` ```
@ -137,7 +137,7 @@ Here is the HTML generated for the SVG element: _(Note that some of the SVG attr
for making very, very big decisions. for making very, very big decisions.
This is actually a very simple flow: identify the big decision and then make the big decision. This is actually a very simple flow: identify the big decision and then make the big decision.
} }
A[Identify Big Descision] --> B{Make Big Decision} A[Identify Big Decision] --> B{Make Big Decision}
B --> D[Be done] B --> D[Be done]
``` ```
@ -149,7 +149,7 @@ Here is the HTML generated for the SVG element: _(Note that some of the SVG attr
for making very, very big decisions. for making very, very big decisions.
This is actually a very simple flow: identify the big decision and then make the big decision. This is actually a very simple flow: identify the big decision and then make the big decision.
} }
A[Identify Big Descision] --> B{Make Big Decision} A[Identify Big Decision] --> B{Make Big Decision}
B --> D[Be done] B --> D[Be done]
``` ```

View File

@ -10,8 +10,8 @@ When mermaid starts, configuration is extracted to determine a configuration to
- The default configuration - The default configuration
- Overrides at the site level are set by the initialize call, and will be applied to all diagrams in the site/app. The term for this is the **siteConfig**. - Overrides at the site level are set by the initialize call, and will be applied to all diagrams in the site/app. The term for this is the **siteConfig**.
- Frontmatter (v10.5.0+) - diagram authors can update select configuration parameters in the frontmatter of the diagram. These are applied to the render config. - Frontmatter (v10.5.0+) - diagram authors can update selected configuration parameters in the frontmatter of the diagram. These are applied to the render config.
- Directives (Deprecated by Frontmatter) - diagram authors can update select configuration parameters directly in the diagram code via directives. These are applied to the render config. - Directives (Deprecated by Frontmatter) - diagram authors can update selected configuration parameters directly in the diagram code via directives. These are applied to the render config.
**The render config** is configuration that is used when rendering by applying these configurations. **The render config** is configuration that is used when rendering by applying these configurations.

View File

@ -16,4 +16,4 @@
#### Defined in #### Defined in
[mermaidAPI.ts:59](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L59) [mermaidAPI.ts:60](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L60)

View File

@ -39,7 +39,7 @@ bindFunctions?.(div); // To call bindFunctions only if it's present.
#### Defined in #### Defined in
[mermaidAPI.ts:79](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L79) [mermaidAPI.ts:80](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L80)
--- ---
@ -51,4 +51,4 @@ The svg code for the rendered graph.
#### Defined in #### Defined in
[mermaidAPI.ts:69](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L69) [mermaidAPI.ts:70](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L70)

View File

@ -14,7 +14,7 @@
#### Defined in #### Defined in
[defaultConfig.ts:268](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L268) [defaultConfig.ts:272](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L272)
--- ---

View File

@ -25,7 +25,7 @@ Renames and re-exports [mermaidAPI](mermaidAPI.md#mermaidapi)
#### Defined in #### Defined in
[mermaidAPI.ts:63](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L63) [mermaidAPI.ts:64](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L64)
## Variables ## Variables
@ -96,7 +96,7 @@ mermaid.initialize(config);
#### Defined in #### Defined in
[mermaidAPI.ts:641](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L641) [mermaidAPI.ts:603](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L603)
## Functions ## Functions
@ -127,7 +127,7 @@ Return the last node appended
#### Defined in #### Defined in
[mermaidAPI.ts:299](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L299) [mermaidAPI.ts:263](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L263)
--- ---
@ -153,7 +153,7 @@ the cleaned up svgCode
#### Defined in #### Defined in
[mermaidAPI.ts:245](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L245) [mermaidAPI.ts:209](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L209)
--- ---
@ -178,7 +178,7 @@ the string with all the user styles
#### Defined in #### Defined in
[mermaidAPI.ts:175](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L175) [mermaidAPI.ts:139](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L139)
--- ---
@ -201,7 +201,7 @@ the string with all the user styles
#### Defined in #### Defined in
[mermaidAPI.ts:222](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L222) [mermaidAPI.ts:186](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L186)
--- ---
@ -228,47 +228,7 @@ with an enclosing block that has each of the cssClasses followed by !important;
#### Defined in #### Defined in
[mermaidAPI.ts:160](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L160) [mermaidAPI.ts:124](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L124)
---
### decodeEntities
**decodeEntities**(`text`): `string`
#### Parameters
| Name | Type | Description |
| :----- | :------- | :----------------- |
| `text` | `string` | text to be decoded |
#### Returns
`string`
#### Defined in
[mermaidAPI.ts:146](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L146)
---
### encodeEntities
**encodeEntities**(`text`): `string`
#### Parameters
| Name | Type | Description |
| :----- | :------- | :----------------- |
| `text` | `string` | text to be encoded |
#### Returns
`string`
#### Defined in
[mermaidAPI.ts:117](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L117)
--- ---
@ -294,7 +254,7 @@ Put the svgCode into an iFrame. Return the iFrame code
#### Defined in #### Defined in
[mermaidAPI.ts:276](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L276) [mermaidAPI.ts:240](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L240)
--- ---
@ -319,4 +279,4 @@ Remove any existing elements from the given document
#### Defined in #### Defined in
[mermaidAPI.ts:349](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L349) [mermaidAPI.ts:313](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L313)

View File

@ -35,12 +35,19 @@ Below are a list of community plugins and integrations created with Mermaid.
- [Notion](https://notion.so) ✅ - [Notion](https://notion.so) ✅
- [Observable](https://observablehq.com/@observablehq/mermaid) ✅ - [Observable](https://observablehq.com/@observablehq/mermaid) ✅
- [Obsidian](https://help.obsidian.md/Editing+and+formatting/Advanced+formatting+syntax#Diagram) ✅ - [Obsidian](https://help.obsidian.md/Editing+and+formatting/Advanced+formatting+syntax#Diagram) ✅
- [NotesHub](https://noteshub.app) ✅
- [GitBook](https://gitbook.com) - [GitBook](https://gitbook.com)
- [Mermaid Plugin](https://github.com/JozoVilcek/gitbook-plugin-mermaid) - [Mermaid Plugin](https://github.com/JozoVilcek/gitbook-plugin-mermaid)
- [Markdown with Mermaid CLI](https://github.com/miao1007/gitbook-plugin-mermaid-cli) - [Markdown with Mermaid CLI](https://github.com/miao1007/gitbook-plugin-mermaid-cli)
- [Mermaid plugin for GitBook](https://github.com/wwformat/gitbook-plugin-mermaid-pdf) - [Mermaid plugin for GitBook](https://github.com/wwformat/gitbook-plugin-mermaid-pdf)
- [LiveBook](https://livebook.dev) ✅ - [LiveBook](https://livebook.dev) ✅
- [Atlassian Products](https://www.atlassian.com) - [Atlassian Products](https://www.atlassian.com)
- [Mermaid for Confluence](https://marketplace.atlassian.com/apps/1224722/mermaid-for-confluence?hosting=cloud&tab=overview)
- [Mermaid Integration for Confluence](https://marketplace.atlassian.com/apps/1222792/mermaid-integration-for-confluence?hosting=cloud&tab=overview)
- [Mermaid Diagrams for Confluence](https://marketplace.atlassian.com/apps/1226945/mermaid-diagrams-for-confluence?hosting=cloud&tab=overview)
- [Mermaid Macro for Confluence](https://marketplace.atlassian.com/apps/1231150/mermaid-macro-for-confluence?hosting=cloud&tab=overview)
- [EliteSoft Mermaid Charts and Diagrams](https://marketplace.atlassian.com/apps/1227286/elitesoft-mermaid-charts-and-diagrams?hosting=cloud&tab=overview)
- [Mermaid for Jira Cloud - Draw UML diagrams easily](https://marketplace.atlassian.com/apps/1223053/mermaid-for-jira-cloud-draw-uml-diagrams-easily?hosting=cloud&tab=overview)
- [Mermaid Charts & Diagrams for Confluence](https://marketplace.atlassian.com/apps/1222572/) - [Mermaid Charts & Diagrams for Confluence](https://marketplace.atlassian.com/apps/1222572/)
- [Mermaid Charts & Diagrams for Jira](https://marketplace.atlassian.com/apps/1224537/) - [Mermaid Charts & Diagrams for Jira](https://marketplace.atlassian.com/apps/1224537/)
- [Mermaid Live Editor for Confluence Cloud](https://marketplace.atlassian.com/apps/1231571/mermaid-live-editor-for-confluence?hosting=cloud&tab=overview) - [Mermaid Live Editor for Confluence Cloud](https://marketplace.atlassian.com/apps/1231571/mermaid-live-editor-for-confluence?hosting=cloud&tab=overview)
@ -99,6 +106,8 @@ Communication tools and platforms
- [phpbb-ext-mermaid](https://github.com/AlfredoRamos/phpbb-ext-mermaid) - [phpbb-ext-mermaid](https://github.com/AlfredoRamos/phpbb-ext-mermaid)
- [NodeBB](https://nodebb.org) - [NodeBB](https://nodebb.org)
- [Mermaid Plugin](https://www.npmjs.com/package/nodebb-plugin-mermaid) - [Mermaid Plugin](https://www.npmjs.com/package/nodebb-plugin-mermaid)
- [Slack](https://slack.com)
- [Mermaid for Slack](https://github.com/JackuB/mermaid-for-slack)
### Wikis ### Wikis
@ -169,13 +178,14 @@ Communication tools and platforms
### Document Generation ### Document Generation
- [Docusaurus](https://docusaurus.io/docs/markdown-features/diagrams) ✅
- [Swimm - Up-to-date diagrams with Swimm, the knowledge management tool for code](https://docs.swimm.io/Features/diagrams-and-charts) - [Swimm - Up-to-date diagrams with Swimm, the knowledge management tool for code](https://docs.swimm.io/Features/diagrams-and-charts)
- [Sphinx](https://www.sphinx-doc.org/en/master/) - [Sphinx](https://www.sphinx-doc.org/en/master/)
- [sphinxcontrib-mermaid](https://github.com/mgaitan/sphinxcontrib-mermaid) - [sphinxcontrib-mermaid](https://github.com/mgaitan/sphinxcontrib-mermaid)
- [remark](https://remark.js.org/) - [remark](https://remark.js.org/)
- [remark-mermaidjs](https://github.com/remcohaszing/remark-mermaidjs) - [remark-mermaidjs](https://github.com/remcohaszing/remark-mermaidjs)
- [rehype](https://github.com/rehypejs/rehype) - [rehype](https://github.com/rehypejs/rehype)
- [rehype-mermaidjs](https://github.com/remcohaszing/rehype-mermaidjs) - [rehype-mermaid](https://github.com/remcohaszing/rehype-mermaid)
- [Gatsby](https://www.gatsbyjs.com/) - [Gatsby](https://www.gatsbyjs.com/)
- [gatsby-remark-mermaid](https://github.com/remcohaszing/gatsby-remark-mermaid) - [gatsby-remark-mermaid](https://github.com/remcohaszing/gatsby-remark-mermaid)
- [JSDoc](https://jsdoc.app/) - [JSDoc](https://jsdoc.app/)

View File

@ -283,6 +283,26 @@ quadrantChart
Campaign F: [0.35, 0.78] Campaign F: [0.35, 0.78]
``` ```
### [XY Chart](../syntax/xyChart.md)
```mermaid-example
xychart-beta
title "Sales Revenue"
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
```
```mermaid
xychart-beta
title "Sales Revenue"
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
```
## Installation ## Installation
**In depth guides and examples can be found at [Getting Started](./getting-started.md) and [Usage](../config/usage.md).** **In depth guides and examples can be found at [Getting Started](./getting-started.md) and [Usage](../config/usage.md).**
@ -320,7 +340,7 @@ To Deploy Mermaid:
</script> </script>
``` ```
**Doing so commands the mermaid parser to look for the `<div>` or `<pre>` tags with `class="mermaid"`. From these tags, mermaid tries read the diagram/chart definitions and render them into SVG charts.** **Doing so commands the mermaid parser to look for the `<div>` or `<pre>` tags with `class="mermaid"`. From these tags, mermaid tries to read the diagram/chart definitions and render them into SVG charts.**
**Examples can be found in** [Other examples](../syntax/examples.md) **Examples can be found in** [Other examples](../syntax/examples.md)

View File

@ -399,7 +399,7 @@ UpdateRelStyle(customerA, bankA, $offsetY="60")
title Component diagram for Internet Banking System - API Application 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(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.") Container(ma, "Mobile App", "Xamarin", "Provides a limited subset to 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.") 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.") System_Ext(mbs, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")
@ -439,7 +439,7 @@ UpdateRelStyle(customerA, bankA, $offsetY="60")
title Component diagram for Internet Banking System - API Application 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(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.") Container(ma, "Mobile App", "Xamarin", "Provides a limited subset to 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.") 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.") System_Ext(mbs, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")

View File

@ -425,8 +425,6 @@ And `Link` can be one of:
A namespace groups classes. A namespace groups classes.
Code:
```mermaid-example ```mermaid-example
classDiagram classDiagram
namespace BaseShapes { namespace BaseShapes {

View File

@ -467,7 +467,7 @@ flowchart TB
A & B--> C & D A & B--> C & D
``` ```
If you describe the same diagram using the the basic syntax, it will take four lines. A If you describe the same diagram using the basic syntax, it will take four lines. A
word of warning, one could go overboard with this making the flowchart harder to read in word of warning, one could go overboard with this making the flowchart harder to read in
markdown form. The Swedish word `lagom` comes to mind. It means, not too much and not too little. markdown form. The Swedish word `lagom` comes to mind. It means, not too much and not too little.
This goes for expressive syntaxes as well. This goes for expressive syntaxes as well.
@ -764,7 +764,7 @@ flowchart LR
end end
%% ^ These subgraphs are identical, except for the links to them: %% ^ These subgraphs are identical, except for the links to them:
%% Link *to* subgraph1: subgraph1 direction is mantained %% Link *to* subgraph1: subgraph1 direction is maintained
outside --> subgraph1 outside --> subgraph1
%% Link *within* subgraph2: %% Link *within* subgraph2:
%% subgraph2 inherits the direction of the top-level graph (LR) %% subgraph2 inherits the direction of the top-level graph (LR)
@ -783,7 +783,7 @@ flowchart LR
end end
%% ^ These subgraphs are identical, except for the links to them: %% ^ These subgraphs are identical, except for the links to them:
%% Link *to* subgraph1: subgraph1 direction is mantained %% Link *to* subgraph1: subgraph1 direction is maintained
outside --> subgraph1 outside --> subgraph1
%% Link *within* subgraph2: %% Link *within* subgraph2:
%% subgraph2 inherits the direction of the top-level graph (LR) %% subgraph2 inherits the direction of the top-level graph (LR)
@ -1112,7 +1112,7 @@ flowchart TD
B-->E(A fa:fa-camera-retro perhaps?) B-->E(A fa:fa-camera-retro perhaps?)
``` ```
Mermaid is compatible with Font Awesome up to verion 5, Free icons only. Check that the icons you use are from the [supported set of icons](https://fontawesome.com/v5/search?o=r&m=free). Mermaid is compatible with Font Awesome up to version 5, Free icons only. Check that the icons you use are from the [supported set of icons](https://fontawesome.com/v5/search?o=r&m=free).
## Graph declarations with spaces between vertices and link and without semicolon ## Graph declarations with spaces between vertices and link and without semicolon

View File

@ -827,18 +827,25 @@ Here, we have changed the default main branch name to `MetroLine1`.
## Orientation (v10.3.0+) ## Orientation (v10.3.0+)
In Mermaid, the default orientation is Left to Right. The branches are lined vertically. Mermaid supports two graph orientations: **Left-to-Right** (default) and **Top-to-Bottom**.
You can set this with either `LR:` (for [**Left-to-Right**](#left-to-right-default-lr)) or `TB:` (for [**Top-to-Bottom**](#top-to-bottom-tb)) after `gitGraph`.
### Left to Right (default, `LR:`)
In Mermaid, the default orientation is for commits to run from left to right and for branches to be stacked on top of one another.
However, you can set this explicitly with `LR:` after `gitGraph`.
Usage example: Usage example:
```mermaid-example ```mermaid-example
gitGraph gitGraph LR:
commit commit
commit commit
branch develop branch develop
commit commit
commit commit
commit
checkout main checkout main
commit commit
commit commit
@ -848,13 +855,12 @@ Usage example:
``` ```
```mermaid ```mermaid
gitGraph gitGraph LR:
commit commit
commit commit
branch develop branch develop
commit commit
commit commit
commit
checkout main checkout main
commit commit
commit commit
@ -863,9 +869,11 @@ Usage example:
commit commit
``` ```
Sometimes we may want to change the orientation. Currently, Mermaid supports two orientations: **Left to Right**(default) and **Top to Bottom**. ### Top to Bottom (`TB:`)
In order to change the orientation from top to bottom i.e. branches lined horizontally, you need to add `TB` along with `gitGraph`. In `TB` (**Top-to-Bottom**) orientation, the commits run from top to bottom of the graph and branches are arranged side-by-side.
To orient the graph this way, you need to add `TB:` after gitGraph.
Usage example: Usage example:
@ -876,7 +884,6 @@ Usage example:
branch develop branch develop
commit commit
commit commit
commit
checkout main checkout main
commit commit
commit commit
@ -892,7 +899,6 @@ Usage example:
branch develop branch develop
commit commit
commit commit
commit
checkout main checkout main
commit commit
commit commit

View File

@ -102,26 +102,26 @@ Points are used to plot a circle inside the quadrantChart. The syntax is `<text>
## Chart Configurations ## Chart Configurations
| Parameter | Description | Default value | | Parameter | Description | Default value |
| --------------------------------- | ------------------------------------------------------------------------------------------------- | :-----------: | | --------------------------------- | -------------------------------------------------------------------------------------------------- | :-----------: |
| chartWidth | Width of the chart | 500 | | chartWidth | Width of the chart | 500 |
| chartHeight | Height of the chart | 500 | | chartHeight | Height of the chart | 500 |
| titlePadding | Top and Bottom padding of the title | 10 | | titlePadding | Top and Bottom padding of the title | 10 |
| titleFontSize | Title font size | 20 | | titleFontSize | Title font size | 20 |
| quadrantPadding | Padding outside all the quadrants | 5 | | quadrantPadding | Padding outside all the quadrants | 5 |
| quadrantTextTopPadding | Quadrant text top padding when text is drawn on top ( not data points are there) | 5 | | quadrantTextTopPadding | Quadrant text top padding when text is drawn on top ( not data points are there) | 5 |
| quadrantLabelFontSize | Quadrant text font size | 16 | | quadrantLabelFontSize | Quadrant text font size | 16 |
| quadrantInternalBorderStrokeWidth | Border stroke width inside the quadrants | 1 | | quadrantInternalBorderStrokeWidth | Border stroke width inside the quadrants | 1 |
| quadrantExternalBorderStrokeWidth | Quadrant external border stroke width | 2 | | quadrantExternalBorderStrokeWidth | Quadrant external border stroke width | 2 |
| xAxisLabelPadding | Top and bottom padding of x-axis text | 5 | | xAxisLabelPadding | Top and bottom padding of x-axis text | 5 |
| xAxisLabelFontSize | X-axis texts font size | 16 | | xAxisLabelFontSize | X-axis texts font size | 16 |
| xAxisPosition | Position of x-axis (top , bottom) if there are points the x-axis will alway be rendered in bottom | 'top' | | xAxisPosition | Position of x-axis (top , bottom) if there are points the x-axis will always be rendered in bottom | 'top' |
| yAxisLabelPadding | Left and Right padding of y-axis text | 5 | | yAxisLabelPadding | Left and Right padding of y-axis text | 5 |
| yAxisLabelFontSize | Y-axis texts font size | 16 | | yAxisLabelFontSize | Y-axis texts font size | 16 |
| yAxisPosition | Position of y-axis (left , right) | 'left' | | yAxisPosition | Position of y-axis (left , right) | 'left' |
| pointTextPadding | Padding between point and the below text | 5 | | pointTextPadding | Padding between point and the below text | 5 |
| pointLabelFontSize | Point text font size | 12 | | pointLabelFontSize | Point text font size | 12 |
| pointRadius | Radius of the point to be drawn | 5 | | pointRadius | Radius of the point to be drawn | 5 |
## Chart Theme Variables ## Chart Theme Variables

View File

@ -217,7 +217,7 @@ Note that there are no sections defined, and each time period and its correspond
2. Disable the multiColor option using the `disableMultiColor` option. This will make all time periods and events follow the same color scheme. 2. Disable the multiColor option using the `disableMultiColor` option. This will make all time periods and events follow the same color scheme.
You will need to add this option either via mermaid.intialize function or directives. You will need to add this option either via mermaid.initialize function or directives.
```javascript ```javascript
mermaid.initialize({ mermaid.initialize({

188
docs/syntax/xyChart.md Normal file
View File

@ -0,0 +1,188 @@
> **Warning**
>
> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT.
>
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/xyChart.md](../../packages/mermaid/src/docs/syntax/xyChart.md).
# XY Chart
> In the context of mermaid-js, the XY chart is a comprehensive charting module that encompasses various types of charts that utilize both x-axis and y-axis for data representation. Presently, it includes two fundamental chart types: the bar chart and the line chart. These charts are designed to visually display and analyze data that involve two numerical variables.
> It's important to note that while the current implementation of mermaid-js includes these two chart types, the framework is designed to be dynamic and adaptable. Therefore, it has the capacity for expansion and the inclusion of additional chart types in the future. This means that users can expect an evolving suite of charting options within the XY chart module, catering to various data visualization needs as new chart types are introduced over time.
## Example
```mermaid-example
xychart-beta
title "Sales Revenue"
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
```
```mermaid
xychart-beta
title "Sales Revenue"
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
```
## Syntax
> **Note**
> All text values that contain only one word can be written without `"`. If a text value has many words in it, specifically if it contains spaces, enclose the value in `"`
### Orientations
The chart can be drawn horizontal or vertical, default value is vertical.
xychart-beta horizontal
...
### Title
The title is a short description of the chart and it will always render on top of the chart.
#### Example
xychart-beta
title "This is a simple example"
...
> **Note**
> If the title is a single word one no need to use `"`, but if it has space `"` is needed
### x-axis
The x-axis primarily serves as a categorical value, although it can also function as a numeric range value when needed.
#### Example
1. `x-axis title min --> max` x-axis will function as numeric with the given range
2. `x-axis "title with space" [cat1, "cat2 with space", cat3]` x-axis if categorical, categories are text type
### y-axis
The y-axis is employed to represent numerical range values, it cannot have categorical values.
#### Example
1. `y-axis title min --> max`
2. `y-axis title` it will only add the title, the range will be auto generated from data.
> **Note**
> Both x and y axis are optional if not provided we will try to create the range
### Line chart
A line chart offers the capability to graphically depict lines.
#### Example
1. `line [2.3, 45, .98, -3.4]` it can have all valid numeric values.
### Bar chart
A bar chart offers the capability to graphically depict bars.
#### Example
1. `bar [2.3, 45, .98, -3.4]` it can have all valid numeric values.
#### Simplest example
The only two things required are the chart name (`xychart-beta`) and one data set. So you will be able to draw a chart with a simple config like
xychart-beta
line [+1.3, .6, 2.4, -.34]
## Chart Configurations
| Parameter | Description | Default value |
| ------------------------ | ---------------------------------------------- | :-----------: |
| width | Width of the chart | 700 |
| height | Height of the chart | 500 |
| titlePadding | Top and Bottom padding of the title | 10 |
| titleFontSize | Title font size | 20 |
| showTitle | Title to be shown or not | true |
| xAxis | xAxis configuration | AxisConfig |
| yAxis | yAxis configuration | AxisConfig |
| chartOrientation | 'vertical' or 'horizontal' | 'vertical' |
| plotReservedSpacePercent | Minimum space plots will take inside the chart | 50 |
### AxisConfig
| Parameter | Description | Default value |
| ------------- | ------------------------------------ | :-----------: |
| showLabel | Show axis labels or tick values | true |
| labelFontSize | Font size of the label to be drawn | 14 |
| labelPadding | Top and Bottom padding of the label | 5 |
| showTitle | Axis title to be shown or not | true |
| titleFontSize | Axis title font size | 16 |
| titlePadding | Top and Bottom padding of Axis title | 5 |
| showTick | Tick to be shown or not | true |
| tickLength | How long the tick will be | 5 |
| tickWidth | How width the tick will be | 2 |
| showAxisLine | Axis line to be shown or not | true |
| axisLineWidth | Thickness of the axis line | 2 |
## Chart Theme Variables
> **Note**
> Themes for xychart resides inside xychart attribute so to set the variables use this syntax
> %%{init: { "themeVariables": {"xyChart": {"titleColor": "#ff0000"} } }}%%
| Parameter | Description |
| ---------------- | --------------------------------------------------------- |
| backgroundColor | Background color of the whole chart |
| titleColor | Color of the Title text |
| xAxisLableColor | Color of the x-axis labels |
| xAxisTitleColor | Color of the x-axis title |
| xAxisTickColor | Color of the x-axis tick |
| xAxisLineColor | Color of the x-axis line |
| yAxisLableColor | Color of the y-axis labels |
| yAxisTitleColor | Color of the y-axis title |
| yAxisTickColor | Color of the y-axis tick |
| yAxisLineColor | Color of the y-axis line |
| plotColorPalette | String of colors separated by comma e.g. "#f3456, #43445" |
## Example on config and theme
```mermaid-example
---
config:
xyChart:
width: 900
height: 600
themeVariables:
xyChart:
titleColor: "#ff0000"
---
xychart-beta
title "Sales Revenue"
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
```
```mermaid
---
config:
xyChart:
width: 900
height: 600
themeVariables:
xyChart:
titleColor: "#ff0000"
---
xychart-beta
title "Sales Revenue"
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
```

View File

@ -4,7 +4,7 @@
"version": "10.2.4", "version": "10.2.4",
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.", "description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
"type": "module", "type": "module",
"packageManager": "pnpm@8.7.6", "packageManager": "pnpm@8.10.4",
"keywords": [ "keywords": [
"diagram", "diagram",
"markdown", "markdown",
@ -89,7 +89,7 @@
"cypress": "^12.10.0", "cypress": "^12.10.0",
"cypress-image-snapshot": "^4.0.1", "cypress-image-snapshot": "^4.0.1",
"esbuild": "^0.19.0", "esbuild": "^0.19.0",
"eslint": "^8.39.0", "eslint": "^8.47.0",
"eslint-config-prettier": "^8.8.0", "eslint-config-prettier": "^8.8.0",
"eslint-plugin-cypress": "^2.13.2", "eslint-plugin-cypress": "^2.13.2",
"eslint-plugin-html": "^7.1.0", "eslint-plugin-html": "^7.1.0",
@ -125,7 +125,7 @@
"vitest": "^0.34.0" "vitest": "^0.34.0"
}, },
"volta": { "volta": {
"node": "18.18.0" "node": "18.18.2"
}, },
"nyc": { "nyc": {
"report-dir": "coverage/cypress" "report-dir": "coverage/cypress"

View File

@ -47,6 +47,7 @@ const MERMAID_CONFIG_DIAGRAM_KEYS = [
'er', 'er',
'pie', 'pie',
'quadrantChart', 'quadrantChart',
'xyChart',
'requirement', 'requirement',
'mindmap', 'mindmap',
'timeline', 'timeline',

View File

@ -3,6 +3,8 @@ import { log } from './logger.js';
import { getDiagram, registerDiagram } from './diagram-api/diagramAPI.js'; import { getDiagram, registerDiagram } from './diagram-api/diagramAPI.js';
import { detectType, getDiagramLoader } from './diagram-api/detectType.js'; import { detectType, getDiagramLoader } from './diagram-api/detectType.js';
import { UnknownDiagramError } from './errors.js'; import { UnknownDiagramError } from './errors.js';
import { encodeEntities } from './utils.js';
import type { DetailedError } from './utils.js'; import type { DetailedError } from './utils.js';
import type { DiagramDefinition, DiagramMetadata } from './diagram-api/types.js'; import type { DiagramDefinition, DiagramMetadata } from './diagram-api/types.js';
@ -21,6 +23,7 @@ export class Diagram {
private detectError?: UnknownDiagramError; private detectError?: UnknownDiagramError;
constructor(public text: string, public metadata: Pick<DiagramMetadata, 'title'> = {}) { constructor(public text: string, public metadata: Pick<DiagramMetadata, 'title'> = {}) {
this.text = encodeEntities(text);
this.text += '\n'; this.text += '\n';
const cnf = configApi.getConfig(); const cnf = configApi.getConfig();
try { try {

View File

@ -135,6 +135,7 @@ export interface MermaidConfig {
er?: ErDiagramConfig; er?: ErDiagramConfig;
pie?: PieDiagramConfig; pie?: PieDiagramConfig;
quadrantChart?: QuadrantChartConfig; quadrantChart?: QuadrantChartConfig;
xyChart?: XYChartConfig;
requirement?: RequirementDiagramConfig; requirement?: RequirementDiagramConfig;
mindmap?: MindmapDiagramConfig; mindmap?: MindmapDiagramConfig;
gitGraph?: GitGraphDiagramConfig; gitGraph?: GitGraphDiagramConfig;
@ -688,6 +689,194 @@ export interface QuadrantChartConfig extends BaseDiagramConfig {
*/ */
quadrantExternalBorderStrokeWidth?: number; quadrantExternalBorderStrokeWidth?: number;
} }
/**
* This object contains configuration for XYChart axis config
*
* This interface was referenced by `MermaidConfig`'s JSON-Schema
* via the `definition` "XYChartAxisConfig".
*/
export interface XYChartAxisConfig {
/**
* Should show the axis labels (tick text)
*/
showLabel?: boolean;
/**
* font size of the axis labels (tick text)
*/
labelFontSize?: number;
/**
* top and bottom space from axis label (tick text)
*/
labelPadding?: number;
/**
* Should show the axis title
*/
showTitle?: boolean;
/**
* font size of the axis title
*/
titleFontSize?: number;
/**
* top and bottom space from axis title
*/
titlePadding?: number;
/**
* Should show the axis tick lines
*/
showTick?: boolean;
/**
* length of the axis tick lines
*/
tickLength?: number;
/**
* width of the axis tick lines
*/
tickWidth?: number;
/**
* Show line across the axis
*/
showAxisLine?: boolean;
/**
* Width of the axis line
*/
axisLineWidth?: number;
}
/**
* This object contains configuration specific to XYCharts
*
* This interface was referenced by `MermaidConfig`'s JSON-Schema
* via the `definition` "XYChartConfig".
*/
export interface XYChartConfig extends BaseDiagramConfig {
/**
* width of the chart
*/
width?: number;
/**
* height of the chart
*/
height?: number;
/**
* Font size of the chart title
*/
titleFontSize?: number;
/**
* Top and bottom space from the chart title
*/
titlePadding?: number;
/**
* Should show the chart title
*/
showTitle?: boolean;
xAxis?: XYChartAxisConfig1;
yAxis?: XYChartAxisConfig2;
/**
* How to plot will be drawn horizontal or vertical
*/
chartOrientation?: 'vertical' | 'horizontal';
/**
* Minimum percent of space plots of the chart will take
*/
plotReservedSpacePercent?: number;
}
/**
* This object contains configuration for XYChart axis config
*/
export interface XYChartAxisConfig1 {
/**
* Should show the axis labels (tick text)
*/
showLabel?: boolean;
/**
* font size of the axis labels (tick text)
*/
labelFontSize?: number;
/**
* top and bottom space from axis label (tick text)
*/
labelPadding?: number;
/**
* Should show the axis title
*/
showTitle?: boolean;
/**
* font size of the axis title
*/
titleFontSize?: number;
/**
* top and bottom space from axis title
*/
titlePadding?: number;
/**
* Should show the axis tick lines
*/
showTick?: boolean;
/**
* length of the axis tick lines
*/
tickLength?: number;
/**
* width of the axis tick lines
*/
tickWidth?: number;
/**
* Show line across the axis
*/
showAxisLine?: boolean;
/**
* Width of the axis line
*/
axisLineWidth?: number;
}
/**
* This object contains configuration for XYChart axis config
*/
export interface XYChartAxisConfig2 {
/**
* Should show the axis labels (tick text)
*/
showLabel?: boolean;
/**
* font size of the axis labels (tick text)
*/
labelFontSize?: number;
/**
* top and bottom space from axis label (tick text)
*/
labelPadding?: number;
/**
* Should show the axis title
*/
showTitle?: boolean;
/**
* font size of the axis title
*/
titleFontSize?: number;
/**
* top and bottom space from axis title
*/
titlePadding?: number;
/**
* Should show the axis tick lines
*/
showTick?: boolean;
/**
* length of the axis tick lines
*/
tickLength?: number;
/**
* width of the axis tick lines
*/
tickWidth?: number;
/**
* Show line across the axis
*/
showAxisLine?: boolean;
/**
* Width of the axis line
*/
axisLineWidth?: number;
}
/** /**
* The object containing configurations specific for entity relationship diagrams * The object containing configurations specific for entity relationship diagrams
* *

View File

@ -3,7 +3,7 @@ import { log } from '../logger.js';
import createLabel from './createLabel.js'; import createLabel from './createLabel.js';
import { createText } from '../rendering-util/createText.js'; import { createText } from '../rendering-util/createText.js';
import { select } from 'd3'; import { select } from 'd3';
import { getConfig } from '../config.js'; import { getConfig } from '../diagram-api/diagramAPI.js';
import { evaluate } from '../diagrams/common/common.js'; import { evaluate } from '../diagrams/common/common.js';
const rect = (parent, node) => { const rect = (parent, node) => {

View File

@ -1,8 +1,8 @@
import { select } from 'd3'; import { select } from 'd3';
import { log } from '../logger.js'; import { log } from '../logger.js';
import { getConfig } from '../config.js'; import { getConfig } from '../diagram-api/diagramAPI.js';
import { evaluate } from '../diagrams/common/common.js'; import { evaluate } from '../diagrams/common/common.js';
import { decodeEntities } from '../mermaidAPI.js'; import { decodeEntities } from '../utils.js';
/** /**
* @param dom * @param dom

View File

@ -2,7 +2,7 @@ import { log } from '../logger.js';
import createLabel from './createLabel.js'; import createLabel from './createLabel.js';
import { createText } from '../rendering-util/createText.js'; import { createText } from '../rendering-util/createText.js';
import { line, curveBasis, select } from 'd3'; import { line, curveBasis, select } from 'd3';
import { getConfig } from '../config.js'; import { getConfig } from '../diagram-api/diagramAPI.js';
import utils from '../utils.js'; import utils from '../utils.js';
import { evaluate } from '../diagrams/common/common.js'; import { evaluate } from '../diagrams/common/common.js';
import { getLineFunctionsWithOffset } from '../utils/lineWithOffset.js'; import { getLineFunctionsWithOffset } from '../utils/lineWithOffset.js';

View File

@ -231,12 +231,12 @@ export const adjustClustersAndEdges = (graph, depth) => {
if (children.length > 0) { if (children.length > 0) {
log.debug('Cluster identified', id, descendants); log.debug('Cluster identified', id, descendants);
edges.forEach((edge) => { edges.forEach((edge) => {
// log.debug('Edge, decendants: ', edge, decendants[id]); // log.debug('Edge, descendants: ', edge, descendants[id]);
// Check if any edge leaves the cluster (not the actual cluster, that's a link from the box) // Check if any edge leaves the cluster (not the actual cluster, that's a link from the box)
if (edge.v !== id && edge.w !== id) { if (edge.v !== id && edge.w !== id) {
// Any edge where either the one of the nodes is descending to the cluster but not the other // Any edge where either the one of the nodes is descending to the cluster but not the other
// if (decendants[id].indexOf(edge.v) < 0 && decendants[id].indexOf(edge.w) < 0) { // if (descendants[id].indexOf(edge.v) < 0 && descendants[id].indexOf(edge.w) < 0) {
const d1 = isDescendant(edge.v, id); const d1 = isDescendant(edge.v, id);
const d2 = isDescendant(edge.w, id); const d2 = isDescendant(edge.w, id);

View File

@ -419,7 +419,7 @@ describe('extractDescendants', function () {
return {}; return {};
}); });
}); });
it('Simple case of one level decendants GLB9', function () { it('Simple case of one level descendants GLB9', function () {
/* /*
subgraph A subgraph A
a a

View File

@ -1,7 +1,7 @@
import { select } from 'd3'; import { select } from 'd3';
import { log } from '../logger.js'; import { log } from '../logger.js';
import { labelHelper, updateNodeBounds, insertPolygonShape } from './shapes/util.js'; import { labelHelper, updateNodeBounds, insertPolygonShape } from './shapes/util.js';
import { getConfig } from '../config.js'; import { getConfig } from '../diagram-api/diagramAPI.js';
import intersect from './intersect/index.js'; import intersect from './intersect/index.js';
import createLabel from './createLabel.js'; import createLabel from './createLabel.js';
import note from './shapes/note.js'; import note from './shapes/note.js';

View File

@ -1,6 +1,6 @@
import { updateNodeBounds, labelHelper } from './util.js'; import { updateNodeBounds, labelHelper } from './util.js';
import { log } from '../../logger.js'; import { log } from '../../logger.js';
import { getConfig } from '../../config.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
const note = async (parent, node) => { const note = async (parent, node) => {

View File

@ -1,9 +1,9 @@
import createLabel from '../createLabel.js'; import createLabel from '../createLabel.js';
import { createText } from '../../rendering-util/createText.js'; import { createText } from '../../rendering-util/createText.js';
import { getConfig } from '../../config.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
import { decodeEntities } from '../../mermaidAPI.js';
import { select } from 'd3'; import { select } from 'd3';
import { evaluate, sanitizeText } from '../../diagrams/common/common.js'; import { evaluate, sanitizeText } from '../../diagrams/common/common.js';
import { decodeEntities } from '../../utils.js';
export const labelHelper = async (parent, node, _classes, isNode) => { export const labelHelper = async (parent, node, _classes, isNode) => {
let classes; let classes;

View File

@ -236,6 +236,10 @@ const config: RequiredDeep<MermaidConfig> = {
...defaultConfigJson.pie, ...defaultConfigJson.pie,
useWidth: 984, useWidth: 984,
}, },
xyChart: {
...defaultConfigJson.xyChart,
useWidth: undefined,
},
requirement: { requirement: {
...defaultConfigJson.requirement, ...defaultConfigJson.requirement,
useWidth: undefined, useWidth: undefined,

View File

@ -7,6 +7,7 @@ import gantt from '../diagrams/gantt/ganttDetector.js';
import { info } from '../diagrams/info/infoDetector.js'; import { info } from '../diagrams/info/infoDetector.js';
import { pie } from '../diagrams/pie/pieDetector.js'; import { pie } from '../diagrams/pie/pieDetector.js';
import quadrantChart from '../diagrams/quadrant-chart/quadrantDetector.js'; import quadrantChart from '../diagrams/quadrant-chart/quadrantDetector.js';
import xychart from '../diagrams/xychart/xychartDetector.js';
import requirement from '../diagrams/requirement/requirementDetector.js'; import requirement from '../diagrams/requirement/requirementDetector.js';
import sequence from '../diagrams/sequence/sequenceDetector.js'; import sequence from '../diagrams/sequence/sequenceDetector.js';
import classDiagram from '../diagrams/class/classDetector.js'; import classDiagram from '../diagrams/class/classDetector.js';
@ -84,6 +85,7 @@ export const addDiagrams = () => {
state, state,
journey, journey,
quadrantChart, quadrantChart,
sankey sankey,
xychart
); );
}; };

View File

@ -1,6 +1,11 @@
import { addDetector } from './detectType.js'; import { addDetector } from './detectType.js';
import { log as _log, setLogLevel as _setLogLevel } from '../logger.js'; import { log as _log, setLogLevel as _setLogLevel } from '../logger.js';
import { getConfig as _getConfig } from '../config.js'; import {
getConfig as _getConfig,
setConfig as _setConfig,
defaultConfig as _defaultConfig,
setSiteConfig as _setSiteConfig,
} from '../config.js';
import { sanitizeText as _sanitizeText } from '../diagrams/common/common.js'; import { sanitizeText as _sanitizeText } from '../diagrams/common/common.js';
import { setupGraphViewbox as _setupGraphViewbox } from '../setupGraphViewbox.js'; import { setupGraphViewbox as _setupGraphViewbox } from '../setupGraphViewbox.js';
import { addStylesForDiagram } from '../styles.js'; import { addStylesForDiagram } from '../styles.js';
@ -15,6 +20,9 @@ import * as _commonDb from '../diagrams/common/commonDb.js';
export const log = _log; export const log = _log;
export const setLogLevel = _setLogLevel; export const setLogLevel = _setLogLevel;
export const getConfig = _getConfig; export const getConfig = _getConfig;
export const setConfig = _setConfig;
export const defaultConfig = _defaultConfig;
export const setSiteConfig = _setSiteConfig;
export const sanitizeText = (text: string) => _sanitizeText(text, getConfig()); export const sanitizeText = (text: string) => _sanitizeText(text, getConfig());
export const setupGraphViewbox = _setupGraphViewbox; export const setupGraphViewbox = _setupGraphViewbox;
export const getCommonDb = () => { export const getCommonDb = () => {

View File

@ -66,4 +66,18 @@ Expecting 'TXT', got 'NEWLINE'"
'"No diagram type detected matching given configuration for text: thor TD; A-->B"' '"No diagram type detected matching given configuration for text: thor TD; A-->B"'
); );
}); });
test('should consider entity codes when present in diagram defination', async () => {
const diagram = await getDiagramFromText(`sequenceDiagram
A->>B: I #9829; you!
B->>A: I #9829; you #infin; times more!`);
// @ts-ignore: we need to add types for sequenceDb which will be done in separate PR
const messages = diagram.db?.getMessages?.();
if (!messages) {
throw new Error('Messages not found!');
}
expect(messages[0].message).toBe('I fl°°9829¶ß you!');
expect(messages[1].message).toBe('I fl°°9829¶ß you fl°infin¶ß times more!');
});
}); });

View File

@ -1,4 +1,4 @@
import * as configApi from '../../config.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
import { sanitizeText } from '../common/common.js'; import { sanitizeText } from '../common/common.js';
import { import {
setAccTitle, setAccTitle,
@ -33,7 +33,7 @@ export const getC4Type = function () {
}; };
export const setC4Type = function (c4TypeParam) { export const setC4Type = function (c4TypeParam) {
let sanitizedText = sanitizeText(c4TypeParam, configApi.getConfig()); let sanitizedText = sanitizeText(c4TypeParam, getConfig());
c4Type = sanitizedText; c4Type = sanitizedText;
}; };
@ -783,7 +783,7 @@ export const PLACEMENT = {
}; };
export const setTitle = function (txt) { export const setTitle = function (txt) {
let sanitizedText = sanitizeText(txt, configApi.getConfig()); let sanitizedText = sanitizeText(txt, getConfig());
title = sanitizedText; title = sanitizedText;
}; };
@ -816,7 +816,7 @@ export default {
getAccTitle, getAccTitle,
getAccDescription, getAccDescription,
setAccDescription, setAccDescription,
getConfig: () => configApi.getConfig().c4, getConfig: () => getConfig().c4,
clear, clear,
LINETYPE, LINETYPE,
ARROWTYPE, ARROWTYPE,

View File

@ -4,7 +4,7 @@ import { log } from '../../logger.js';
import { parser } from './parser/c4Diagram.jison'; import { parser } from './parser/c4Diagram.jison';
import common from '../common/common.js'; import common from '../common/common.js';
import c4Db from './c4Db.js'; import c4Db from './c4Db.js';
import * as configApi from '../../config.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
import assignWithDepth from '../../assignWithDepth.js'; import assignWithDepth from '../../assignWithDepth.js';
import { wrapLabel, calculateTextWidth, calculateTextHeight } from '../../utils.js'; import { wrapLabel, calculateTextWidth, calculateTextHeight } from '../../utils.js';
import { configureSvgSize } from '../../setupGraphViewbox.js'; import { configureSvgSize } from '../../setupGraphViewbox.js';
@ -580,8 +580,8 @@ function drawInsideBoundary(
* @param diagObj * @param diagObj
*/ */
export const draw = function (_text, id, _version, diagObj) { export const draw = function (_text, id, _version, diagObj) {
conf = configApi.getConfig().c4; conf = getConfig().c4;
const securityLevel = configApi.getConfig().securityLevel; const securityLevel = getConfig().securityLevel;
// Handle root and Document for when rendering in sandbox mode // Handle root and Document for when rendering in sandbox mode
let sandboxElement; let sandboxElement;
if (securityLevel === 'sandbox') { if (securityLevel === 'sandbox') {

View File

@ -1,7 +1,7 @@
import type { Selection } from 'd3'; import type { Selection } from 'd3';
import { select } from 'd3'; import { select } from 'd3';
import { log } from '../../logger.js'; import { log } from '../../logger.js';
import * as configApi from '../../config.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
import common from '../common/common.js'; import common from '../common/common.js';
import utils from '../../utils.js'; import utils from '../../utils.js';
import { import {
@ -34,10 +34,10 @@ let namespaceCounter = 0;
let functions: any[] = []; let functions: any[] = [];
const sanitizeText = (txt: string) => common.sanitizeText(txt, configApi.getConfig()); const sanitizeText = (txt: string) => common.sanitizeText(txt, getConfig());
const splitClassNameAndType = function (_id: string) { const splitClassNameAndType = function (_id: string) {
const id = common.sanitizeText(_id, configApi.getConfig()); const id = common.sanitizeText(_id, getConfig());
let genericType = ''; let genericType = '';
let className = id; let className = id;
@ -51,7 +51,7 @@ const splitClassNameAndType = function (_id: string) {
}; };
export const setClassLabel = function (_id: string, label: string) { export const setClassLabel = function (_id: string, label: string) {
const id = common.sanitizeText(_id, configApi.getConfig()); const id = common.sanitizeText(_id, getConfig());
if (label) { if (label) {
label = sanitizeText(label); label = sanitizeText(label);
} }
@ -67,14 +67,14 @@ export const setClassLabel = function (_id: string, label: string) {
* @public * @public
*/ */
export const addClass = function (_id: string) { export const addClass = function (_id: string) {
const id = common.sanitizeText(_id, configApi.getConfig()); const id = common.sanitizeText(_id, getConfig());
const { className, type } = splitClassNameAndType(id); const { className, type } = splitClassNameAndType(id);
// Only add class if not exists // Only add class if not exists
if (Object.hasOwn(classes, className)) { if (Object.hasOwn(classes, className)) {
return; return;
} }
// alert('Adding class: ' + className); // alert('Adding class: ' + className);
const name = common.sanitizeText(className, configApi.getConfig()); const name = common.sanitizeText(className, getConfig());
// alert('Adding class after: ' + name); // alert('Adding class after: ' + name);
classes[name] = { classes[name] = {
id: name, id: name,
@ -97,7 +97,7 @@ export const addClass = function (_id: string) {
* @public * @public
*/ */
export const lookUpDomId = function (_id: string): string { export const lookUpDomId = function (_id: string): string {
const id = common.sanitizeText(_id, configApi.getConfig()); const id = common.sanitizeText(_id, getConfig());
if (id in classes) { if (id in classes) {
return classes[id].domId; return classes[id].domId;
} }
@ -139,15 +139,9 @@ export const addRelation = function (relation: ClassRelation) {
relation.id1 = splitClassNameAndType(relation.id1).className; relation.id1 = splitClassNameAndType(relation.id1).className;
relation.id2 = splitClassNameAndType(relation.id2).className; relation.id2 = splitClassNameAndType(relation.id2).className;
relation.relationTitle1 = common.sanitizeText( relation.relationTitle1 = common.sanitizeText(relation.relationTitle1.trim(), getConfig());
relation.relationTitle1.trim(),
configApi.getConfig()
);
relation.relationTitle2 = common.sanitizeText( relation.relationTitle2 = common.sanitizeText(relation.relationTitle2.trim(), getConfig());
relation.relationTitle2.trim(),
configApi.getConfig()
);
relations.push(relation); relations.push(relation);
}; };
@ -267,7 +261,7 @@ export const getTooltip = function (id: string, namespace?: string) {
* @param target - Target of the link, _blank by default as originally defined in the svgDraw.js file * @param target - Target of the link, _blank by default as originally defined in the svgDraw.js file
*/ */
export const setLink = function (ids: string, linkStr: string, target: string) { export const setLink = function (ids: string, linkStr: string, target: string) {
const config = configApi.getConfig(); const config = getConfig();
ids.split(',').forEach(function (_id) { ids.split(',').forEach(function (_id) {
let id = _id; let id = _id;
if (_id[0].match(/\d/)) { if (_id[0].match(/\d/)) {
@ -303,8 +297,8 @@ export const setClickEvent = function (ids: string, functionName: string, functi
}; };
const setClickFunc = function (_domId: string, functionName: string, functionArgs: string) { const setClickFunc = function (_domId: string, functionName: string, functionArgs: string) {
const domId = common.sanitizeText(_domId, configApi.getConfig()); const domId = common.sanitizeText(_domId, getConfig());
const config = configApi.getConfig(); const config = getConfig();
if (config.securityLevel !== 'loose') { if (config.securityLevel !== 'loose') {
return; return;
} }
@ -465,7 +459,7 @@ export default {
getAccTitle, getAccTitle,
getAccDescription, getAccDescription,
setAccDescription, setAccDescription,
getConfig: () => configApi.getConfig().class, getConfig: () => getConfig().class,
addClass, addClass,
bindFunctions, bindFunctions,
clear, clear,

View File

@ -2,7 +2,7 @@
import { select, curveLinear } from 'd3'; import { select, curveLinear } from 'd3';
import * as graphlib from 'dagre-d3-es/src/graphlib/index.js'; import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
import { log } from '../../logger.js'; import { log } from '../../logger.js';
import { getConfig } from '../../config.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
import { render } from '../../dagre-wrapper/index.js'; import { render } from '../../dagre-wrapper/index.js';
import utils from '../../utils.js'; import utils from '../../utils.js';
import { interpolateToCurve, getStylesFromArray } from '../../utils.js'; import { interpolateToCurve, getStylesFromArray } from '../../utils.js';
@ -231,7 +231,7 @@ export const addRelations = function (relations: ClassRelation[], g: graphlib.Gr
//Set relationship style and line type //Set relationship style and line type
classes: 'relation', classes: 'relation',
pattern: edge.relation.lineType == 1 ? 'dashed' : 'solid', pattern: edge.relation.lineType == 1 ? 'dashed' : 'solid',
id: 'id' + cnt, id: `id_${edge.id1}_${edge.id2}_${cnt}`,
// Set link type for rendering // Set link type for rendering
arrowhead: edge.type === 'arrow_open' ? 'none' : 'normal', arrowhead: edge.type === 'arrow_open' ? 'none' : 'normal',
//Set edge extra labels //Set edge extra labels

View File

@ -4,7 +4,7 @@ import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
import { log } from '../../logger.js'; import { log } from '../../logger.js';
import svgDraw from './svgDraw.js'; import svgDraw from './svgDraw.js';
import { configureSvgSize } from '../../setupGraphViewbox.js'; import { configureSvgSize } from '../../setupGraphViewbox.js';
import { getConfig } from '../../config.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
let idCache = {}; let idCache = {};
const padding = 20; const padding = 20;

View File

@ -1,4 +1,4 @@
import { getConfig } from '../../config.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
import { parseGenericTypes, sanitizeText } from '../common/common.js'; import { parseGenericTypes, sanitizeText } from '../common/common.js';
export interface ClassNode { export interface ClassNode {

View File

@ -1,7 +1,6 @@
const getStyles = (options) => const getStyles = (options) =>
`g.classGroup text { `g.classGroup text {
fill: ${options.nodeBorder}; fill: ${options.nodeBorder || options.classText};
fill: ${options.classText};
stroke: none; stroke: none;
font-family: ${options.fontFamily}; font-family: ${options.fontFamily};
font-size: 10px; font-size: 10px;

View File

@ -38,6 +38,20 @@ describe('when securityLevel is antiscript, all script must be removed', () => {
compareRemoveScript(`<img onerror="alert('hello');">`, `<img>`); compareRemoveScript(`<img onerror="alert('hello');">`, `<img>`);
}); });
it('should detect unsecured target attribute, if value is _blank then generate a secured link', () => {
compareRemoveScript(
`<a href="https://mermaid.js.org/" target="_blank">note about mermaid</a>`,
`<a href="https://mermaid.js.org/" target="_blank" rel="noopener">note about mermaid</a>`
);
});
it('should detect unsecured target attribute from links', () => {
compareRemoveScript(
`<a href="https://mermaid.js.org/" target="_self">note about mermaid</a>`,
`<a href="https://mermaid.js.org/" target="_self">note about mermaid</a>`
);
});
it('should detect iframes', () => { it('should detect iframes', () => {
compareRemoveScript( compareRemoveScript(
`<iframe src="http://abc.com/script1.js"></iframe> `<iframe src="http://abc.com/script1.js"></iframe>

View File

@ -25,7 +25,27 @@ export const getRows = (s?: string): string[] => {
* @returns The safer text * @returns The safer text
*/ */
export const removeScript = (txt: string): string => { export const removeScript = (txt: string): string => {
return DOMPurify.sanitize(txt); const TEMPORARY_ATTRIBUTE = 'data-temp-href-target';
DOMPurify.addHook('beforeSanitizeAttributes', (node: Element) => {
if (node.tagName === 'A' && node.hasAttribute('target')) {
node.setAttribute(TEMPORARY_ATTRIBUTE, node.getAttribute('target') || '');
}
});
const sanitizedText = DOMPurify.sanitize(txt);
DOMPurify.addHook('afterSanitizeAttributes', (node: Element) => {
if (node.tagName === 'A' && node.hasAttribute(TEMPORARY_ATTRIBUTE)) {
node.setAttribute('target', node.getAttribute(TEMPORARY_ATTRIBUTE) || '');
node.removeAttribute(TEMPORARY_ATTRIBUTE);
if (node.getAttribute('target') === '_blank') {
node.setAttribute('rel', 'noopener');
}
}
});
return sanitizedText;
}; };
const sanitizeMore = (text: string, config: MermaidConfig) => { const sanitizeMore = (text: string, config: MermaidConfig) => {

View File

@ -1,5 +1,5 @@
import { log } from '../../logger.js'; import { log } from '../../logger.js';
import * as configApi from '../../config.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
import { import {
setAccTitle, setAccTitle,
@ -83,7 +83,7 @@ const clear = function () {
export default { export default {
Cardinality, Cardinality,
Identification, Identification,
getConfig: () => configApi.getConfig().er, getConfig: () => getConfig().er,
addEntity, addEntity,
addAttributes, addAttributes,
getEntities, getEntities,

View File

@ -1,7 +1,7 @@
import * as graphlib from 'dagre-d3-es/src/graphlib/index.js'; import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
import { line, curveBasis, select } from 'd3'; import { line, curveBasis, select } from 'd3';
import { layout as dagreLayout } from 'dagre-d3-es/src/dagre/index.js'; import { layout as dagreLayout } from 'dagre-d3-es/src/dagre/index.js';
import { getConfig } from '../../config.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
import { log } from '../../logger.js'; import { log } from '../../logger.js';
import utils from '../../utils.js'; import utils from '../../utils.js';
import erMarkers from './erMarkers.js'; import erMarkers from './erMarkers.js';
@ -202,7 +202,7 @@ const drawAttributes = (groupNode, entityTextNode, attributes) => {
let attribStyle = 'attributeBoxOdd'; // We will flip the style on alternate rows to achieve a banded effect let attribStyle = 'attributeBoxOdd'; // We will flip the style on alternate rows to achieve a banded effect
attributeNodes.forEach((attributeNode) => { attributeNodes.forEach((attributeNode) => {
// Calculate the alignment y co-ordinate for the type/name of the attribute // Calculate the alignment y coordinate for the type/name of the attribute
const alignY = heightOffset + heightPadding + attributeNode.height / 2; const alignY = heightOffset + heightPadding + attributeNode.height / 2;
// Position the type attribute // Position the type attribute
@ -579,8 +579,8 @@ export const draw = function (text, id, _version, diagObj) {
// 2. Make sure they are all added to the graph // 2. Make sure they are all added to the graph
// 3. Add all the edges (relationships) to the graph as well // 3. Add all the edges (relationships) to the graph as well
// 4. Let dagre do its magic to lay out the graph. This assigns: // 4. Let dagre do its magic to lay out the graph. This assigns:
// - the centre co-ordinates for each node, bearing in mind the dimensions and edge relationships // - the centre coordinates for each node, bearing in mind the dimensions and edge relationships
// - the path co-ordinates for each edge // - the path coordinates for each edge
// But it has no impact on the svg child nodes - the diagram remains with every entity rooted at 0,0 // But it has no impact on the svg child nodes - the diagram remains with every entity rooted at 0,0
// 5. Now assign a transform to each entity in the svg node so that it gets drawn in the correct place, as determined by // 5. Now assign a transform to each entity in the svg node so that it gets drawn in the correct place, as determined by
// its centre point, which is obtained from the graph, and it's width and height // its centre point, which is obtained from the graph, and it's width and height

View File

@ -92,7 +92,7 @@ describe('when parsing ER diagram it...', function () {
}); });
}); });
it('cannot contain % because it interfers with parsing comments', function () { it('cannot contain % because it interferes with parsing comments', function () {
expect(() => { expect(() => {
erDiagram.parser.parse(`erDiagram\n "Blo%rf"\n`); erDiagram.parser.parse(`erDiagram\n "Blo%rf"\n`);
const entities = erDb.getEntities(); const entities = erDb.getEntities();

View File

@ -561,7 +561,7 @@ export const addEdges = function (edges, diagObj, graph, svg) {
}; };
// TODO: break out and share with dagre wrapper. The current code in dagre wrapper also adds // TODO: break out and share with dagre wrapper. The current code in dagre wrapper also adds
// adds the line to the graph, but we don't need that here. This is why we cant use the dagre // adds the line to the graph, but we don't need that here. This is why we can't use the dagre
// wrapper directly for this // wrapper directly for this
/** /**
* Add the markers to the edge depending on the type of arrow is * Add the markers to the edge depending on the type of arrow is
@ -803,8 +803,14 @@ const insertChildren = (nodeArray, parentLookupDb) => {
*/ */
export const draw = async function (text, id, _version, diagObj) { export const draw = async function (text, id, _version, diagObj) {
// Add temporary render element
diagObj.db.clear();
nodeDb = {}; nodeDb = {};
portPos = {}; portPos = {};
diagObj.db.setGen('gen-2');
// Parse the graph definition
diagObj.parser.parse(text);
const renderEl = select('body').append('div').attr('style', 'height:400px').attr('id', 'cy'); const renderEl = select('body').append('div').attr('style', 'height:400px').attr('id', 'cy');
let graph = { let graph = {
id: 'root', id: 'root',

View File

@ -1,6 +1,6 @@
import { select } from 'd3'; import { select } from 'd3';
import utils from '../../utils.js'; import utils from '../../utils.js';
import * as configApi from '../../config.js'; import { getConfig, defaultConfig } from '../../diagram-api/diagramAPI.js';
import common from '../common/common.js'; import common from '../common/common.js';
import { log } from '../../logger.js'; import { log } from '../../logger.js';
import { import {
@ -12,10 +12,11 @@ import {
setDiagramTitle, setDiagramTitle,
getDiagramTitle, getDiagramTitle,
} from '../common/commonDb.js'; } from '../common/commonDb.js';
import errorDiagram from '../error/errorDiagram.js';
const MERMAID_DOM_ID_PREFIX = 'flowchart-'; const MERMAID_DOM_ID_PREFIX = 'flowchart-';
let vertexCounter = 0; let vertexCounter = 0;
let config = configApi.getConfig(); let config = getConfig();
let vertices = {}; let vertices = {};
let edges = []; let edges = [];
let classes = {}; let classes = {};
@ -84,7 +85,7 @@ export const addVertex = function (_id, textObj, type, style, classes, dir, prop
} }
vertexCounter++; vertexCounter++;
if (textObj !== undefined) { if (textObj !== undefined) {
config = configApi.getConfig(); config = getConfig();
txt = sanitizeText(textObj.text.trim()); txt = sanitizeText(textObj.text.trim());
vertices[id].labelType = textObj.type; vertices[id].labelType = textObj.type;
// strip quotes if string starts and ends with a quote // strip quotes if string starts and ends with a quote
@ -156,7 +157,15 @@ export const addSingleLink = function (_start, _end, type) {
edge.stroke = type.stroke; edge.stroke = type.stroke;
edge.length = type.length; edge.length = type.length;
} }
edges.push(edge); if (edge?.length > 10) {
edge.length = 10;
}
if (edges.length < 280) {
log.info('abc78 pushing edge...');
edges.push(edge);
} else {
throw new Error('Too many edges');
}
}; };
export const addLink = function (_start, _end, type) { export const addLink = function (_start, _end, type) {
log.info('addLink (abc78)', _start, _end, type); log.info('addLink (abc78)', _start, _end, type);
@ -192,6 +201,13 @@ export const updateLinkInterpolate = function (positions, interp) {
*/ */
export const updateLink = function (positions, style) { export const updateLink = function (positions, style) {
positions.forEach(function (pos) { positions.forEach(function (pos) {
if (pos >= edges.length) {
throw new Error(
`The index ${pos} for linkStyle is out of bounds. Valid indices for linkStyle are between 0 and ${
edges.length - 1
}. (Help: Ensure that the index is within the range of existing edges.)`
);
}
if (pos === 'default') { if (pos === 'default') {
edges.defaultStyle = style; edges.defaultStyle = style;
} else { } else {
@ -277,7 +293,7 @@ const setTooltip = function (ids, tooltip) {
const setClickFun = function (id, functionName, functionArgs) { const setClickFun = function (id, functionName, functionArgs) {
let domId = lookUpDomId(id); let domId = lookUpDomId(id);
// if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id; // if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
if (configApi.getConfig().securityLevel !== 'loose') { if (getConfig().securityLevel !== 'loose') {
return; return;
} }
if (functionName === undefined) { if (functionName === undefined) {
@ -416,7 +432,7 @@ const setupToolTips = function (element) {
tooltipElem tooltipElem
.text(el.attr('title')) .text(el.attr('title'))
.style('left', window.scrollX + rect.left + (rect.right - rect.left) / 2 + 'px') .style('left', window.scrollX + rect.left + (rect.right - rect.left) / 2 + 'px')
.style('top', window.scrollY + rect.top - 14 + document.body.scrollTop + 'px'); .style('top', window.scrollY + rect.bottom + 'px');
tooltipElem.html(tooltipElem.html().replace(/&lt;br\/&gt;/g, '<br/>')); tooltipElem.html(tooltipElem.html().replace(/&lt;br\/&gt;/g, '<br/>'));
el.classed('hover', true); el.classed('hover', true);
}) })
@ -766,7 +782,7 @@ export const lex = {
firstGraph, firstGraph,
}; };
export default { export default {
defaultConfig: () => configApi.defaultConfig.flowchart, defaultConfig: () => defaultConfig.flowchart,
setAccTitle, setAccTitle,
getAccTitle, getAccTitle,
getAccDescription, getAccDescription,

View File

@ -4,7 +4,7 @@ import flowDb from './flowDb.js';
import flowRendererV2 from './flowRenderer-v2.js'; import flowRendererV2 from './flowRenderer-v2.js';
import flowStyles from './styles.js'; import flowStyles from './styles.js';
import type { MermaidConfig } from '../../config.type.js'; import type { MermaidConfig } from '../../config.type.js';
import { setConfig } from '../../config.js'; import { setConfig } from '../../diagram-api/diagramAPI.js';
export const diagram = { export const diagram = {
parser: flowParser, parser: flowParser,

View File

@ -1,6 +1,6 @@
import * as graphlib from 'dagre-d3-es/src/graphlib/index.js'; import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
import { select, curveLinear, selectAll } from 'd3'; import { select, curveLinear, selectAll } from 'd3';
import { getConfig } from '../../config.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
import utils from '../../utils.js'; import utils from '../../utils.js';
import { render } from '../../dagre-wrapper/index.js'; import { render } from '../../dagre-wrapper/index.js';
import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js'; import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js';

View File

@ -1,6 +1,6 @@
import * as graphlib from 'dagre-d3-es/src/graphlib/index.js'; import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
import { select, curveLinear, selectAll } from 'd3'; import { select, curveLinear, selectAll } from 'd3';
import { getConfig } from '../../config.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
import { render as Render } from 'dagre-d3-es'; import { render as Render } from 'dagre-d3-es';
import { applyStyle } from 'dagre-d3-es/src/dagre-js/util.js'; import { applyStyle } from 'dagre-d3-es/src/dagre-js/util.js';
import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js'; import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js';

View File

@ -1,5 +1,5 @@
import { addVertices, addEdges } from './flowRenderer.js'; import { addVertices, addEdges } from './flowRenderer.js';
import { setConfig } from '../../config.js'; import { setConfig } from '../../diagram-api/diagramAPI.js';
setConfig({ setConfig({
flowchart: { flowchart: {

View File

@ -286,6 +286,30 @@ describe('[Style] when parsing', () => {
expect(edges[0].type).toBe('arrow_point'); expect(edges[0].type).toBe('arrow_point');
}); });
it('should handle style definitions within number of edges', function () {
expect(() =>
flow.parser
.parse(
`graph TD
A-->B
linkStyle 1 stroke-width:1px;`
)
.toThrow(
'The index 1 for linkStyle is out of bounds. Valid indices for linkStyle are between 0 and 0. (Help: Ensure that the index is within the range of existing edges.)'
)
);
});
it('should handle style definitions within number of edges', function () {
const res = flow.parser.parse(`graph TD
A-->B
linkStyle 0 stroke-width:1px;`);
const edges = flow.parser.yy.getEdges();
expect(edges[0].style[0]).toBe('stroke-width:1px');
});
it('should handle multi-numbered style definitions with more then 1 digit in a row', function () { it('should handle multi-numbered style definitions with more then 1 digit in a row', function () {
const res = flow.parser.parse( const res = flow.parser.parse(
'graph TD\n' + 'graph TD\n' +

View File

@ -535,6 +535,10 @@ describe('[Text] when parsing', () => {
expect(vert['A'].text).toBe('this is an ellipse'); expect(vert['A'].text).toBe('this is an ellipse');
}); });
it('should not freeze when ellipse text has a `(`', function () {
expect(() => flow.parser.parse('graph\nX(- My Text (')).toThrowError();
});
it('should handle text in diamond vertices with space', function () { it('should handle text in diamond vertices with space', function () {
const res = flow.parser.parse('graph TD;A(chimpansen hoppar)-->C;'); const res = flow.parser.parse('graph TD;A(chimpansen hoppar)-->C;');

View File

@ -134,7 +134,7 @@ that id.
<*>\s*\~\~[\~]+\s* return 'LINK'; <*>\s*\~\~[\~]+\s* return 'LINK';
<ellipseText>[-/\)][\)] { this.popState(); return '-)'; } <ellipseText>[-/\)][\)] { this.popState(); return '-)'; }
<ellipseText>[^\(\)\[\]\{\}]|-/!\)+ return "TEXT" <ellipseText>[^\(\)\[\]\{\}]|-\!\)+ return "TEXT"
<*>"(-" { this.pushState("ellipseText"); return '(-'; } <*>"(-" { this.pushState("ellipseText"); return '(-'; }
<text>"])" { this.popState(); return 'STADIUMEND'; } <text>"])" { this.popState(); return 'STADIUMEND'; }

View File

@ -4,7 +4,7 @@ import dayjsIsoWeek from 'dayjs/plugin/isoWeek.js';
import dayjsCustomParseFormat from 'dayjs/plugin/customParseFormat.js'; import dayjsCustomParseFormat from 'dayjs/plugin/customParseFormat.js';
import dayjsAdvancedFormat from 'dayjs/plugin/advancedFormat.js'; import dayjsAdvancedFormat from 'dayjs/plugin/advancedFormat.js';
import { log } from '../../logger.js'; import { log } from '../../logger.js';
import * as configApi from '../../config.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
import utils from '../../utils.js'; import utils from '../../utils.js';
import { import {
@ -603,7 +603,7 @@ const compileTasks = function () {
*/ */
export const setLink = function (ids, _linkStr) { export const setLink = function (ids, _linkStr) {
let linkStr = _linkStr; let linkStr = _linkStr;
if (configApi.getConfig().securityLevel !== 'loose') { if (getConfig().securityLevel !== 'loose') {
linkStr = sanitizeUrl(_linkStr); linkStr = sanitizeUrl(_linkStr);
} }
ids.split(',').forEach(function (id) { ids.split(',').forEach(function (id) {
@ -634,7 +634,7 @@ export const setClass = function (ids, className) {
}; };
const setClickFun = function (id, functionName, functionArgs) { const setClickFun = function (id, functionName, functionArgs) {
if (configApi.getConfig().securityLevel !== 'loose') { if (getConfig().securityLevel !== 'loose') {
return; return;
} }
if (functionName === undefined) { if (functionName === undefined) {
@ -725,7 +725,7 @@ export const bindFunctions = function (element) {
}; };
export default { export default {
getConfig: () => configApi.getConfig().gantt, getConfig: () => getConfig().gantt,
clear, clear,
setDateFormat, setDateFormat,
getDateFormat, getDateFormat,

View File

@ -25,7 +25,7 @@ import {
timeMonth, timeMonth,
} from 'd3'; } from 'd3';
import common from '../common/common.js'; import common from '../common/common.js';
import { getConfig } from '../../config.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
import { configureSvgSize } from '../../setupGraphViewbox.js'; import { configureSvgSize } from '../../setupGraphViewbox.js';
export const setConf = function () { export const setConf = function () {

View File

@ -1,9 +1,9 @@
const getStyles = (options) => const getStyles = (options) =>
` `
.mermaid-main-font { .mermaid-main-font {
font-family: "trebuchet ms", verdana, arial, sans-serif; font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
font-family: var(--mermaid-font-family);
} }
.exclude-range { .exclude-range {
fill: ${options.excludeBkgColor}; fill: ${options.excludeBkgColor};
} }
@ -45,11 +45,7 @@ const getStyles = (options) =>
.sectionTitle { .sectionTitle {
text-anchor: start; text-anchor: start;
// font-size: ${options.ganttFontSize}; font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
// text-height: 14px;
font-family: 'trebuchet ms', verdana, arial, sans-serif;
font-family: var(--mermaid-font-family);
} }
@ -59,10 +55,11 @@ const getStyles = (options) =>
stroke: ${options.gridColor}; stroke: ${options.gridColor};
opacity: 0.8; opacity: 0.8;
shape-rendering: crispEdges; shape-rendering: crispEdges;
text { }
font-family: ${options.fontFamily};
fill: ${options.textColor}; .grid .tick text {
} font-family: ${options.fontFamily};
fill: ${options.textColor};
} }
.grid path { .grid path {
@ -89,33 +86,27 @@ const getStyles = (options) =>
.taskText { .taskText {
text-anchor: middle; text-anchor: middle;
font-family: 'trebuchet ms', verdana, arial, sans-serif; font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
font-family: var(--mermaid-font-family);
} }
// .taskText:not([font-size]) {
// font-size: ${options.ganttFontSize};
// }
.taskTextOutsideRight { .taskTextOutsideRight {
fill: ${options.taskTextDarkColor}; fill: ${options.taskTextDarkColor};
text-anchor: start; text-anchor: start;
// font-size: ${options.ganttFontSize}; font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
font-family: 'trebuchet ms', verdana, arial, sans-serif;
font-family: var(--mermaid-font-family);
} }
.taskTextOutsideLeft { .taskTextOutsideLeft {
fill: ${options.taskTextDarkColor}; fill: ${options.taskTextDarkColor};
text-anchor: end; text-anchor: end;
// font-size: ${options.ganttFontSize};
} }
/* Special case clickable */ /* Special case clickable */
.task.clickable { .task.clickable {
cursor: pointer; cursor: pointer;
} }
.taskText.clickable { .taskText.clickable {
cursor: pointer; cursor: pointer;
fill: ${options.taskTextClickableColor} !important; fill: ${options.taskTextClickableColor} !important;
@ -134,6 +125,7 @@ const getStyles = (options) =>
font-weight: bold; font-weight: bold;
} }
/* Specific task settings for the sections*/ /* Specific task settings for the sections*/
.taskText0, .taskText0,
@ -255,9 +247,8 @@ const getStyles = (options) =>
.titleText { .titleText {
text-anchor: middle; text-anchor: middle;
font-size: 18px; font-size: 18px;
fill: ${options.textColor} ; fill: ${options.titleColor || options.textColor};
font-family: 'trebuchet ms', verdana, arial, sans-serif; font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
font-family: var(--mermaid-font-family);
} }
`; `;

View File

@ -1,7 +1,6 @@
import { log } from '../../logger.js'; import { log } from '../../logger.js';
import { random } from '../../utils.js'; import { random } from '../../utils.js';
import * as configApi from '../../config.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
import { getConfig } from '../../config.js';
import common from '../common/common.js'; import common from '../common/common.js';
import { import {
setAccTitle, setAccTitle,
@ -106,9 +105,9 @@ export const getOptions = function () {
export const commit = function (msg, id, type, tag) { export const commit = function (msg, id, type, tag) {
log.debug('Entering commit:', msg, id, type, tag); log.debug('Entering commit:', msg, id, type, tag);
id = common.sanitizeText(id, configApi.getConfig()); id = common.sanitizeText(id, getConfig());
msg = common.sanitizeText(msg, configApi.getConfig()); msg = common.sanitizeText(msg, getConfig());
tag = common.sanitizeText(tag, configApi.getConfig()); tag = common.sanitizeText(tag, getConfig());
const commit = { const commit = {
id: id ? id : seq + '-' + getId(), id: id ? id : seq + '-' + getId(),
message: msg, message: msg,
@ -125,7 +124,7 @@ export const commit = function (msg, id, type, tag) {
}; };
export const branch = function (name, order) { export const branch = function (name, order) {
name = common.sanitizeText(name, configApi.getConfig()); name = common.sanitizeText(name, getConfig());
if (branches[name] === undefined) { if (branches[name] === undefined) {
branches[name] = head != null ? head.id : null; branches[name] = head != null ? head.id : null;
branchesConfig[name] = { name, order: order ? parseInt(order, 10) : null }; branchesConfig[name] = { name, order: order ? parseInt(order, 10) : null };
@ -149,8 +148,8 @@ export const branch = function (name, order) {
}; };
export const merge = function (otherBranch, custom_id, override_type, custom_tag) { export const merge = function (otherBranch, custom_id, override_type, custom_tag) {
otherBranch = common.sanitizeText(otherBranch, configApi.getConfig()); otherBranch = common.sanitizeText(otherBranch, getConfig());
custom_id = common.sanitizeText(custom_id, configApi.getConfig()); custom_id = common.sanitizeText(custom_id, getConfig());
const currentCommit = commits[branches[curBranch]]; const currentCommit = commits[branches[curBranch]];
const otherCommit = commits[branches[otherBranch]]; const otherCommit = commits[branches[otherBranch]];
@ -258,9 +257,9 @@ export const merge = function (otherBranch, custom_id, override_type, custom_tag
export const cherryPick = function (sourceId, targetId, tag) { export const cherryPick = function (sourceId, targetId, tag) {
log.debug('Entering cherryPick:', sourceId, targetId, tag); log.debug('Entering cherryPick:', sourceId, targetId, tag);
sourceId = common.sanitizeText(sourceId, configApi.getConfig()); sourceId = common.sanitizeText(sourceId, getConfig());
targetId = common.sanitizeText(targetId, configApi.getConfig()); targetId = common.sanitizeText(targetId, getConfig());
tag = common.sanitizeText(tag, configApi.getConfig()); tag = common.sanitizeText(tag, getConfig());
if (!sourceId || commits[sourceId] === undefined) { if (!sourceId || commits[sourceId] === undefined) {
let error = new Error( let error = new Error(
@ -338,7 +337,7 @@ export const cherryPick = function (sourceId, targetId, tag) {
} }
}; };
export const checkout = function (branch) { export const checkout = function (branch) {
branch = common.sanitizeText(branch, configApi.getConfig()); branch = common.sanitizeText(branch, getConfig());
if (branches[branch] === undefined) { if (branches[branch] === undefined) {
let error = new Error( let error = new Error(
'Trying to checkout branch which is not yet created. (Help try using "branch ' + branch + '")' 'Trying to checkout branch which is not yet created. (Help try using "branch ' + branch + '")'
@ -502,7 +501,7 @@ export const commitType = {
}; };
export default { export default {
getConfig: () => configApi.getConfig().gitGraph, getConfig: () => getConfig().gitGraph,
setDirection, setDirection,
setOptions, setOptions,
getOptions, getOptions,

View File

@ -6,7 +6,7 @@ describe('when parsing a gitGraph', function () {
parser.yy = gitGraphAst; parser.yy = gitGraphAst;
parser.yy.clear(); parser.yy.clear();
}); });
it('should handle a gitGraph commit with NO pararms, get auto-genrated reandom ID', function () { it('should handle a gitGraph commit with NO pararms, get auto-generated reandom ID', function () {
const str = `gitGraph: const str = `gitGraph:
commit commit
`; `;

View File

@ -1,4 +1,4 @@
import { getConfig } from '../../config.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
export default (dir, _branches) => { export default (dir, _branches) => {
const config = getConfig().gitGraph; const config = getConfig().gitGraph;

View File

@ -129,7 +129,7 @@ root
expect(child.nodeId).toEqual('theId'); expect(child.nodeId).toEqual('theId');
expect(child.type).toEqual(mindmap.yy.nodeType.ROUNDED_RECT); expect(child.type).toEqual(mindmap.yy.nodeType.ROUNDED_RECT);
}); });
it('MMP-10 mutiple types (circle)', function () { it('MMP-10 multiple types (circle)', function () {
let str = `mindmap let str = `mindmap
root((the root)) root((the root))
`; `;
@ -141,7 +141,7 @@ root
expect(mm.type).toEqual(mindmap.yy.nodeType.CIRCLE); expect(mm.type).toEqual(mindmap.yy.nodeType.CIRCLE);
}); });
it('MMP-11 mutiple types (cloud)', function () { it('MMP-11 multiple types (cloud)', function () {
let str = `mindmap let str = `mindmap
root)the root( root)the root(
`; `;
@ -152,7 +152,7 @@ root
expect(mm.children.length).toEqual(0); expect(mm.children.length).toEqual(0);
expect(mm.type).toEqual(mindmap.yy.nodeType.CLOUD); expect(mm.type).toEqual(mindmap.yy.nodeType.CLOUD);
}); });
it('MMP-12 mutiple types (bang)', function () { it('MMP-12 multiple types (bang)', function () {
let str = `mindmap let str = `mindmap
root))the root(( root))the root((
`; `;
@ -164,7 +164,7 @@ root
expect(mm.type).toEqual(mindmap.yy.nodeType.BANG); expect(mm.type).toEqual(mindmap.yy.nodeType.BANG);
}); });
it('MMP-12-a mutiple types (hexagon)', function () { it('MMP-12-a multiple types (hexagon)', function () {
let str = `mindmap let str = `mindmap
root{{the root}} root{{the root}}
`; `;

View File

@ -1,4 +1,4 @@
import { getConfig } from '../../config.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
import { sanitizeText as _sanitizeText } from '../../diagrams/common/common.js'; import { sanitizeText as _sanitizeText } from '../../diagrams/common/common.js';
import { log } from '../../logger.js'; import { log } from '../../logger.js';

View File

@ -1,7 +1,7 @@
/** Created by knut on 14-12-11. */ /** Created by knut on 14-12-11. */
import { select } from 'd3'; import { select } from 'd3';
import { log } from '../../logger.js'; import { log } from '../../logger.js';
import { getConfig } from '../../config.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
import { setupGraphViewbox } from '../../setupGraphViewbox.js'; import { setupGraphViewbox } from '../../setupGraphViewbox.js';
import svgDraw from './svgDraw.js'; import svgDraw from './svgDraw.js';
import cytoscape from 'cytoscape/dist/cytoscape.umd.js'; import cytoscape from 'cytoscape/dist/cytoscape.umd.js';

View File

@ -1,6 +1,6 @@
import { parser } from './pieParser.js'; import { parser } from './pieParser.js';
import { DEFAULT_PIE_DB, db } from './pieDb.js'; import { DEFAULT_PIE_DB, db } from './pieDb.js';
import { setConfig } from '../../config.js'; import { setConfig } from '../../diagram-api/diagramAPI.js';
setConfig({ setConfig({
securityLevel: 'strict', securityLevel: 'strict',

View File

@ -3,7 +3,7 @@ import { scaleOrdinal, pie as d3pie, arc } from 'd3';
import { log } from '../../logger.js'; import { log } from '../../logger.js';
import { configureSvgSize } from '../../setupGraphViewbox.js'; import { configureSvgSize } from '../../setupGraphViewbox.js';
import { getConfig } from '../../config.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
import { cleanAndMerge, parseFontSize } from '../../utils.js'; import { cleanAndMerge, parseFontSize } from '../../utils.js';
import type { DrawDefinition, Group, SVG } from '../../diagram-api/types.js'; import type { DrawDefinition, Group, SVG } from '../../diagram-api/types.js';
import type { D3Section, PieDB, Sections } from './pieTypes.js'; import type { D3Section, PieDB, Sections } from './pieTypes.js';

View File

@ -1,4 +1,3 @@
// @ts-ignore: TODO Fix ts errors
import { scaleLinear } from 'd3'; import { scaleLinear } from 'd3';
import { log } from '../../logger.js'; import { log } from '../../logger.js';
import type { BaseDiagramConfig, QuadrantChartConfig } from '../../config.type.js'; import type { BaseDiagramConfig, QuadrantChartConfig } from '../../config.type.js';

View File

@ -1,4 +1,4 @@
import * as configApi from '../../config.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
import { sanitizeText } from '../common/common.js'; import { sanitizeText } from '../common/common.js';
import { import {
setAccTitle, setAccTitle,
@ -11,7 +11,7 @@ import {
} from '../common/commonDb.js'; } from '../common/commonDb.js';
import { QuadrantBuilder } from './quadrantBuilder.js'; import { QuadrantBuilder } from './quadrantBuilder.js';
const config = configApi.getConfig(); const config = getConfig();
function textSanitizer(text: string) { function textSanitizer(text: string) {
return sanitizeText(text.trim(), config); return sanitizeText(text.trim(), config);
@ -66,7 +66,7 @@ function setHeight(height: number) {
} }
function getQuadrantData() { function getQuadrantData() {
const config = configApi.getConfig(); const config = getConfig();
const { themeVariables, quadrantChart: quadrantChartConfig } = config; const { themeVariables, quadrantChart: quadrantChartConfig } = config;
if (quadrantChartConfig) { if (quadrantChartConfig) {
quadrantBuilder.setConfig(quadrantChartConfig); quadrantBuilder.setConfig(quadrantChartConfig);

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