Compare commits

..

1 Commits

Author SHA1 Message Date
Sidharth Vinod
f85f4bb661 Use undefined instead of null 2023-01-17 14:06:50 +05:30
636 changed files with 24151 additions and 51229 deletions

View File

@@ -3,6 +3,4 @@ dist/**
docs/Setup.md
cypress.config.js
cypress/plugins/index.js
coverage
*.json
node_modules
coverage

View File

@@ -1,165 +0,0 @@
module.exports = {
env: {
browser: true,
es6: true,
'jest/globals': true,
node: true,
},
root: true,
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
experimentalObjectRestSpread: true,
jsx: true,
},
tsconfigRootDir: __dirname,
sourceType: 'module',
ecmaVersion: 2020,
allowAutomaticSingleRunInference: true,
project: ['./tsconfig.eslint.json', './packages/*/tsconfig.json'],
parser: '@typescript-eslint/parser',
},
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:json/recommended',
'plugin:markdown/recommended',
'plugin:@cspell/recommended',
'prettier',
],
plugins: [
'@typescript-eslint',
'no-only-tests',
'html',
'jest',
'jsdoc',
'json',
'@cspell',
'lodash',
'unicorn',
],
ignorePatterns: [
// this file is automatically generated by `pnpm run --filter mermaid types:build-config`
'packages/mermaid/src/config.type.ts',
],
rules: {
curly: 'error',
'no-console': 'error',
'no-prototype-builtins': 'off',
'no-unused-vars': 'off',
'cypress/no-async-tests': 'off',
'@typescript-eslint/consistent-type-imports': 'error',
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/no-misused-promises': 'error',
'@typescript-eslint/no-unused-vars': 'warn',
'@typescript-eslint/ban-ts-comment': [
'error',
{
'ts-expect-error': 'allow-with-description',
'ts-ignore': 'allow-with-description',
'ts-nocheck': 'allow-with-description',
'ts-check': 'allow-with-description',
minimumDescriptionLength: 10,
},
],
'json/*': ['error', 'allowComments'],
'@cspell/spellchecker': [
'error',
{
checkIdentifiers: false,
checkStrings: false,
checkStringTemplates: false,
},
],
'no-empty': [
'error',
{
allowEmptyCatch: true,
},
],
'no-only-tests/no-only-tests': 'error',
'lodash/import-scope': ['error', 'method'],
'unicorn/better-regex': 'error',
'unicorn/no-abusive-eslint-disable': 'error',
'unicorn/no-array-push-push': 'error',
'unicorn/no-for-loop': 'error',
'unicorn/no-instanceof-array': 'error',
'unicorn/no-typeof-undefined': 'error',
'unicorn/no-unnecessary-await': 'error',
'unicorn/no-unsafe-regex': 'warn',
'unicorn/no-useless-promise-resolve-reject': 'error',
'unicorn/prefer-array-find': 'error',
'unicorn/prefer-array-flat-map': 'error',
'unicorn/prefer-array-index-of': 'error',
'unicorn/prefer-array-some': 'error',
'unicorn/prefer-default-parameters': 'error',
'unicorn/prefer-includes': 'error',
'unicorn/prefer-negative-index': 'error',
'unicorn/prefer-object-from-entries': 'error',
'unicorn/prefer-string-starts-ends-with': 'error',
'unicorn/prefer-string-trim-start-end': 'error',
'unicorn/string-content': 'error',
'unicorn/prefer-spread': 'error',
'unicorn/no-lonely-if': 'error',
},
overrides: [
{
files: ['cypress/**', 'demos/**'],
rules: {
'no-console': 'off',
},
},
{
files: ['*.{js,jsx,mjs,cjs}'],
extends: ['plugin:jsdoc/recommended'],
rules: {
'jsdoc/check-indentation': 'off',
'jsdoc/check-alignment': 'off',
'jsdoc/check-line-alignment': 'off',
'jsdoc/multiline-blocks': 'off',
'jsdoc/newline-after-description': 'off',
'jsdoc/tag-lines': 'off',
'jsdoc/require-param-description': 'off',
'jsdoc/require-param-type': 'off',
'jsdoc/require-returns': 'off',
'jsdoc/require-returns-description': 'off',
},
},
{
files: ['*.{ts,tsx}'],
plugins: ['tsdoc'],
rules: {
'no-restricted-syntax': [
'error',
{
selector: 'TSEnumDeclaration',
message:
'Prefer using TypeScript union types over TypeScript enum, since TypeScript enums have a bunch of issues, see https://dev.to/dvddpl/whats-the-problem-with-typescript-enums-2okj',
},
],
'tsdoc/syntax': 'error',
},
},
{
files: ['*.spec.{ts,js}', 'cypress/**', 'demos/**', '**/docs/**'],
rules: {
'jsdoc/require-jsdoc': 'off',
'@typescript-eslint/no-unused-vars': 'off',
},
},
{
files: ['*.html', '*.md', '**/*.md/*'],
rules: {
'no-var': 'error',
'no-undef': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/no-floating-promises': 'off',
'@typescript-eslint/no-misused-promises': 'off',
},
parserOptions: {
project: null,
},
},
],
};

138
.eslintrc.json Normal file
View File

@@ -0,0 +1,138 @@
{
"env": {
"browser": true,
"es6": true,
"jest/globals": true,
"node": true
},
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"experimentalObjectRestSpread": true,
"jsx": true
},
"sourceType": "module"
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:json/recommended",
"plugin:markdown/recommended",
"plugin:@cspell/recommended",
"prettier"
],
"plugins": [
"@typescript-eslint",
"no-only-tests",
"html",
"jest",
"jsdoc",
"json",
"@cspell",
"lodash",
"unicorn"
],
"rules": {
"curly": "error",
"no-console": "error",
"no-prototype-builtins": "off",
"no-unused-vars": "off",
"cypress/no-async-tests": "off",
"@typescript-eslint/ban-ts-comment": [
"error",
{
"ts-expect-error": "allow-with-description",
"ts-ignore": "allow-with-description",
"ts-nocheck": "allow-with-description",
"ts-check": "allow-with-description",
"minimumDescriptionLength": 10
}
],
"json/*": ["error", "allowComments"],
"@cspell/spellchecker": [
"error",
{
"checkIdentifiers": false,
"checkStrings": false,
"checkStringTemplates": false
}
],
"no-empty": [
"error",
{
"allowEmptyCatch": true
}
],
"no-only-tests/no-only-tests": "error",
"lodash/import-scope": ["error", "method"],
"unicorn/better-regex": "error",
"unicorn/no-abusive-eslint-disable": "error",
"unicorn/no-array-push-push": "error",
"unicorn/no-for-loop": "error",
"unicorn/no-null": "error",
"unicorn/no-instanceof-array": "error",
"unicorn/no-typeof-undefined": "error",
"unicorn/no-unnecessary-await": "error",
"unicorn/no-unsafe-regex": "warn",
"unicorn/no-useless-promise-resolve-reject": "error",
"unicorn/prefer-array-find": "error",
"unicorn/prefer-array-flat-map": "error",
"unicorn/prefer-array-index-of": "error",
"unicorn/prefer-array-some": "error",
"unicorn/prefer-default-parameters": "error",
"unicorn/prefer-includes": "error",
"unicorn/prefer-negative-index": "error",
"unicorn/prefer-object-from-entries": "error",
"unicorn/prefer-string-starts-ends-with": "error",
"unicorn/prefer-string-trim-start-end": "error",
"unicorn/string-content": "error",
"unicorn/prefer-spread": "error",
"unicorn/no-lonely-if": "error"
},
"overrides": [
{
"files": ["cypress/**", "demos/**"],
"rules": {
"no-console": "off"
}
},
{
"files": ["*.{js,jsx,mjs,cjs}"],
"extends": ["plugin:jsdoc/recommended"],
"rules": {
"jsdoc/check-indentation": "off",
"jsdoc/check-alignment": "off",
"jsdoc/check-line-alignment": "off",
"jsdoc/multiline-blocks": "off",
"jsdoc/newline-after-description": "off",
"jsdoc/tag-lines": "off",
"jsdoc/require-param-description": "off",
"jsdoc/require-param-type": "off",
"jsdoc/require-returns": "off",
"jsdoc/require-returns-description": "off"
}
},
{
"files": ["*.{ts,tsx}"],
"plugins": ["tsdoc"],
"rules": {
"tsdoc/syntax": "error"
}
},
{
"files": ["*.spec.{ts,js}", "cypress/**", "demos/**", "**/docs/**"],
"rules": {
"jsdoc/require-jsdoc": "off",
"@typescript-eslint/no-unused-vars": "off"
}
},
{
"files": ["*.html", "*.md", "**/*.md/*"],
"rules": {
"no-var": "error",
"no-undef": "off",
"@typescript-eslint/no-unused-vars": "off"
}
}
]
}

4
.github/FUNDING.yml vendored
View File

@@ -1,8 +1,6 @@
# These are supported funding model platforms
github:
- knsv
- sidharthv96
github: [knsv]
#patreon: # Replace with a single Patreon username
#open_collective: # Replace with a single Open Collective username
#ko_fi: # Replace with a single Ko-fi username

View File

@@ -17,9 +17,6 @@ body:
- Use a clear and concise title
- Fill out the text fields with as much detail as possible.
- Never be shy to give us screenshots and/or code samples. It will help!
There is a chance that the bug is already fixed in the git `develop` branch, but is not released yet.
So please check in [Live Editor - Develop](https://develop.git.mermaid.live) before raising an issue.
- type: textarea
attributes:
label: Description
@@ -46,27 +43,26 @@ body:
attributes:
label: Code Sample
description: |-
If applicable, add the code sample or a link to the [Live Editor - Develop](https://develop.git.mermaid.live).
If applicable, add the code sample or a link to the [Live Editor](https://mermaid.live).
Any text pasted here will be rendered as a Code block.
render: text
- type: textarea
attributes:
label: Setup
description: |-
Please fill out the info below.
Note that you only need to fill out the relevant section
Please fill out the below info.
Note that you only need to fill out one and not both sections.
value: |-
- Mermaid version:
**Desktop**
- OS and Version: [Windows, Linux, Mac, ...]
- Browser and Version: [Chrome, Edge, Firefox]
- type: textarea
attributes:
label: Suggested Solutions
description: >
If applicable, suggest solutions that could resolve the bug.
It would help maintainers/contributors to not waste time looking for the solution. Even pointing the line causing the bug would be great!
placeholder: |-
- Variable `parser` in file <filepath> is not initialised ...
- Add a new type for ...
**Smartphone**
- Device: [Samsung, iPhone, ...]
- OS and Version: [Android, iOS, ...]
- Browser and Version: [Chrome, Safari, ...]
- type: textarea
attributes:
label: Additional Context

View File

@@ -1,4 +1,4 @@
blank_issues_enabled: true
blank_issues_enabled: false
contact_links:
- name: GitHub Discussions
url: https://github.com/mermaid-js/mermaid/discussions
@@ -7,14 +7,8 @@ contact_links:
url: https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE
about: Join our Community on Slack for Help and a casual chat.
- name: Documentation
url: https://mermaid.js.org
url: https://mermaid-js.github.io
about: Read our documentation for all that Mermaid.js can offer.
- name: Live Editor
url: https://mermaid.live
about: Try the live editor to preview graphs in no time.
- name: Live Editor - Develop
url: https://develop.git.mermaid.live
about: Try unreleased changes in the develop branch.
- name: Live Editor - Next
url: https://next.git.mermaid.live
about: Try unreleased changes in the next branch.

View File

@@ -3,7 +3,6 @@ description: Suggest a new Diagram Type to add to Mermaid.
labels:
- 'Status: Triage'
- 'Type: Enhancement'
- 'Type: New Diagram'
body:
- type: markdown
@@ -18,14 +17,6 @@ body:
- Use a clear and concise title
- Fill out the text fields with as much detail as possible.
- Never be shy to give us screenshots and/or code samples. It will help!
## Example issues
Refer to the discussions here to get an idea of how the diagram syntax is created.
- https://github.com/mermaid-js/mermaid/issues/4269
- https://github.com/mermaid-js/mermaid/issues/4282
- type: textarea
attributes:
label: Proposal
@@ -44,17 +35,8 @@ body:
description: If applicable, add screenshots to show possible examples of how the diagram may look like.
- type: textarea
attributes:
label: Syntax
label: Code Sample
description: |-
If possible, include a syntax which could be used to write the diagram.
Try to add one or two examples of valid use-cases here.
- type: dropdown
id: implementation
attributes:
label: Implementation
description: |-
Would you like to implement this yourself, or is it a proposal for the community?
If there is no corresponding PR from your side after 30 days, the diagram will be open for everyone to implement.
options:
- I will try and implement it myself.
- This is a proposal which I'd love to see built into mermaid by the wonderful community.
If applicable, add a code sample for how to implement this new diagram.
The text will automatically be rendered as JavaScript code.
render: javascript

17
.github/codecov.yaml vendored
View File

@@ -1,17 +0,0 @@
codecov:
branch: develop
comment:
layout: 'reach, diff, flags, files'
behavior: default
require_changes: false # if true: only post the comment if coverage changes
require_base: no # [yes :: must have a base report to post]
require_head: yes # [yes :: must have a head report to post]
coverage:
status:
project:
off
# Turing off for now as code coverage isn't stable and causes unnecessary build failures.
# default:
# threshold: 2%

44
.github/lychee.toml vendored
View File

@@ -1,44 +0,0 @@
############################# Display #############################
# Verbose program output
# Accepts log level: "error", "warn", "info", "debug", "trace"
verbose = "debug"
# Don't show interactive progress bar while checking links.
no_progress = true
############################# Cache ###############################
# Enable link caching. This can be helpful to avoid checking the same links on
# multiple runs.
cache = true
# Discard all cached requests older than this duration.
max_cache_age = "1d"
############################# Requests ############################
# Comma-separated list of accepted status codes for valid links.
accept = [200, 429]
############################# Exclusions ##########################
# Exclude URLs and mail addresses from checking (supports regex).
exclude = [
# Network error: Forbidden
"https://codepen.io",
# Timeout error, maybe Twitter has anti-bot defenses against GitHub's CI servers?
"https://twitter.com/mermaidjs_",
# Don't check files that are generated during the build via `pnpm docs:code`
'packages/mermaid/src/docs/config/setup/*',
# Ignore slack invite
"https://join.slack.com/"
]
# Exclude all private IPs from checking.
# Equivalent to setting `exclude_private`, `exclude_link_local`, and
# `exclude_loopback` to true.
exclude_all_private = true

View File

@@ -1,22 +1,3 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/release-drafter/release-drafter/master/schema.json
autolabeler:
- label: 'Type: Bug / Error'
branch:
- '/bug\/.+/'
- '/fix\/.+/'
- label: 'Type: Enhancement'
branch:
- '/feature\/.+/'
- '/feat\/.+/'
- label: 'Type: Other'
branch:
- '/other\/.+/'
- '/chore\/.+/'
- '/test\/.+/'
- '/refactor\/.+/'
- label: 'Area: Documentation'
branch:
- '/docs\/.+/'
template: |
This field is unused, as we only use this config file for labeling PRs.
'Type: Bug / Error': 'bug/*'
'Type: Enhancement': 'feature/*'
'Type: Other': 'other/*'

View File

@@ -13,6 +13,6 @@ Describe the way your implementation works or what design decisions you made if
Make sure you
- [ ] :book: have read the [contribution guidelines](https://github.com/mermaid-js/mermaid/blob/develop/CONTRIBUTING.md)
- [ ] :computer: have added necessary unit/e2e tests.
- [ ] :notebook: have added documentation. Make sure [`MERMAID_RELEASE_VERSION`](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/docs/community/contributing.md#update-documentation) is used for all new features.
- [ ] :computer: have added unit/e2e tests (if appropriate)
- [ ] :notebook: have added documentation (if appropriate)
- [ ] :bookmark: targeted `develop` branch

View File

@@ -1,30 +1,19 @@
name-template: '$NEXT_PATCH_VERSION'
tag-template: '$NEXT_PATCH_VERSION'
categories:
- title: '🚨 **Breaking Changes**'
labels:
- 'Breaking Change'
- title: '🚀 Features'
labels:
- 'Type: Enhancement'
- 'feature' # deprecated, new PRs shouldn't have this
- title: '🐛 Bug Fixes'
labels:
- 'Type: Bug / Error'
- 'fix' # deprecated, new PRs shouldn't have this
- title: '🧰 Maintenance'
labels:
- 'Type: Other'
- 'chore' # deprecated, new PRs shouldn't have this
- title: '⚡️ Performance'
labels:
- 'Type: Performance'
- title: '📚 Documentation'
labels:
- 'Area: Documentation'
label: 'Type: Other'
change-template: '- $TITLE (#$NUMBER) @$AUTHOR'
sort-by: title
sort-direction: ascending
branches:
- develop
exclude-labels:
- 'Skip changelog'
no-changes-template: 'This release contains minor changes and bugfixes.'

View File

@@ -1,37 +0,0 @@
name: Build Vitepress docs
on:
push:
branches:
- master
- release/*
pull_request:
merge_group:
permissions:
contents: read
jobs:
build-docs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
- name: Setup Node.js
uses: actions/setup-node@v4
with:
cache: pnpm
node-version: 18
- name: Install Packages
run: pnpm install --frozen-lockfile
- name: Verify release version
if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release')) }}
run: pnpm --filter mermaid run docs:verify-version
- name: Run Build
run: pnpm --filter mermaid run docs:build:vitepress

View File

@@ -2,7 +2,6 @@ name: Build
on:
push: {}
merge_group:
pull_request:
types:
- opened
@@ -13,19 +12,19 @@ permissions:
contents: read
jobs:
build-mermaid:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
uses: actions/setup-node@v3
with:
cache: pnpm
node-version: ${{ matrix.node-version }}

View File

@@ -14,11 +14,11 @@ permissions:
contents: read
jobs:
check-readme:
check:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: Check for difference in README.md and docs/README.md
run: |

View File

@@ -1,21 +1,20 @@
on:
push:
merge_group:
push: {}
pull_request:
types:
- opened
- synchronize
- ready_for_review
name: Static analysis on Test files
name: Static analysis
jobs:
check-tests:
test:
runs-on: ubuntu-latest
name: check tests
if: github.repository_owner == 'mermaid-js'
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: testomatio/check-tests@stable

View File

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

View File

@@ -1,6 +1,6 @@
# Dependency Review Action
#
# 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.
# 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.
#
# 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
@@ -15,6 +15,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: 'Checkout Repository'
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: 'Dependency Review'
uses: actions/dependency-review-action@v3
uses: actions/dependency-review-action@v2

View File

@@ -19,7 +19,7 @@ env:
USE_APPLI: ${{ secrets.APPLITOOLS_API_KEY && 'true' || '' }}
jobs:
e2e-applitools:
test:
runs-on: ubuntu-latest
strategy:
matrix:
@@ -28,18 +28,25 @@ jobs:
- if: ${{ ! env.USE_APPLI }}
name: Warn if not using Applitools
run: |
echo "::error,title=Not using Applitools::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@v4
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
uses: actions/setup-node@v3
with:
cache: pnpm
node-version: ${{ matrix.node-version }}
- name: Install Packages
run: |
pnpm install --frozen-lockfile
env:
CYPRESS_CACHE_FOLDER: .cache/Cypress
- if: ${{ env.USE_APPLI }}
name: Notify applitools of new batch
# Copied from docs https://applitools.com/docs/topics/integrations/github-integration-ci-setup.html
@@ -47,22 +54,19 @@ jobs:
env:
# e.g. mermaid-js/mermaid/my-branch
APPLITOOLS_BRANCH: ${{ github.repository }}/${{ github.ref_name }}
APPLITOOLS_PARENT_BRANCH: ${{ github.event.inputs.parent_branch }}
APPLITOOLS_PARENT_BRANCH: ${{ github.inputs.parent_branch }}
APPLITOOLS_API_KEY: ${{ secrets.APPLITOOLS_API_KEY }}
APPLITOOLS_SERVER_URL: 'https://eyesapi.applitools.com'
- name: Cypress run
uses: cypress-io/github-action@v4
id: cypress
with:
start: pnpm run dev
wait-on: 'http://localhost:9000'
- name: Run E2E Tests
run: pnpm run e2e
env:
CYPRESS_CACHE_FOLDER: .cache/Cypress
# Mermaid applitools.config.js uses this to pick batch name.
APPLI_BRANCH: ${{ github.ref_name }}
APPLITOOLS_BATCH_ID: ${{ github.sha }}
# e.g. mermaid-js/mermaid/my-branch
APPLITOOLS_BRANCH: ${{ github.repository }}/${{ github.ref_name }}
APPLITOOLS_PARENT_BRANCH: ${{ github.event.inputs.parent_branch }}
APPLITOOLS_PARENT_BRANCH: ${{ github.inputs.parent_branch }}
APPLITOOLS_API_KEY: ${{ secrets.APPLITOOLS_API_KEY }}
APPLITOOLS_SERVER_URL: 'https://eyesapi.applitools.com'

View File

@@ -1,168 +1,46 @@
# We use github cache to save snapshots between runs.
# For PRs and MergeQueues, the target commit is used, and for push events, github.event.previous is used.
# If a snapshot for a given Hash is not found, we checkout that commit, run the tests and cache the snapshots.
# These are then downloaded before running the E2E, providing the reference snapshots.
# If there are any errors, the diff image is uploaded to artifacts, and the user is notified.
name: E2E
on:
push:
branches-ignore:
- 'gh-readonly-queue/**'
pull_request:
merge_group:
on: [push, pull_request]
permissions:
contents: read
env:
# For PRs and MergeQueues, the target commit is used, and for push events, github.event.previous is used.
targetHash: ${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha || github.event.before }}
jobs:
cache:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 18.x
- name: Cache snapshots
id: cache-snapshot
uses: actions/cache@v4
with:
save-always: true
path: ./cypress/snapshots
key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
# If a snapshot for a given Hash is not found, we checkout that commit, run the tests and cache the snapshots.
- name: Switch to base branch
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
uses: actions/checkout@v4
with:
ref: ${{ env.targetHash }}
- name: Cypress run
uses: cypress-io/github-action@v4
id: cypress-snapshot-gen
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
with:
start: pnpm run dev
wait-on: 'http://localhost:9000'
browser: chrome
e2e:
runs-on: ubuntu-latest
needs: cache
strategy:
fail-fast: false
matrix:
node-version: [18.x]
containers: [1, 2, 3, 4]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
uses: actions/setup-node@v3
# Need to skip setup if Cypress run is skipped, otherwise an error
# is thrown since the pnpm cache step fails
if: ${{ ( env.CYPRESS_RECORD_KEY != '' ) || ( matrix.containers == 1 ) }}
with:
cache: pnpm
node-version: ${{ matrix.node-version }}
# These cached snapshots are downloaded, providing the reference snapshots.
- name: Cache snapshots
id: cache-snapshot
uses: actions/cache/restore@v3
with:
path: ./cypress/snapshots
key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
# Install NPM dependencies, cache them correctly
# and run all Cypress tests
- name: Cypress run
uses: cypress-io/github-action@v4
id: cypress
# If CYPRESS_RECORD_KEY is set, run in parallel on all containers
# Otherwise (e.g. if running from fork), we run on a single container only
if: ${{ ( env.CYPRESS_RECORD_KEY != '' ) || ( matrix.containers == 1 ) }}
with:
start: pnpm run dev:coverage
start: pnpm run dev
wait-on: 'http://localhost:9000'
browser: chrome
# Disable recording if we don't have an API key
# e.g. if this action was run from a fork
record: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
parallel: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
env:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
VITEST_COVERAGE: true
CYPRESS_COMMIT: ${{ github.sha }}
- name: Upload Coverage to Codecov
uses: codecov/codecov-action@v3
# Run step only pushes to develop and pull_requests
if: ${{ steps.cypress.conclusion == 'success' && (github.event_name == 'pull_request' || github.ref == 'refs/heads/develop')}}
with:
files: coverage/cypress/lcov.info
flags: e2e
name: mermaid-codecov
fail_ci_if_error: false
verbose: true
token: 6845cc80-77ee-4e17-85a1-026cd95e0766
# We upload the artifacts into numbered archives to prevent overwriting
- name: Upload Artifacts
uses: actions/upload-artifact@v4
if: ${{ always() }}
with:
name: snapshots-${{ matrix.containers }}
retention-days: 1
path: ./cypress/snapshots
combineArtifacts:
needs: e2e
runs-on: ubuntu-latest
if: ${{ always() }}
steps:
# Download all snapshot artifacts and merge them into a single folder
- name: Download All Artifacts
uses: actions/download-artifact@v4
with:
path: snapshots
pattern: snapshots-*
merge-multiple: true
# For successful push events, we save the snapshots cache
- name: Save snapshots cache
id: cache-upload
if: ${{ github.event_name == 'push' && needs.e2e.result != 'failure' }}
uses: actions/cache/save@v3
with:
path: ./snapshots
key: ${{ runner.os }}-snapshots-${{ github.event.after }}
- name: Flatten images to a folder
if: ${{ needs.e2e.result == 'failure' }}
run: |
mkdir errors
cd snapshots
find . -mindepth 2 -type d -name "*__diff_output__*" -exec sh -c 'mv "$0"/*.png ../errors/' {} \;
- name: Upload Error snapshots
if: ${{ needs.e2e.result == 'failure' }}
uses: actions/upload-artifact@v4
id: upload-artifacts
with:
name: error-snapshots
retention-days: 10
path: errors/
- name: Notify Users
if: ${{ needs.e2e.result == 'failure' }}
run: |
echo "::error title=Visual tests failed::You can view images that failed by downloading the error-snapshots artifact: ${{ steps.upload-artifacts.outputs.artifact-url }}"

View File

@@ -14,19 +14,18 @@ on:
pull_request:
branches:
- master
workflow_dispatch:
schedule:
# * is a special character in YAML so you have to quote this string
- cron: '30 8 * * *'
jobs:
link-checker:
linkChecker:
runs-on: ubuntu-latest
permissions:
# lychee only uses the GITHUB_TOKEN to avoid rate-limiting
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- name: Restore lychee cache
uses: actions/cache@v3
@@ -36,13 +35,9 @@ jobs:
restore-keys: cache-lychee-
- name: Link Checker
uses: lycheeverse/lychee-action@v1.9.1
uses: lycheeverse/lychee-action@v1.5.4
with:
args: >-
--config .github/lychee.toml
packages/mermaid/src/docs/**/*.md
README.md
README.zh-CN.md
args: --verbose --no-progress --cache --max-cache-age 1d packages/mermaid/src/docs/**/*.md README.md README.zh-CN.md
fail: true
jobSummary: true
env:

View File

@@ -1,8 +1,7 @@
name: Lint
on:
push:
merge_group:
push: {}
pull_request:
types:
- opened
@@ -20,13 +19,13 @@ jobs:
matrix:
node-version: [18.x]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
uses: actions/setup-node@v3
with:
cache: pnpm
node-version: ${{ matrix.node-version }}
@@ -38,47 +37,7 @@ jobs:
CYPRESS_CACHE_FOLDER: .cache/Cypress
- name: Run Linting
shell: bash
run: |
if ! pnpm run lint; then
# print a nice error message on lint failure
ERROR_MESSAGE='Running `pnpm run lint` failed.'
ERROR_MESSAGE+=' Running `pnpm -w run lint:fix` may fix this issue. '
ERROR_MESSAGE+=" If this error doesn't occur on your local machine,"
ERROR_MESSAGE+=' make sure your packages are up-to-date by running `pnpm install`.'
ERROR_MESSAGE+=' You may also need to delete your prettier cache by running'
ERROR_MESSAGE+=' `rm ./node_modules/.cache/prettier/.prettier-cache`.'
echo "::error title=Lint failure::${ERROR_MESSAGE}"
# make sure to return an error exitcode so that GitHub actions shows a red-cross
exit 1
fi
- name: Verify `./src/config.type.ts` is in sync with `./src/schemas/config.schema.yaml`
shell: bash
run: |
if ! pnpm run --filter mermaid types:verify-config; then
ERROR_MESSAGE='Running `pnpm run --filter mermaid types:verify-config` failed.'
ERROR_MESSAGE+=' This should be fixed by running'
ERROR_MESSAGE+=' `pnpm run --filter mermaid types:build-config`'
ERROR_MESSAGE+=' on your local machine.'
echo "::error title=Lint failure::${ERROR_MESSAGE}"
# make sure to return an error exitcode so that GitHub actions shows a red-cross
exit 1
fi
- name: Verify no circular dependencies
working-directory: ./packages/mermaid
shell: bash
run: |
if ! pnpm run --filter mermaid checkCircle; then
ERROR_MESSAGE='Circular dependency detected.'
ERROR_MESSAGE+=' This should be fixed by removing the circular dependency.'
ERROR_MESSAGE+=' Run `pnpm run --filter mermaid checkCircle` on your local machine'
ERROR_MESSAGE+=' to see the circular dependency.'
echo "::error title=Lint failure::${ERROR_MESSAGE}"
# make sure to return an error exitcode so that GitHub actions shows a red-cross
exit 1
fi
run: pnpm run lint
- name: Verify Docs
id: verifyDocs

View File

@@ -0,0 +1,19 @@
name: Validate PR Labeler Configuration
on:
push: {}
pull_request:
types:
- opened
- synchronize
- ready_for_review
jobs:
pr-labeler:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Validate Configuration
uses: Yash-Singh1/pr-labeler-config-validator@releases/v0.0.3
with:
configuration-path: .github/pr-labeler.yml

View File

@@ -1,31 +1,13 @@
name: Apply labels to PR
on:
pull_request_target:
# required for pr-labeler to support PRs from forks
# ===================== ⛔ ☢️ 🚫 ⚠️ Warning ⚠️ 🚫 ☢️ ⛔ =======================
# Be very careful what you put in this GitHub Action workflow file to avoid
# malicious PRs from getting access to the Mermaid-js repo.
#
# Please read the following first before reviewing/merging:
# - https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target
# - https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
types: [opened, reopened, synchronize]
permissions:
contents: read
types: [opened]
jobs:
pr-labeler:
runs-on: ubuntu-latest
permissions:
contents: read # read permission is required to read config file
pull-requests: write # write permission is required to label PRs
steps:
- name: Label PR
uses: release-drafter/release-drafter@v5
with:
config-name: pr-labeler.yml
disable-autolabeler: false
disable-releaser: true
uses: TimonVS/pr-labeler-action@v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -6,6 +6,9 @@ on:
branches:
- master
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
@@ -19,16 +22,16 @@ concurrency:
jobs:
# Build job
build-docs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v3
with:
cache: pnpm
node-version: 18
@@ -37,7 +40,7 @@ jobs:
run: pnpm install --frozen-lockfile
- name: Setup Pages
uses: actions/configure-pages@v3
uses: actions/configure-pages@v2
- name: Run Build
run: pnpm --filter mermaid run docs:build:vitepress
@@ -48,12 +51,12 @@ jobs:
path: packages/mermaid/src/vitepress/.vitepress/dist
# Deployment job
deploy-docs:
deploy:
environment:
name: github-pages
runs-on: ubuntu-latest
needs: build-docs
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
uses: actions/deploy-pages@v1

View File

@@ -3,21 +3,13 @@ name: Draft Release
on:
push:
branches:
- master
permissions:
contents: read
- develop
jobs:
draft-release:
runs-on: ubuntu-latest
permissions:
contents: write # write permission is required to create a github release
pull-requests: read # required to read PR titles/labels
steps:
- name: Draft Release
uses: release-drafter/release-drafter@v5
with:
disable-autolabeler: true
uses: toolmantim/release-drafter@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

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

View File

@@ -8,24 +8,21 @@ jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: fregante/setup-git-user@v2
- uses: actions/checkout@v3
- uses: fregante/setup-git-user@v1
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js v18
uses: actions/setup-node@v4
- name: Setup Node.js
uses: actions/setup-node@v3
with:
cache: pnpm
node-version: 18.x
- name: Install Yarn
run: npm i yarn --global
- name: Install Json
run: npm i json --global
- name: Install Packages
run: |
pnpm install --frozen-lockfile
npm i json --global
env:
CYPRESS_CACHE_FOLDER: .cache/Cypress
run: yarn install --frozen-lockfile
- name: Prepare release
run: |
@@ -34,7 +31,7 @@ jobs:
git checkout -t origin/release/$VERSION
npm version --no-git-tag-version --allow-same-version $VERSION
git add package.json
git commit -nm "Bump version $VERSION"
git commit -m "Bump version $VERSION"
git checkout -t origin/master
git merge -m "Release $VERSION" --no-ff release/$VERSION
git push --no-verify

View File

@@ -1,24 +1,24 @@
name: Unit Tests
on: [push, pull_request, merge_group]
on: [push, pull_request]
permissions:
contents: read
jobs:
unit-test:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
uses: actions/setup-node@v3
with:
cache: pnpm
node-version: ${{ matrix.node-version }}
@@ -31,24 +31,13 @@ jobs:
- name: Run Unit Tests
run: |
pnpm test:coverage
pnpm run ci --coverage
- name: Run ganttDb tests using California timezone
env:
# Makes sure that gantt db works even in a timezone that has daylight savings
# since some days have 25 hours instead of 24.
TZ: America/Los_Angeles
run: |
pnpm exec vitest run ./packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts --coverage
- name: Upload Coverage to Codecov
uses: codecov/codecov-action@v3
# Run step only pushes to develop and pull_requests
if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/develop' }}
- name: Upload Coverage to Coveralls
# it feels a bit weird to use @master, but that's what the docs use
# (coveralls also doesn't publish a @v1 we can use)
# https://github.com/marketplace/actions/coveralls-github-action
uses: coverallsapp/github-action@master
with:
files: ./coverage/vitest/lcov.info
flags: unit
name: mermaid-codecov
fail_ci_if_error: false
verbose: true
token: 6845cc80-77ee-4e17-85a1-026cd95e0766
github-token: ${{ secrets.GITHUB_TOKEN }}
flag-name: unit

View File

@@ -5,21 +5,14 @@ on:
workflow_dispatch:
jobs:
update-browser-list:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
- run: npx update-browserslist-db@latest
- uses: actions/checkout@v3
- run: npx browserslist@latest --update-db
- name: Commit changes
uses: EndBug/add-and-commit@v9
with:
author_name: ${{ github.actor }}
author_email: ${{ github.actor }}@users.noreply.github.com
message: 'chore: update browsers list'
push: false
- name: Create Pull Request
uses: peter-evans/create-pull-request@v5
with:
branch: update-browserslist
title: Update Browserslist

11
.gitignore vendored
View File

@@ -3,10 +3,8 @@
node_modules/
coverage/
.idea/
.pnpm-store/
dist
v8-compile-cache-0
yarn-error.log
.npmrc
@@ -38,12 +36,3 @@ tsconfig.tsbuildinfo
knsv*.html
local*.html
stats/
**/user-avatars/*
**/contributor-names.json
.pnpm-store
.nyc_output
demos/dev/**
!/demos/dev/example.html
tsx-0/**

View File

@@ -1,11 +1,5 @@
export default {
'!(docs/**/*)*.{ts,js,html,md,mts}': [
'eslint --cache --cache-strategy content --fix',
// don't cache prettier yet, since we use `prettier-plugin-jsdoc`,
// and prettier doesn't invalidate cache on plugin updates"
// https://prettier.io/docs/en/cli.html#--cache
'prettier --write',
],
'cSpell.json': ['tsx scripts/fixCSpell.ts'],
'!(docs/**/*)*.{ts,js,json,html,md,mts}': ['eslint --fix', 'prettier --write'],
'cSpell.json': ['ts-node-esm scripts/fixCSpell.ts'],
'**/*.jison': ['pnpm -w run lint:jison'],
};

16
.lycheeignore Normal file
View File

@@ -0,0 +1,16 @@
# These links are ignored by our link checker https://github.com/lycheeverse/lychee
# The file allows you to list multiple regular expressions for exclusion (one pattern per line).
# Network error: Forbidden
https://codepen.io
# Network error: The certificate was not trusted
https://mkdocs.org/
https://osawards.com/javascript/#nominees
https://osawards.com/javascript/2019
# Timeout error, maybe Twitter has anti-bot defences against GitHub's CI servers?
https://twitter.com/mermaidjs_
# Don't check files that are generated during the build via `pnpm docs:code`
packages/mermaid/src/docs/config/setup/*

2
.npmrc
View File

@@ -1,3 +1,3 @@
registry=https://registry.npmjs.org
auto-install-peers=true
strict-peer-dependencies=false
use-inline-specifiers-lockfile-format=true

6
.percy.yml Normal file
View File

@@ -0,0 +1,6 @@
version: 2
snapshot:
widths:
- 1280
discovery:
disable-cache: true

View File

@@ -4,12 +4,4 @@ cypress/platform/xss3.html
coverage
# Autogenerated by PNPM
pnpm-lock.yaml
stats
**/.vitepress/components.d.ts
**/.vitepress/cache
.nyc_output
# Autogenerated by `pnpm run --filter mermaid types:build-config`
packages/mermaid/src/config.type.ts
# Ignore the files creates in /demos/dev except for example.html
demos/dev/**
!/demos/dev/example.html
stats

15
.tern-project Normal file
View File

@@ -0,0 +1,15 @@
{
"ecmaVersion": 6,
"libs": ["browser"],
"loadEagerly": [],
"dontLoad": ["node_modules/**"],
"plugins": {
"modules": {},
"es_modules": {},
"node": {},
"doc_comment": {
"fullDocs": true,
"strong": true
}
}
}

View File

@@ -2,19 +2,14 @@ import { build, InlineConfig, type PluginOption } from 'vite';
import { resolve } from 'path';
import { fileURLToPath } from 'url';
import jisonPlugin from './jisonPlugin.js';
import jsonSchemaPlugin from './jsonSchemaPlugin.js';
import { readFileSync } from 'fs';
import typescript from '@rollup/plugin-typescript';
import { visualizer } from 'rollup-plugin-visualizer';
import type { TemplateType } from 'rollup-plugin-visualizer/dist/plugin/template-types.js';
import istanbul from 'vite-plugin-istanbul';
const visualize = process.argv.includes('--visualize');
const watch = process.argv.includes('--watch');
const mermaidOnly = process.argv.includes('--mermaid');
const coverage = process.env.VITE_COVERAGE === 'true';
const __dirname = fileURLToPath(new URL('.', import.meta.url));
const sourcemap = false;
type OutputOptions = Exclude<
Exclude<InlineConfig['build'], undefined>['rollupOptions'],
@@ -25,14 +20,13 @@ const visualizerOptions = (packageName: string, core = false): PluginOption[] =>
if (packageName !== 'mermaid' || !visualize) {
return [];
}
return ['network', 'treemap', 'sunburst'].map(
(chartType) =>
visualizer({
filename: `./stats/${chartType}${core ? '.core' : ''}.html`,
template: chartType as TemplateType,
gzipSize: true,
brotliSize: true,
}) as PluginOption
return ['network', 'treemap', 'sunburst'].map((chartType) =>
visualizer({
filename: `./stats/${chartType}${core ? '.core' : ''}.html`,
template: chartType as TemplateType,
gzipSize: true,
brotliSize: true,
})
);
};
@@ -42,16 +36,21 @@ const packageOptions = {
packageName: 'mermaid',
file: 'mermaid.ts',
},
'mermaid-example-diagram': {
name: 'mermaid-example-diagram',
packageName: 'mermaid-example-diagram',
'mermaid-mindmap': {
name: 'mermaid-mindmap',
packageName: 'mermaid-mindmap',
file: 'detector.ts',
},
'mermaid-zenuml': {
name: 'mermaid-zenuml',
packageName: 'mermaid-zenuml',
'mermaid-flowchart-v3': {
name: 'mermaid-flowchart-v3',
packageName: 'mermaid-flowchart-v3',
file: 'detector.ts',
},
// 'mermaid-example-diagram-detector': {
// name: 'mermaid-example-diagram-detector',
// packageName: 'mermaid-example-diagram',
// file: 'detector.ts',
// },
};
interface BuildOptions {
@@ -69,13 +68,13 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
{
name,
format: 'esm',
sourcemap,
sourcemap: true,
entryFileNames: `${name}.esm${minify ? '.min' : ''}.mjs`,
},
{
name,
format: 'umd',
sourcemap,
sourcemap: true,
entryFileNames: `${name}${minify ? '.min' : ''}.js`,
},
];
@@ -94,7 +93,7 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
{
name,
format: 'esm',
sourcemap,
sourcemap: true,
entryFileNames: `${name}.core.mjs`,
},
];
@@ -117,30 +116,20 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
output,
},
},
define: {
'import.meta.vitest': 'undefined',
},
resolve: {
extensions: [],
extensions: ['.jison', '.js', '.ts', '.json'],
},
plugins: [
jisonPlugin(),
jsonSchemaPlugin(), // handles `.schema.yaml` files
// @ts-expect-error According to the type definitions, rollup plugins are incompatible with vite
typescript({ compilerOptions: { declaration: false } }),
istanbul({
exclude: ['node_modules', 'test/', '__mocks__'],
extension: ['.js', '.ts'],
requireEnv: true,
forceBuildInstrument: coverage,
}),
...visualizerOptions(packageName, core),
],
plugins: [jisonPlugin(), ...visualizerOptions(packageName, core)],
};
if (watch && config.build) {
config.build.watch = {
include: ['packages/mermaid-example-diagram/src/**', 'packages/mermaid/src/**'],
include: [
'packages/mermaid-flowchart-v3/src/**',
'packages/mermaid-mindmap/src/**',
'packages/mermaid/src/**',
// 'packages/mermaid-example-diagram/src/**',
],
};
}
@@ -148,9 +137,11 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
};
const buildPackage = async (entryName: keyof typeof packageOptions) => {
await build(getBuildConfig({ minify: false, entryName }));
await build(getBuildConfig({ minify: 'esbuild', entryName }));
await build(getBuildConfig({ minify: false, core: true, entryName }));
return Promise.allSettled([
build(getBuildConfig({ minify: false, entryName })),
build(getBuildConfig({ minify: 'esbuild', entryName })),
build(getBuildConfig({ minify: false, core: true, entryName })),
]);
};
const main = async () => {
@@ -163,8 +154,9 @@ const main = async () => {
if (watch) {
build(getBuildConfig({ minify: false, watch, core: false, entryName: 'mermaid' }));
if (!mermaidOnly) {
build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-example-diagram' }));
build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-zenuml' }));
build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-flowchart-v3' }));
build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-mindmap' }));
// build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-example-diagram' }));
}
} else if (visualize) {
await build(getBuildConfig({ minify: false, core: true, entryName: 'mermaid' }));

View File

@@ -1,6 +1,8 @@
// @ts-ignore No typings for jison
import jison from 'jison';
export const transformJison = (src: string): string => {
// @ts-ignore No typings for jison
const parser = new jison.Generator(src, {
moduleType: 'js',
'token-stack': true,

View File

@@ -1,151 +0,0 @@
import { load, JSON_SCHEMA } from 'js-yaml';
import assert from 'node:assert';
import Ajv2019, { type JSONSchemaType } from 'ajv/dist/2019.js';
import { PluginOption } from 'vite';
import type { MermaidConfig, BaseDiagramConfig } from '../packages/mermaid/src/config.type.js';
/**
* All of the keys in the mermaid config that have a mermaid diagram config.
*/
const MERMAID_CONFIG_DIAGRAM_KEYS = [
'flowchart',
'sequence',
'gantt',
'journey',
'class',
'state',
'er',
'pie',
'quadrantChart',
'xyChart',
'requirement',
'mindmap',
'timeline',
'gitGraph',
'c4',
'sankey',
] as const;
/**
* Generate default values from the JSON Schema.
*
* AJV does not support nested default values yet (or default values with $ref),
* so we need to manually find them (this may be fixed in ajv v9).
*
* @param mermaidConfigSchema - The Mermaid JSON Schema to use.
* @returns The default mermaid config object.
*/
function generateDefaults(mermaidConfigSchema: JSONSchemaType<MermaidConfig>) {
const ajv = new Ajv2019({
useDefaults: true,
allowUnionTypes: true,
strict: true,
});
ajv.addKeyword({
keyword: 'meta:enum', // used by jsonschema2md
errors: false,
});
ajv.addKeyword({
keyword: 'tsType', // used by json-schema-to-typescript
errors: false,
});
// ajv currently doesn't support nested default values, see https://github.com/ajv-validator/ajv/issues/1718
// (may be fixed in v9) so we need to manually use sub-schemas
const mermaidDefaultConfig = {};
assert.ok(mermaidConfigSchema.$defs);
const baseDiagramConfig = mermaidConfigSchema.$defs.BaseDiagramConfig;
for (const key of MERMAID_CONFIG_DIAGRAM_KEYS) {
const subSchemaRef = mermaidConfigSchema.properties[key].$ref;
const [root, defs, defName] = subSchemaRef.split('/');
assert.strictEqual(root, '#');
assert.strictEqual(defs, '$defs');
const subSchema = {
$schema: mermaidConfigSchema.$schema,
$defs: mermaidConfigSchema.$defs,
...mermaidConfigSchema.$defs[defName],
} as JSONSchemaType<BaseDiagramConfig>;
const validate = ajv.compile(subSchema);
mermaidDefaultConfig[key] = {};
for (const required of subSchema.required ?? []) {
if (subSchema.properties[required] === undefined && baseDiagramConfig.properties[required]) {
mermaidDefaultConfig[key][required] = baseDiagramConfig.properties[required].default;
}
}
if (!validate(mermaidDefaultConfig[key])) {
throw new Error(
`schema for subconfig ${key} does not have valid defaults! Errors were ${JSON.stringify(
validate.errors,
undefined,
2
)}`
);
}
}
const validate = ajv.compile(mermaidConfigSchema);
if (!validate(mermaidDefaultConfig)) {
throw new Error(
`Mermaid config JSON Schema does not have valid defaults! Errors were ${JSON.stringify(
validate.errors,
undefined,
2
)}`
);
}
return mermaidDefaultConfig;
}
/**
* Vite plugin that handles JSON Schemas saved as a `.schema.yaml` file.
*
* Use `my-example.schema.yaml?only-defaults=true` to only load the default values.
*/
export default function jsonSchemaPlugin(): PluginOption {
return {
name: 'json-schema-plugin',
transform(src: string, id: string) {
const idAsUrl = new URL(id, 'file:///');
if (!idAsUrl.pathname.endsWith('schema.yaml')) {
return;
}
if (idAsUrl.searchParams.get('only-defaults')) {
const jsonSchema = load(src, {
filename: idAsUrl.pathname,
// only allow JSON types in our YAML doc (will probably be default in YAML 1.3)
// e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`.
schema: JSON_SCHEMA,
}) as JSONSchemaType<MermaidConfig>;
return {
code: `export default ${JSON.stringify(generateDefaults(jsonSchema), undefined, 2)};`,
map: null, // no source map
};
} else {
return {
code: `export default ${JSON.stringify(
load(src, {
filename: idAsUrl.pathname,
// only allow JSON types in our YAML doc (will probably be default in YAML 1.3)
// e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`.
schema: JSON_SCHEMA,
}),
undefined,
2
)};`,
map: null, // provide source map if available
};
}
},
};
}

View File

@@ -1,6 +1,14 @@
import express from 'express';
import cors from 'cors';
import express, { NextFunction, Request, Response } from 'express';
import { createServer as createViteServer } from 'vite';
// import { getBuildConfig } from './build';
const cors = (req: Request, res: Response, next: NextFunction) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
};
async function createServer() {
const app = express();
@@ -8,15 +16,14 @@ async function createServer() {
// Create Vite server in middleware mode
const vite = await createViteServer({
configFile: './vite.config.ts',
mode: 'production',
server: { middlewareMode: true },
appType: 'custom', // don't include Vite's default HTML handling middleware
appType: 'custom', // don't include Vite's default HTML handling middlewares
});
app.use(cors());
app.use(cors);
app.use(express.static('./packages/mermaid/dist'));
app.use(express.static('./packages/mermaid-zenuml/dist'));
app.use(express.static('./packages/mermaid-example-diagram/dist'));
app.use(express.static('./packages/mermaid-mindmap/dist'));
app.use(vite.middlewares);
app.use(express.static('demos'));
app.use(express.static('cypress/platform'));
@@ -26,4 +33,5 @@ async function createServer() {
});
}
// build(getBuildConfig({ minify: false, watch: true }));
createServer();

5
.vscode/launch.json vendored
View File

@@ -17,9 +17,8 @@
"name": "Docs generation",
"type": "node",
"request": "launch",
"args": ["scripts/docs.cli.mts"],
// we'll need to change this to --import in Node.JS v20.6.0 and up
"runtimeArgs": ["--loader", "tsx/esm"],
"args": ["src/docs.mts"],
"runtimeArgs": ["--loader", "ts-node/esm"],
"cwd": "${workspaceRoot}/packages/mermaid",
"skipFiles": ["<node_internals>/**", "**/node_modules/**"],
"smartStep": true,

View File

@@ -1,105 +1,6 @@
# Changelog
# Change Log
## [10.0.0](https://github.com/mermaid-js/mermaid/releases/tag/v10.0.0)
### Mermaid is ESM only!
We've dropped CJS support. So, you will have to update your import scripts as follows.
```html
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
```
You can keep using v9 by adding the `@9` in the CDN URL.
```diff
- <script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.js"></script>
+ <script src="https://cdn.jsdelivr.net/npm/mermaid@9/dist/mermaid.js"></script>
```
### mermaid.render is async and doesn't accept callbacks
```js
// < v10
mermaid.render('id', 'graph TD;\nA-->B', (svg, bindFunctions) => {
element.innerHTML = svg;
if (bindFunctions) {
bindFunctions(element);
}
});
// Shorter syntax
if (bindFunctions) {
bindFunctions(element);
}
// can be replaced with the `?.` shorthand
bindFunctions?.(element);
// >= v10 with async/await
const { svg, bindFunctions } = await mermaid.render('id', 'graph TD;\nA-->B');
element.innerHTML = svg;
bindFunctions?.(element);
// >= v10 with promise.then
mermaid.render('id', 'graph TD;A-->B').then(({ svg, bindFunctions }) => {
element.innerHTML = svg;
bindFunctions?.(element);
});
```
### mermaid.parse is async and ParseError is removed
```js
// < v10
mermaid.parse(text, parseError);
//>= v10
await mermaid.parse(text).catch(parseError);
// or
try {
await mermaid.parse(text);
} catch (err) {
parseError(err);
}
```
### Init deprecated and InitThrowsErrors removed
The config passed to `init` was not being used earlier.
It will now be used.
The `init` function is deprecated and will be removed in the next major release.
init currently works as a wrapper to `initialize` and `run`.
```js
// < v10
mermaid.init(config, selector, cb);
//>= v10
mermaid.initialize(config);
mermaid.run({
querySelector: selector,
postRenderCallback: cb,
suppressErrors: true,
});
```
```js
// < v10
mermaid.initThrowsErrors(config, selector, cb);
//>= v10
mermaid.initialize(config);
mermaid.run({
querySelector: selector,
postRenderCallback: cb,
suppressErrors: false,
});
```
// TODO: Populate changelog pre v10
// TODO: Populate changelog
- Config has a lot of changes
- globalReset resets to `defaultConfig` instead of current config. Use `reset` instead.
@@ -195,7 +96,7 @@ mermaid.run({
- "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)
- How to pass styling [\#639](https://github.com/knsv/mermaid/issues/639)
- The live editor can't show seq diagram with notes for 8.0.0-alpha.3 [\#638](https://github.com/knsv/mermaid/issues/638)
- The live editor cant 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)
- 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)
@@ -504,7 +405,7 @@ mermaid.run({
- 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)
- How to link backwards in flowchat? [\#321](https://github.com/knsv/mermaid/issues/321)
- How to link backwords in flowchat? [\#321](https://github.com/knsv/mermaid/issues/321)
- Help with editor [\#310](https://github.com/knsv/mermaid/issues/310)
- +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)
@@ -619,7 +520,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)
- 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)
- Add a reversed asymmetric shape [\#124](https://github.com/knsv/mermaid/issues/124)
- Add a reversed assymetric shape [\#124](https://github.com/knsv/mermaid/issues/124)
- 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)
@@ -659,7 +560,7 @@ mermaid.run({
- 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)
- Autoscaling for all diagram types [\#175](https://github.com/knsv/mermaid/issues/175)
- Problem with click event callback [\#174](https://github.com/knsv/mermaid/issues/174)
- Problem wit click event callback [\#174](https://github.com/knsv/mermaid/issues/174)
- How to escape characters? [\#170](https://github.com/knsv/mermaid/issues/170)
- it can not work [\#167](https://github.com/knsv/mermaid/issues/167)
- UML Class diagram [\#154](https://github.com/knsv/mermaid/issues/154)
@@ -762,7 +663,7 @@ mermaid.run({
- 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)
- Internet Explorer Support [\#99](https://github.com/knsv/mermaid/issues/99)
- Asymmetric shapes not documented [\#82](https://github.com/knsv/mermaid/issues/82)
- Assymetric shapes not documented [\#82](https://github.com/knsv/mermaid/issues/82)
- NoModificationAllowedError [\#23](https://github.com/knsv/mermaid/issues/23)
- Improve arrows [\#3](https://github.com/knsv/mermaid/issues/3)
@@ -908,7 +809,7 @@ mermaid.run({
- 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)
- Provide parse function in browser without `require`? [\#21](https://github.com/knsv/mermaid/issues/21)
- Provide parse function in browser widthout `require`? [\#21](https://github.com/knsv/mermaid/issues/21)
- 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)

View File

@@ -1,16 +0,0 @@
cff-version: 1.2.0
title: 'Mermaid: Generate diagrams from markdown-like text'
message: >-
If you use this software, please cite it using the metadata from this file.
type: software
authors:
- family-names: Sveidqvist
given-names: Knut
- name: 'Contributors to Mermaid'
repository-code: 'https://github.com/mermaid-js/mermaid'
date-released: 2014-12-02
url: 'https://mermaid.js.org/'
abstract: >-
JavaScript based diagramming and charting tool that renders Markdown-inspired
text definitions to create and modify diagrams dynamically.
license: MIT

View File

@@ -59,8 +59,8 @@ representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at <security@mermaid.live>.
reported to the community leaders responsible for enforcement at security@mermaid.live
.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the

View File

@@ -1 +0,0 @@
./packages/mermaid/src/docs/community/contributing.md

156
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,156 @@
# Contributing
So you want to help? That's great!
![Happy people jumping with excitement](https://media.giphy.com/media/BlVnrxJgTGsUw/giphy.gif)
Here are a few things to know to get you started on the right path.
Below link will help you making a copy of the repository in your local system.
https://docs.github.com/en/get-started/quickstart/fork-a-repo
## Requirements
- [volta](https://volta.sh/) to manage node versions.
- [Node.js](https://nodejs.org/en/). `volta install node`
- [pnpm](https://pnpm.io/) package manager. `volta install pnpm`
## Development Installation
```bash
git clone git@github.com:mermaid-js/mermaid.git
cd mermaid
# npx is required for first install as volta support for pnpm is not added yet.
npx pnpm install
pnpm test
```
## Committing code
We make all changes via pull requests. As we have many pull requests from developers new to mermaid, the current approach is to have _knsv, Knut Sveidqvist_ as a main reviewer of changes and merging pull requests. More precisely like this:
- Large changes reviewed by knsv or other developer asked to review by knsv
- Smaller low-risk changes like dependencies, documentation, etc. can be merged by active collaborators
- Documentation (updates to the `package/mermaid/src/docs` folder is also allowed via direct commits)
To commit code, create a branch, let it start with the type like feature or bug followed by the issue number for reference and some describing text.
One example:
`feature/945_state_diagrams`
Another:
`bug/123_nasty_bug_branch`
## Committing documentation
Less strict here, it is OK to commit directly in the `develop` branch if you are a collaborator.
The documentation is written in **Markdown**. For more information about Markdown [see the GitHub Markdown help page](https://help.github.com/en/github/writing-on-github/basic-writing-and-formatting-syntax).
### Documentation source files are in [`/packages/mermaid/src/docs`](packages/mermaid/src/docs)
The source files for the project documentation are located in the [`/packages/mermaid/src/docs`](packages/mermaid/src/docs) directory. This is where you should make changes.
The files under `/packages/mermaid/src/docs` are processed to generate the published documentation, and the resulting files are put into the `/docs` directory.
```mermaid
flowchart LR
classDef default fill:#fff,color:black,stroke:black
source["files in /packages/mermaid/src/docs\n(changes should be done here)"] -- automatic processing\nto generate the final documentation--> published["files in /docs\ndisplayed on the official documentation site"]
```
**_DO NOT CHANGE FILES IN `/docs`_**
### The official documentation site
**[The mermaid documentation site](https://mermaid-js.github.io/mermaid/) is powered by [Vitepress](https://vitepress.vuejs.org/), a simple documentation site generator.**
If you want to preview the whole documentation site on your machine:
```sh
cd packages/mermaid
pnpm i
pnpm docs:dev
```
You can now build and serve the documentation site:
```sh
pnpm docs:serve
```
## Branching
Going forward we will use a git flow inspired approach to branching. So development is done in develop, to do the development in the develop.
Once development is done we branch a release branch from develop for testing.
Once the release happens we merge the release branch to master and kill the release branch.
This means... **branch off your pull request from develop**
## Content of a pull request
A new feature has been born. Great! But without the steps below it might just ... fade away ...
### **Add unit tests for the parsing part**
This is important so that, if someone else does a change to the grammar that does not know about this great feature, gets notified early on when that change breaks the parser. Another important aspect is that without proper parsing tests refactoring is pretty much impossible.
### **Add e2e tests**
This tests the rendering and visual appearance of the diagram. This ensures that the rendering of that feature in the e2e will be reviewed in the release process going forward. Less chance that it breaks!
To start working with the e2e tests, run `pnpm run dev` to start the dev server, after that start cypress by running `pnpm exec cypress open` in the mermaid folder.
The rendering tests are very straightforward to create. There is a function imgSnapshotTest. This function takes a diagram in text form, the mermaid options and renders that diagram in cypress.
When running in ci it will take a snapshot of the rendered diagram and compare it with the snapshot from last build and flag for review it if it differs.
This is what a rendering test looks like:
```javascript
it('should render forks and joins', () => {
imgSnapshotTest(
`
stateDiagram
state fork_state &lt;&lt;fork&gt;&gt;
[*] --> fork_state
fork_state --> State2
fork_state --> State3
state join_state &lt;&lt;join&gt;&gt;
State2 --> join_state
State3 --> join_state
join_state --> State4
State4 --> [*]
`,
{ logLevel: 0 }
);
cy.get('svg');
});
```
### **Add documentation for it**
Finally, if it is not in the documentation, no one will know about it and then **no one will use it**. Wouldn't that be sad? With all the effort that was put into the feature?
The source files for documentation are in `/packages/mermaid/src/docs` and are written in markdown. Just pick the right section and start typing. See the [Committing Documentation](#committing-documentation) section for more about how the documentation is generated.
#### Adding to or changing the documentation organization
If you want to add a new section or change the organization (structure), then you need to make sure to **change the side navigation** in `mermaid/src/docs/.vitepress/config.js`.
When changes are committed and then released, they become part of the `master` branch and become part of the published documentation on https://mermaid-js.github.io/mermaid/
## Last words
Don't get daunted if it is hard in the beginning. We have a great community with only encouraging words. So if you get stuck, ask for help and hints in the slack forum. If you want to show off something good, show it off there.
[Join our slack community if you want closer contact!](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE)
![A superhero wishing you good luck](https://media.giphy.com/media/l49JHz7kJvl6MCj3G/giphy.gif)

View File

@@ -1,2 +0,0 @@
FROM node:18.19.0-alpine3.18 AS base
RUN wget -qO- https://get.pnpm.io/install.sh | ENV="$HOME/.shrc" SHELL="$(which sh)" sh -

110
README.md
View File

@@ -1,40 +1,8 @@
<p align="center">
<img src="https://raw.githubusercontent.com/mermaid-js/mermaid/develop/docs/public/favicon.svg" height="150">
</p>
<h1 align="center">
Mermaid
</h1>
<p align="center">
Generate diagrams from markdown-like text.
<p>
<p align="center">
<a href="https://www.npmjs.com/package/mermaid"><img src="https://img.shields.io/npm/v/mermaid?color=ff3670&label="></a>
<p>
# mermaid
<p align="center">
<a href="https://mermaid.live/"><b>Live Editor!</b></a>
</p>
<p align="center">
<a href="https://mermaid.js.org">📖 Documentation</a> | <a href="https://mermaid.js.org/intro/">🚀 Getting Started</a> | <a href="https://www.jsdelivr.com/package/npm/mermaid">🌐 CDN</a> | <a href="https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE" title="Slack invite">🙌 Join Us</a>
</p>
<p align="center">
<a href="./README.zh-CN.md">简体中文</a>
</p>
<p align="center">
Try Live Editor previews of future releases: <a href="https://develop.git.mermaid.live/" title="Try the mermaid version from the develop branch.">Develop</a> | <a href="https://next.git.mermaid.live/" title="Try the mermaid version from the next branch.">Next</a>
</p>
[![Build CI Status](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml/badge.svg)](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml) [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![npm minified gzipped bundle size](https://img.shields.io/bundlephobia/minzip/mermaid)](https://bundlephobia.com/package/mermaid) [![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid) [![NPM](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) [![Twitter Follow](https://img.shields.io/twitter/follow/mermaidjs_?style=social)](https://twitter.com/mermaidjs_)
<br>
<br>
[![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid)
[![Build CI Status](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml/badge.svg)](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml)
[![npm minified gzipped bundle size](https://img.shields.io/bundlephobia/minzip/mermaid)](https://bundlephobia.com/package/mermaid)
[![Coverage Status](https://codecov.io/github/mermaid-js/mermaid/branch/develop/graph/badge.svg)](https://app.codecov.io/github/mermaid-js/mermaid/tree/develop)
[![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid)
[![NPM Downloads](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid)
[![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE)
[![Twitter Follow](https://img.shields.io/badge/Social-mermaidjs__-blue?style=social&logo=X)](https://twitter.com/mermaidjs_)
English | [简体中文](./README.zh-CN.md)
<img src="./img/header.png" alt="" />
@@ -44,22 +12,6 @@ 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>
## 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
<!-- <Main description> -->
@@ -74,12 +26,14 @@ Mermaid addresses this problem by enabling users to create easily modifiable dia
<br/>
Mermaid allows even non-programmers to easily create detailed diagrams through the [Mermaid Live Editor](https://mermaid.live/).<br/>
For video tutorials, visit our [Tutorials](./docs/ecosystem/tutorials.md) page.
Use Mermaid with your favorite applications, check out the list of [Integrations and Usages of Mermaid](./docs/ecosystem/integrations-community.md).
[Tutorials](./docs/config/Tutorials.md) has video tutorials.
Use Mermaid with your favorite applications, check out the list of [Integrations and Usages of Mermaid](./docs/misc/integrations.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/misc/integrations.md).
For a more detailed introduction to Mermaid and some of its more basic uses, look to the [Beginner's Guide](./docs/intro/getting-started.md), [Usage](./docs/config/usage.md) and [Tutorials](./docs/ecosystem/tutorials.md).
For a more detailed introduction to Mermaid and some of its more basic uses, look to the [Beginner's Guide](./docs/community/n00b-overview.md), [Usage](./docs/config/usage.md) and [Tutorials](./docs/config/Tutorials.md).
🌐 [CDN](https://unpkg.com/mermaid/) | 📖 [Documentation](https://mermaidjs.github.io) | 🙌 [Contribution](https://github.com/mermaid-js/mermaid/blob/develop/CONTRIBUTING.md) | 📜 [Changelog](./docs/CHANGELOG.md)
In our release process we rely heavily on visual regression tests using [applitools](https://applitools.com/). Applitools is a great service which has been easy to use and integrate with our tests.
@@ -184,7 +138,6 @@ class Class10 {
int id
size()
}
```
```mermaid
@@ -204,7 +157,6 @@ class Class10 {
int id
size()
}
```
### State diagram [<a href="https://mermaid-js.github.io/mermaid/#/stateDiagram">docs</a> - <a href="https://mermaid.live/edit#pako:eNpdkEFvgzAMhf8K8nEqpYSNthx22Xbcqcexg0sCiZQQlDhIFeK_L8A6TfXp6fOz9ewJGssFVOAJSbwr7ByadGR1n8T6evpO0vQ1uZDSekOrXGFsPqJPO6q-2-imH8f_0TeHXm50lfelsAMjnEHFY6xpMdRAUhhRQxUlFy0GTTXU_RytYeAx-AdXZB1ULWovdoCB7OXWN1CRC-Ju-r3uz6UtchGHJqDbsPygU57iysb2reoWHpyOWBINvsqypb3vFMlw3TfWZF5xiY7keC6zkpUnZIUojwW-FAVvrvn51LLnvOXHQ84Q5nn-AVtLcwk">live editor</a>]
@@ -247,44 +199,6 @@ pie
### Git graph [experimental - <a href="https://mermaid.live/edit#pako:eNqNkMFugzAMhl8F-VyVAR1tOW_aA-zKxSSGRCMJCk6lCvHuNZPKZdM0n-zf3_8r8QIqaIIGMqnB8kfEybQ--y4VnLP8-9RF9Mpkmm40hmlnDKmvkPiH_kfS7nFo_VN0FAf6XwocQGgxa_nGsm1bYEOOWmik1dRjGrmF1q-Cpkkj07u2HCI0PY4zHQATh8-7V9BwTPSE3iwOEd1OjQE1iWkBvk_bzQY7s0Sq4Hs7bHqKo8iGeZqbPN_WR7mpSd1RHpvPVhuMbG7XOq_L-oJlRfW5wteq0qorrpe-PBW9Pr8UJcK6rg-BLYPQ">live editor</a>]
### Bar chart (using gantt chart) [<a href="https://mermaid-js.github.io/mermaid/#/gantt">docs</a> - <a href="https://mermaid.live/edit#pako:eNptkU1vhCAQhv8KIenNugiI4rkf6bmXpvEyFVxJFDYyNt1u9r8X63Z7WQ9m5pknLzieaBeMpQ3dg0dsPUkPOhwteXZIXmJcbCT3xMAxkuh8Z8kIEclyMIB209fqKcwTICFvG4IvFy_oLrZ-g9F26ILfQgvNFN94VaRXQ1iWqpumZBcu1J8p1E1TXDx59eQNr5LyEqjJn6hv5QnGNlxevZJmdLLpy5xJSzut45biYCfb0iaVxvawjNjS1p-TCguG16PvaIPzYjO67e3BwX6GiTY9jPFKH43DMF_hGMDY1J4oHg-_f8hFTJFd8L3br3yZx4QHxENsdrt1nO8dDstH3oVpF50ZYMbhU6ud4qoGLqyqBJRCmO6j0HXPZdGbihUc6Pmc0QP49xD-b5X69ZQv2gjO81IwzWqhC1lKrjJ6pA3nVS7SMiVjrKirWlYp5fs3osgrWeo00lorLWvOzz8JVbXm">live editor</a>]
```
gantt
title Git Issues - days since last update
dateFormat X
axisFormat %s
section Issue19062
71 : 0, 71
section Issue19401
36 : 0, 36
section Issue193
34 : 0, 34
section Issue7441
9 : 0, 9
section Issue1300
5 : 0, 5
```
```mermaid
gantt
title Git Issues - days since last update
dateFormat X
axisFormat %s
section Issue19062
71 : 0, 71
section Issue19401
36 : 0, 36
section Issue193
34 : 0, 34
section Issue7441
9 : 0, 9
section Issue1300
5 : 0, 5
```
### User Journey diagram [<a href="https://mermaid-js.github.io/mermaid/#/user-journey">docs</a> - <a href="https://mermaid.live/edit#pako:eNplkMFuwjAQRH9l5TMiTVIC-FqqnjhxzWWJN4khsSN7XRSh_HsdKBVt97R6Mzsj-yoqq0hIAXCywRkaSwNxWHNHsB_hYt1ZmwYUfiueKtbWwIcFtjf5zgH2eCZgQgkrCXt64GgMg2fUzkvIn5Xd_V5COtMFvCH_62ht_5yk7MU8sn61HDTfxD8VYiF6cj1qFd94nWkpuKWYKWRcFdUYOi5FaaZoDYNCpnel2Toha-w8LQQGtofRVEKyC_Qw7TQ2DvsfV2dRUTy6Ch6H-UMb7TlGVtbUupl5cF3ELfPgZZLM8rLR3IbjsrJ94rVq0XH7uS2SIis2mOVUrHNc5bmqjul2U2evaa3WL2mGYpqmL2BGiho">live editor</a>]
```
@@ -393,7 +307,7 @@ Update version number in `package.json`.
npm publish
```
The above command generates files into the `dist` folder and publishes them to <https://www.npmjs.com>.
The above command generates files into the `dist` folder and publishes them to npmjs.org.
## Related projects
@@ -409,7 +323,7 @@ Detailed information about how to contribute can be found in the [contribution g
## Security and safe diagrams
For public sites, it can be precarious to retrieve text from users on the internet, storing that content for presentation in a browser at a later stage. The reason is that the user content can contain embedded malicious scripts that will run when the data is presented. For Mermaid this is a risk, specially as mermaid diagrams contain many characters that are used in html which makes the standard sanitation unusable as it also breaks the diagrams. We still make an effort to sanitize the incoming code and keep refining the process but it is hard to guarantee that there are no loop holes.
For public sites, it can be precarious to retrieve text from users on the internet, storing that content for presentation in a browser at a later stage. The reason is that the user content can contain embedded malicious scripts that will run when the data is presented. For Mermaid this is a risk, specially as mermaid diagrams contain many characters that are used in html which makes the standard sanitation unusable as it also breaks the diagrams. We still make an effort to sanitise the incoming code and keep refining the process but it is hard to guarantee that there are no loop holes.
As an extra level of security for sites with external users we are happy to introduce a new security level in which the diagram is rendered in a sandboxed iframe preventing javascript in the code from being executed. This is a great step forward for better security.
@@ -417,7 +331,7 @@ _Unfortunately you can not have a cake and eat it at the same time which in this
## Reporting vulnerabilities
To report a vulnerability, please e-mail <security@mermaid.live> with a description of the issue, the steps you took to create the issue, affected versions, and if known, mitigations for the issue.
To report a vulnerability, please e-mail security@mermaid.live with a description of the issue, the steps you took to create the issue, affected versions, and if known, mitigations for the issue.
## Appreciation

View File

@@ -1,41 +1,8 @@
<p align="center">
<img src="https://raw.githubusercontent.com/mermaid-js/mermaid/develop/docs/public/favicon.svg" height="150">
</p>
<h1 align="center">
Mermaid
</h1>
<p align="center">
通过解析类 Markdown 的文本语法来实现图表的创建和动态修改。
<p>
<p align="center">
<a href="https://www.npmjs.com/package/mermaid"><img src="https://img.shields.io/npm/v/mermaid?color=ff3670&label="></a>
<p>
# mermaid
<p align="center">
<a href="https://mermaid.live/"><b>实时编辑器!</b></a>
</p>
<p align="center">
<a href="https://mermaid.js.org">📖 文档</a> | <a href="https://mermaid.js.org/intro/">🚀 入门</a> | <a href="https://www.jsdelivr.com/package/npm/mermaid">🌐 CDN</a> | <a href="https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE" title="Slack invite">🙌 加入我们</a>
</p>
<p align="center">
<a href="./README.md">English</a>
</p>
[![Build CI Status](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml/badge.svg)](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml) [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![npm minified gzipped bundle size](https://img.shields.io/bundlephobia/minzip/mermaid)](https://bundlephobia.com/package/mermaid) [![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid) [![NPM](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) [![Twitter Follow](https://img.shields.io/twitter/follow/mermaidjs_?style=social)](https://twitter.com/mermaidjs_)
<p align="center">
尝试未来版本的实时编辑器预览: <a href="https://develop.git.mermaid.live/" title="尝试来自develop分支的mermaid版本。">Develop</a> | <a href="https://next.git.mermaid.live/" title="尝试来自next分支的mermaid版本。">Next</a>
</p>
<br>
<br>
[![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid)
[![Build CI Status](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml/badge.svg)](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml)
[![npm minified gzipped bundle size](https://img.shields.io/bundlephobia/minzip/mermaid)](https://bundlephobia.com/package/mermaid)
[![Coverage Status](https://codecov.io/github/mermaid-js/mermaid/branch/develop/graph/badge.svg)](https://app.codecov.io/github/mermaid-js/mermaid/tree/develop)
[![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid)
[![NPM Downloads](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid)
[![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE)
[![Twitter Follow](https://img.shields.io/badge/Social-mermaidjs__-blue?style=social&logo=X)](https://twitter.com/mermaidjs_)
[English](./README.md) | 简体中文
<img src="./img/header.png" alt="" />
@@ -57,9 +24,11 @@ Mermaid 是一个基于 Javascript 的图表绘制工具,通过解析类 Markd
Mermaid 通过允许用户创建便于修改的图表来解决这一难题,它也可以作为生产脚本(或其他代码)的一部分。<br/>
<br/>
Mermaid 甚至能让非程序员也能通过 [Mermaid Live Editor](https://mermaid.live/) 轻松创建详细的图表。<br/>
你可以访问 [教程](./docs/ecosystem/tutorials.md) 来查看 Live Editor 的视频教程,也可以查看 [Mermaid 的集成和使用](./docs/ecosystem/integrations-community.md) 这个清单来检查你的文档工具是否已经集成了 Mermaid 支持。
你可以访问 [教程](./docs/config/Tutorials.md) 来查看 Live Editor 的视频教程,也可以查看 [Mermaid 的集成和使用](./docs/misc/integrations.md) 这个清单来检查你的文档工具是否已经集成了 Mermaid 支持。
如果想要查看关于 Mermaid 更详细的介绍及基础使用方式,可以查看 [入门指引](./docs/intro/getting-started.md), [用法](./docs/config/usage.md) 和 [教程](./docs/ecosystem/tutorials.md).
如果想要查看关于 Mermaid 更详细的介绍及基础使用方式,可以查看 [入门指引](./docs/community/n00b-overview.md), [用法](./docs/config/usage.md) 和 [教程](./docs/config/Tutorials.md).
🌐 [CDN](https://unpkg.com/mermaid/) | 📖 [文档](https://mermaidjs.github.io) | 🙌 [贡献](https://github.com/mermaid-js/mermaid/blob/develop/CONTRIBUTING.md) | 📜 [更新日志](./docs/CHANGELOG.md)
<!-- </Main description> -->
@@ -326,7 +295,7 @@ Rel(SystemC, customerA, "Sends e-mails to")
npm publish
```
以上的命令会将文件打包到 `dist` 目录并发布至 <https://www.npmjs.com>.
以上的命令会将文件打包到 `dist` 目录并发布至 npmjs.org.
## 相关项目
@@ -356,7 +325,7 @@ _很不幸的是鱼与熊掌不可兼得在这个场景下它意味着在
来自 Knut Sveidqvist:
> _特别感谢 [d3](https://d3js.org/) 和 [dagre-d3](https://github.com/cpettitt/dagre-d3) 这两个优秀的项目,它们提供了图形布局和绘图工具库_ > _同样感谢 [js-sequence-diagram](https://bramp.github.io/js-sequence-diagrams) 提供了时序图语法的使用。 感谢 Jessica Peter 提供了甘特图渲染的灵感。_ > _感谢 [Tyler Long](https://github.com/tylerlong) 从 2017 年四月开始成为了项目的合作者。_
> _特别感谢 [d3](https://d3js.org/) 和 [dagre-d3](https://github.com/cpettitt/dagre-d3) 这两个优秀的项目,它们提供了图形布局和绘图工具库! _ >_同样感谢 [js-sequence-diagram](https://bramp.github.io/js-sequence-diagrams) 提供了时序图语法的使用。 感谢 Jessica Peter 提供了甘特图渲染的灵感。_ >_感谢 [Tyler Long](https://github.com/tylerlong) 从 2017 年四月开始成为了项目的合作者。_
>
> _感谢越来越多的 [贡献者们](https://github.com/knsv/mermaid/graphs/contributors)没有你们就没有这个项目的今天_

5
V10-BreakingChanges.md Normal file
View File

@@ -0,0 +1,5 @@
# A collection of updates that change the behaviour
## Lazy loading and asynchronisity
- Invalid dates are rendered as syntax error instead of returning best guess or the current date

View File

@@ -1,4 +1,5 @@
import { MockedD3 } from '../packages/mermaid/src/tests/MockedD3.js';
// @ts-nocheck TODO: Fix TS
import { MockedD3 } from '../packages/mermaid/src/tests/MockedD3';
export const select = function () {
return new MockedD3();

View File

@@ -1,5 +1,5 @@
/**
* Mocked Sankey diagram renderer
* Mocked pie (picChart) diagram renderer
*/
import { vi } from 'vitest';

View File

@@ -1,8 +0,0 @@
/**
* Mocked pie (picChart) diagram renderer
*/
import { vi } from 'vitest';
const draw = vi.fn().mockImplementation(() => '');
export const renderer = { draw };

View File

@@ -5,51 +5,35 @@
"acyclicer",
"adamiecki",
"alois",
"aloisklink",
"antiscript",
"antlr",
"appli",
"applitools",
"asciidoctor",
"ashish",
"ashishjain",
"astah",
"bbox",
"bilkent",
"bisheng",
"blrs",
"braintree",
"brkt",
"brolin",
"brotli",
"catmull",
"città",
"classdef",
"codedoc",
"codemia",
"colour",
"commitlint",
"cpettitt",
"customizability",
"cuzon",
"cytoscape",
"dagre",
"deepdwn",
"descr",
"docsify",
"docsy",
"doku",
"dompurify",
"dont",
"doublecircle",
"edgechromium",
"elems",
"elkjs",
"elle",
"faber",
"flatmap",
"foswiki",
"frontmatter",
"ftplugin",
"gantt",
"gitea",
@@ -59,50 +43,29 @@
"graphviz",
"grav",
"greywolf",
"gzipped",
"huynh",
"huynhicode",
"inkdrop",
"jaoude",
"jgreywolf",
"jison",
"jiti",
"kaufmann",
"khroma",
"klemm",
"klink",
"knsv",
"knut",
"knutsveidqvist",
"laganeckas",
"linetype",
"lintstagedrc",
"logmsg",
"lucida",
"markdownish",
"matthieu",
"matthieumorel",
"mdast",
"mdbook",
"mermaidjs",
"mermerd",
"mindaugas",
"mindmap",
"mindmaps",
"mitigations",
"mkdocs",
"mmorel",
"mult",
"neurodiverse",
"nextra",
"nikolay",
"nirname",
"npmjs",
"orlandoni",
"pathe",
"pbrolin",
"phpbb",
"pixelmatch",
"plantuml",
"playfair",
"pnpm",
@@ -112,30 +75,16 @@
"ranksep",
"rect",
"rects",
"reda",
"redmine",
"regexes",
"rehype",
"roledescription",
"rozhkov",
"sandboxed",
"sankey",
"setupgraphviewbox",
"shiki",
"sidharth",
"sidharthv",
"sphinxcontrib",
"ssim",
"startx",
"starty",
"statediagram",
"steph",
"stopx",
"stopy",
"stylis",
"subhash-halder",
"substate",
"sulais",
"sveidqvist",
"swimm",
"techn",
@@ -143,27 +92,16 @@
"textlength",
"treemap",
"ts-nocheck",
"tsdoc",
"tuleap",
"tylerlong",
"typora",
"ugge",
"unist",
"unocss",
"upvoting",
"valign",
"verdana",
"viewports",
"vinod",
"visio",
"vitepress",
"vueuse",
"xlink",
"xychart",
"yash",
"yokozuna",
"zenuml",
"zune"
"yash"
],
"patterns": [
{ "name": "Markdown links", "pattern": "\\((.*)\\)", "description": "" },
@@ -203,7 +141,6 @@
],
"ignorePaths": [
"packages/mermaid/src/docs/CHANGELOG.md",
"packages/mermaid/src/docs/.vitepress/redirect.ts",
"packages/mermaid/src/docs/.vitepress/contributor-names.json"
"packages/mermaid/src/docs/.vitepress/redirect.ts"
]
}

View File

@@ -2,22 +2,12 @@
const { defineConfig } = require('cypress');
const { addMatchImageSnapshotPlugin } = require('cypress-image-snapshot/plugin');
const coverage = require('@cypress/code-coverage/task');
module.exports = defineConfig({
projectId: 'n2sma2',
viewportWidth: 1440,
viewportHeight: 1024,
e2e: {
specPattern: 'cypress/integration/**/*.{js,ts}',
specPattern: 'cypress/integration/**/*.{js,jsx,ts,tsx}',
setupNodeEvents(on, config) {
coverage(on, config);
on('before:browser:launch', (browser = {}, launchOptions) => {
if (browser.name === 'chrome' && browser.isHeadless) {
launchOptions.args.push('--window-size=1440,1024', '--force-device-scale-factor=1');
}
return launchOptions;
});
addMatchImageSnapshotPlugin(on, config);
// copy any needed variables from process.env to config.env
config.env.useAppli = process.env.USE_APPLI ? true : false;

141
cypress/helpers/util.js Normal file
View File

@@ -0,0 +1,141 @@
const utf8ToB64 = (str) => {
return window.btoa(unescape(encodeURIComponent(str)));
};
const batchId = 'mermid-batch' + new Date().getTime();
export const mermaidUrl = (graphStr, options, api) => {
const obj = {
code: graphStr,
mermaid: options,
};
const objStr = JSON.stringify(obj);
let url = 'http://localhost:9000/e2e.html?graph=' + utf8ToB64(objStr);
if (api) {
url = 'http://localhost:9000/xss.html?graph=' + graphStr;
}
if (options.listUrl) {
cy.log(options.listId, ' ', url);
}
return url;
};
export const imgSnapshotTest = (graphStr, _options, api = false, validation) => {
cy.log(_options);
const options = Object.assign(_options);
if (!options.fontFamily) {
options.fontFamily = 'courier';
}
if (!options.sequence) {
options.sequence = {};
}
if (!options.sequence || (options.sequence && !options.sequence.actorFontFamily)) {
options.sequence.actorFontFamily = 'courier';
}
if (options.sequence && !options.sequence.noteFontFamily) {
options.sequence.noteFontFamily = 'courier';
}
options.sequence.actorFontFamily = 'courier';
options.sequence.noteFontFamily = 'courier';
options.sequence.messageFontFamily = 'courier';
if (options.sequence && !options.sequence.actorFontFamily) {
options.sequence.actorFontFamily = 'courier';
}
if (!options.fontSize) {
options.fontSize = '16px';
}
const useAppli = Cypress.env('useAppli');
cy.log('Hello ' + useAppli ? 'Appli' : 'image-snapshot');
const name = (options.name || cy.state('runnable').fullTitle()).replace(/\s+/g, '-');
if (useAppli) {
cy.log('Opening eyes ' + Cypress.spec.name + ' --- ' + name);
cy.eyesOpen({
appName: 'Mermaid',
testName: name,
batchName: Cypress.spec.name,
batchId: batchId + Cypress.spec.name,
});
}
const url = mermaidUrl(graphStr, options, api);
cy.visit(url);
if (validation) {
cy.get('svg').should(validation);
}
cy.get('svg');
// Default name to test title
if (useAppli) {
cy.log('Check eyes' + Cypress.spec.name);
cy.eyesCheckWindow('Click!');
cy.log('Closing eyes: ' + Cypress.spec.name);
cy.eyesClose();
} else {
cy.matchImageSnapshot(name);
}
};
export const urlSnapshotTest = (url, _options, api = false, validation) => {
cy.log(_options);
const options = Object.assign(_options);
if (!options.fontFamily) {
options.fontFamily = 'courier';
}
if (!options.sequence) {
options.sequence = {};
}
if (!options.sequence || (options.sequence && !options.sequence.actorFontFamily)) {
options.sequence.actorFontFamily = 'courier';
}
if (options.sequence && !options.sequence.noteFontFamily) {
options.sequence.noteFontFamily = 'courier';
}
options.sequence.actorFontFamily = 'courier';
options.sequence.noteFontFamily = 'courier';
options.sequence.messageFontFamily = 'courier';
if (options.sequence && !options.sequence.actorFontFamily) {
options.sequence.actorFontFamily = 'courier';
}
if (!options.fontSize) {
options.fontSize = '16px';
}
const useAppli = Cypress.env('useAppli');
cy.log('Hello ' + useAppli ? 'Appli' : 'image-snapshot');
const name = (options.name || cy.state('runnable').fullTitle()).replace(/\s+/g, '-');
if (useAppli) {
cy.log('Opening eyes 2' + Cypress.spec.name);
cy.eyesOpen({
appName: 'Mermaid',
testName: name,
batchName: Cypress.spec.name,
batchId: batchId + Cypress.spec.name,
});
}
cy.visit(url);
if (validation) {
cy.get('svg').should(validation);
}
cy.get('body');
// Default name to test title
if (useAppli) {
cy.log('Check eyes 2' + Cypress.spec.name);
cy.eyesCheckWindow('Click!');
cy.log('Closing eyes 2' + Cypress.spec.name);
cy.eyesClose();
} else {
cy.matchImageSnapshot(name);
}
};
export const renderGraph = (graphStr, options, api) => {
const url = mermaidUrl(graphStr, options, api);
cy.visit(url);
};

View File

@@ -1,127 +0,0 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Buffer } from 'buffer';
import type { MermaidConfig } from '../../packages/mermaid/src/config.type.js';
interface CypressConfig {
listUrl?: boolean;
listId?: string;
name?: string;
}
type CypressMermaidConfig = MermaidConfig & CypressConfig;
interface CodeObject {
code: string | string[];
mermaid: CypressMermaidConfig;
}
const utf8ToB64 = (str: string): string => {
return Buffer.from(decodeURIComponent(encodeURIComponent(str))).toString('base64');
};
const batchId: string =
'mermaid-batch-' +
(Cypress.env('useAppli')
? Date.now().toString()
: Cypress.env('CYPRESS_COMMIT') || Date.now().toString());
export const mermaidUrl = (
graphStr: string | string[],
options: CypressMermaidConfig,
api: boolean
): string => {
const codeObject: CodeObject = {
code: graphStr,
mermaid: options,
};
const objStr: string = JSON.stringify(codeObject);
let url = `http://localhost:9000/e2e.html?graph=${utf8ToB64(objStr)}`;
if (api) {
url = `http://localhost:9000/xss.html?graph=${graphStr}`;
}
if (options.listUrl) {
cy.log(options.listId, ' ', url);
}
return url;
};
export const imgSnapshotTest = (
graphStr: string,
_options: CypressMermaidConfig = {},
api = false,
validation?: any
): void => {
const options: CypressMermaidConfig = {
..._options,
fontFamily: _options.fontFamily || 'courier',
// @ts-ignore TODO: Fix type of fontSize
fontSize: _options.fontSize || '16px',
sequence: {
...(_options.sequence || {}),
actorFontFamily: 'courier',
noteFontFamily:
_options.sequence && _options.sequence.noteFontFamily
? _options.sequence.noteFontFamily
: 'courier',
messageFontFamily: 'courier',
},
};
const url: string = mermaidUrl(graphStr, options, api);
openURLAndVerifyRendering(url, options, validation);
};
export const urlSnapshotTest = (
url: string,
options: CypressMermaidConfig,
_api = false,
validation?: any
): void => {
openURLAndVerifyRendering(url, options, validation);
};
export const renderGraph = (
graphStr: string | string[],
options: CypressMermaidConfig = {},
api = false
): void => {
const url: string = mermaidUrl(graphStr, options, api);
openURLAndVerifyRendering(url, options);
};
export const openURLAndVerifyRendering = (
url: string,
options: CypressMermaidConfig,
validation?: any
): void => {
const useAppli: boolean = Cypress.env('useAppli');
const name: string = (options.name || cy.state('runnable').fullTitle()).replace(/\s+/g, '-');
if (useAppli) {
cy.log(`Opening eyes ${Cypress.spec.name} --- ${name}`);
cy.eyesOpen({
appName: 'Mermaid',
testName: name,
batchName: Cypress.spec.name,
batchId: batchId + Cypress.spec.name,
});
}
cy.visit(url);
cy.window().should('have.property', 'rendered', true);
cy.get('svg').should('be.visible');
if (validation) {
cy.get('svg').should(validation);
}
if (useAppli) {
cy.log(`Check eyes ${Cypress.spec.name}`);
cy.eyesCheckWindow('Click!');
cy.log(`Closing eyes ${Cypress.spec.name}`);
cy.eyesClose();
} else {
cy.matchImageSnapshot(name);
}
};

View File

@@ -1,4 +1,4 @@
import { renderGraph } from '../../helpers/util.ts';
import { renderGraph } from '../../helpers/util';
describe('Configuration', () => {
describe('arrowMarkerAbsolute', () => {
it('should handle default value false of arrowMarkerAbsolute', () => {
@@ -117,6 +117,7 @@ describe('Configuration', () => {
});
it('should not taint the initial configuration when using multiple directives', () => {
const url = 'http://localhost:9000/regression/issue-1874.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('svg');

View File

@@ -1,9 +1,9 @@
import { urlSnapshotTest } from '../../helpers/util.ts';
import { urlSnapshotTest } from '../../helpers/util';
describe('mermaid', () => {
describe('registerDiagram', () => {
it('should work on @mermaid-js/mermaid-example-diagram', () => {
const url = 'http://localhost:9000/external-diagrams-example-diagram.html';
it('should work on @mermaid-js/mermaid-mindmap and mermaid-example-diagram', () => {
const url = 'http://localhost:9000/external-diagrams-mindmap.html';
urlSnapshotTest(url, {}, false, false);
});
});

View File

@@ -1,4 +1,4 @@
import { urlSnapshotTest, openURLAndVerifyRendering } from '../../helpers/util.ts';
import { urlSnapshotTest } from '../../helpers/util';
describe('CSS injections', () => {
it('should not allow CSS injections outside of the diagram', () => {
@@ -13,11 +13,4 @@ describe('CSS injections', () => {
flowchart: { htmlLabels: false },
});
});
it('should not allow manipulating styletags using arrowheads', () => {
openURLAndVerifyRendering('http://localhost:9000/xss23-css.html', {
logLevel: 1,
arrowMarkerAbsolute: false,
flowchart: { htmlLabels: true },
});
});
});

View File

@@ -1,12 +1,14 @@
describe('Rerendering', () => {
it('should be able to render after an error has occurred', () => {
const url = 'http://localhost:9000/render-after-error.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('#graphDiv').should('exist');
});
it('should be able to render and rerender a graph via API', () => {
const url = 'http://localhost:9000/rerender.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('#graph [id^=flowchart-A]').should('have.text', 'XMas');

View File

@@ -1,4 +1,4 @@
import { mermaidUrl } from '../../helpers/util.ts';
import { mermaidUrl } from '../../helpers/util.js';
describe('XSS', () => {
it('should handle xss in tags', () => {
const str =
@@ -132,9 +132,4 @@ describe('XSS', () => {
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
});
it('should sanitize backticks in class names properly', () => {
cy.visit('http://localhost:9000/xss24.html');
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
});
});

View File

@@ -1,4 +1,4 @@
import { imgSnapshotTest } from '../../helpers/util.ts';
import { imgSnapshotTest } from '../../helpers/util.js';
describe('Git Graph diagram', () => {
it('1: should render a simple gitgraph with commit on main branch', () => {

View File

@@ -1,4 +1,4 @@
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
describe('C4 diagram', () => {
it('should render a simple C4Context diagram', () => {

View File

@@ -1,4 +1,4 @@
import { imgSnapshotTest } from '../../helpers/util.ts';
import { imgSnapshotTest } from '../../helpers/util';
describe('Class diagram V2', () => {
it('0: should render a simple class diagram', () => {
imgSnapshotTest(
@@ -13,6 +13,7 @@ describe('Class diagram V2', () => {
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('1: should render a simple class diagram', () => {
@@ -46,6 +47,7 @@ describe('Class diagram V2', () => {
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('2: should render a simple class diagrams with cardinality', () => {
@@ -74,6 +76,7 @@ describe('Class diagram V2', () => {
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('should render a simple class diagram with different visibilities', () => {
@@ -91,6 +94,7 @@ describe('Class diagram V2', () => {
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('should render multiple class diagrams', () => {
@@ -143,6 +147,7 @@ describe('Class diagram V2', () => {
],
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('4: should render a simple class diagram with comments', () => {
@@ -172,6 +177,7 @@ describe('Class diagram V2', () => {
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('5: should render a simple class diagram with abstract method', () => {
@@ -183,6 +189,7 @@ describe('Class diagram V2', () => {
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('6: should render a simple class diagram with static method', () => {
@@ -194,6 +201,7 @@ describe('Class diagram V2', () => {
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('7: should render a simple class diagram with Generic class', () => {
@@ -213,6 +221,7 @@ describe('Class diagram V2', () => {
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('8: should render a simple class diagram with Generic class and relations', () => {
@@ -233,6 +242,7 @@ describe('Class diagram V2', () => {
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('9: should render a simple class diagram with clickable link', () => {
@@ -254,6 +264,7 @@ describe('Class diagram V2', () => {
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('10: should render a simple class diagram with clickable callback', () => {
@@ -275,6 +286,7 @@ describe('Class diagram V2', () => {
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('11: should render a simple class diagram with return type on method', () => {
@@ -289,6 +301,7 @@ describe('Class diagram V2', () => {
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('12: should render a simple class diagram with generic types', () => {
@@ -304,6 +317,7 @@ describe('Class diagram V2', () => {
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('13: should render a simple class diagram with css classes applied', () => {
@@ -321,6 +335,7 @@ describe('Class diagram V2', () => {
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('14: should render a simple class diagram with css classes applied directly', () => {
@@ -336,6 +351,7 @@ describe('Class diagram V2', () => {
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('15: should render a simple class diagram with css classes applied two multiple classes', () => {
@@ -349,6 +365,7 @@ describe('Class diagram V2', () => {
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('16a: should render a simple class diagram with static field', () => {
@@ -361,6 +378,7 @@ describe('Class diagram V2', () => {
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('16b: should handle the direction statement with TB', () => {
@@ -385,6 +403,32 @@ describe('Class diagram V2', () => {
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('18: should handle the direction statement with LR', () => {
imgSnapshotTest(
`
classDiagram
direction LR
class Student {
-idCard : IdCard
}
class IdCard{
-id : int
-name : string
}
class Bike{
-id : int
-name : string
}
Student "1" --o "1" IdCard : carries
Student "1" --o "1" Bike : rides
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('17a: should handle the direction statement with BT', () => {
imgSnapshotTest(
@@ -408,6 +452,7 @@ describe('Class diagram V2', () => {
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('17b: should handle the direction statement with RL', () => {
imgSnapshotTest(
@@ -431,33 +476,10 @@ describe('Class diagram V2', () => {
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('18a: should handle the direction statement with LR', () => {
imgSnapshotTest(
`
classDiagram
direction LR
class Student {
-idCard : IdCard
}
class IdCard{
-id : int
-name : string
}
class Bike{
-id : int
-name : string
}
Student "1" --o "1" IdCard : carries
Student "1" --o "1" Bike : rides
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
});
it('18b: should render a simple class diagram with notes', () => {
it('18: should render a simple class diagram with notes', () => {
imgSnapshotTest(
`
classDiagram-v2
@@ -471,6 +493,7 @@ describe('Class diagram V2', () => {
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('1433: should render a simple class with a title', () => {
@@ -480,105 +503,8 @@ title: simple class diagram
---
classDiagram-v2
class Class10
`
);
});
it('should render a class with text label', () => {
imgSnapshotTest(
`classDiagram
class C1["Class 1 with text label"]
C1 --> C2`
);
});
it('should render two classes with text labels', () => {
imgSnapshotTest(
`classDiagram
class C1["Class 1 with text label"]
class C2["Class 2 with chars @?"]
C1 --> C2`
);
});
it('should render a class with a text label, members and annotation', () => {
imgSnapshotTest(
`classDiagram
class C1["Class 1 with text label"] {
&lt;&lt;interface&gt;&gt;
+member1
}
C1 --> C2`
);
});
it('should render multiple classes with same text labels', () => {
imgSnapshotTest(
`classDiagram
class C1["Class with text label"]
class C2["Class with text label"]
class C3["Class with text label"]
C1 --> C2
C3 ..> C2
`
);
});
it('should render classes with different text labels', () => {
imgSnapshotTest(
`classDiagram
class C1["OneWord"]
class C2["With, Comma"]
class C3["With (Brackets)"]
class C4["With [Brackets]"]
class C5["With {Brackets}"]
class C7["With 1 number"]
class C8["With . period..."]
class C9["With - dash"]
class C10["With _ underscore"]
class C11["With ' single quote"]
class C12["With ~!@#$%^&*()_+=-/?"]
class C13["With Città foreign language"]
`
);
});
it('should render classLabel if class has already been defined earlier', () => {
imgSnapshotTest(
`classDiagram
Animal <|-- Duck
class Duck["Duck with text label"]
`
);
});
it('should add classes namespaces', function () {
imgSnapshotTest(
`
classDiagram
namespace Namespace1 {
class C1
class C2
}
C1 --> C2
class C3
class C4
`
);
});
it('should render a simple class diagram with no members', () => {
imgSnapshotTest(
`
classDiagram-v2
class Class10
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
});
it('should render a simple class diagram with style definition', () => {
imgSnapshotTest(
`
classDiagram-v2
class Class10
style Class10 fill:#f9f,stroke:#333,stroke-width:4px
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
`,
{}
);
});
});

View File

@@ -1,4 +1,4 @@
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
import { imgSnapshotTest, renderGraph } from '../../helpers/util';
describe('Class diagram', () => {
it('1: should render a simple class diagram', () => {
@@ -286,7 +286,7 @@ describe('Class diagram', () => {
cy.get('svg');
});
it('15: should render a simple class diagram with css classes applied to multiple classes', () => {
it('15: should render a simple class diagram with css classes applied two multiple classes', () => {
imgSnapshotTest(
`
classDiagram
@@ -423,94 +423,4 @@ describe('Class diagram', () => {
);
cy.get('svg');
});
it('should render class diagram with newlines in title', () => {
imgSnapshotTest(`
classDiagram
Animal <|-- \`Du\nck\`
Animal : +int age
Animal : +String gender
Animal: +isMammal()
Animal: +mate()
class \`Du\nck\` {
+String beakColor
+String featherColor
+swim()
+quack()
}
`);
cy.get('svg');
});
it('should render class diagram with many newlines in title', () => {
imgSnapshotTest(`
classDiagram
class \`This\nTitle\nHas\nMany\nNewlines\` {
+String Also
-Stirng Many
#int Members
+And()
-Many()
#Methods()
}
`);
});
it('should render with newlines in title and an annotation', () => {
imgSnapshotTest(`
classDiagram
class \`This\nTitle\nHas\nMany\nNewlines\` {
+String Also
-Stirng Many
#int Members
+And()
-Many()
#Methods()
}
&lt;&lt;Interface&gt;&gt; \`This\nTitle\nHas\nMany\nNewlines\`
`);
});
it('should handle newline title in namespace', () => {
imgSnapshotTest(`
classDiagram
namespace testingNamespace {
class \`This\nTitle\nHas\nMany\nNewlines\` {
+String Also
-Stirng Many
#int Members
+And()
-Many()
#Methods()
}
}
`);
});
it('should handle newline in string label', () => {
imgSnapshotTest(`
classDiagram
class A["This has\na newline!"] {
+String boop
-Int beep
#double bop
}
class B["This title also has\na newline"]
B : +with(more)
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

@@ -1,4 +1,4 @@
import { imgSnapshotTest, urlSnapshotTest } from '../../helpers/util.ts';
import { imgSnapshotTest } from '../../helpers/util.js';
describe('Configuration and directives - nodes should be light blue', () => {
it('No config - use default', () => {
@@ -14,6 +14,7 @@ describe('Configuration and directives - nodes should be light blue', () => {
`,
{}
);
cy.get('svg');
});
it('Settings from initialize - nodes should be green', () => {
imgSnapshotTest(
@@ -27,6 +28,7 @@ graph TD
end `,
{ theme: 'forest' }
);
cy.get('svg');
});
it('Settings from initialize overriding themeVariable - nodes should be red', () => {
imgSnapshotTest(
@@ -44,6 +46,7 @@ graph TD
`,
{ theme: 'base', themeVariables: { primaryColor: '#ff0000' }, logLevel: 0 }
);
cy.get('svg');
});
it('Settings from directive - nodes should be grey', () => {
imgSnapshotTest(
@@ -59,24 +62,7 @@ graph TD
`,
{}
);
});
it('Settings from frontmatter - nodes should be grey', () => {
imgSnapshotTest(
`
---
config:
theme: neutral
---
graph TD
A(Start) --> B[/Another/]
A[/Another/] --> C[End]
subgraph section
B
C
end
`,
{}
);
cy.get('svg');
});
it('Settings from directive overriding theme variable - nodes should be red', () => {
@@ -93,6 +79,7 @@ graph TD
`,
{}
);
cy.get('svg');
});
it('Settings from initialize and directive - nodes should be grey', () => {
imgSnapshotTest(
@@ -108,6 +95,7 @@ graph TD
`,
{ theme: 'forest' }
);
cy.get('svg');
});
it('Theme from initialize, directive overriding theme variable - nodes should be red', () => {
imgSnapshotTest(
@@ -123,71 +111,8 @@ graph TD
`,
{ theme: 'base' }
);
cy.get('svg');
});
it('Theme from initialize, frontmatter overriding theme variable - nodes should be red', () => {
imgSnapshotTest(
`
---
config:
theme: base
themeVariables:
primaryColor: '#ff0000'
---
graph TD
A(Start) --> B[/Another/]
A[/Another/] --> C[End]
subgraph section
B
C
end
`,
{ theme: 'forest' }
);
});
it('Theme from initialize, frontmatter overriding theme variable, directive overriding primaryColor - nodes should be red', () => {
imgSnapshotTest(
`
---
config:
theme: base
themeVariables:
primaryColor: '#00ff00'
---
%%{init: {'theme': 'base', 'themeVariables':{ 'primaryColor': '#ff0000'}}}%%
graph TD
A(Start) --> B[/Another/]
A[/Another/] --> C[End]
subgraph section
B
C
end
`,
{ theme: 'forest' }
);
});
it('should render if values are not quoted properly', () => {
// #ff0000 is not quoted properly, and will evaluate to null.
// This test ensures that the rendering still works.
imgSnapshotTest(
`---
config:
theme: base
themeVariables:
primaryColor: #ff0000
---
graph TD
A(Start) --> B[/Another/]
A[/Another/] --> C[End]
subgraph section
B
C
end
`,
{ theme: 'forest' }
);
});
it('Theme variable from initialize, theme from directive - nodes should be red', () => {
imgSnapshotTest(
`
@@ -202,11 +127,14 @@ graph TD
`,
{ themeVariables: { primaryColor: '#ff0000' } }
);
cy.get('svg');
});
describe('when rendering several diagrams', () => {
it('diagrams should not taint later diagrams', () => {
const url = 'http://localhost:9000/theme-directives.html';
urlSnapshotTest(url, {});
cy.visit(url);
cy.get('svg');
cy.matchImageSnapshot('conf-and-directives.spec-when-rendering-several-diagrams-diagram-1');
});
});
});

View File

@@ -1,4 +1,4 @@
import { imgSnapshotTest } from '../../helpers/util.ts';
import { imgSnapshotTest } from '../../helpers/util';
describe('Current diagram', () => {
it('should render a state with states in it', () => {

View File

@@ -0,0 +1,12 @@
import { imgSnapshotTest } from '../../helpers/util';
describe('Flowchart', () => {
it('34: testing the label width in percy', () => {
imgSnapshotTest(
`graph TD
A[Christmas]
`,
{ theme: 'forest', fontFamily: '"Noto Sans SC", sans-serif' }
);
});
});

View File

@@ -1,4 +1,4 @@
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
import { imgSnapshotTest, renderGraph } from '../../helpers/util';
describe('Entity Relationship Diagram', () => {
it('should render a simple ER diagram', () => {
@@ -10,6 +10,7 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render an ER diagram with a recursive relationship', () => {
@@ -22,6 +23,7 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render an ER diagram with multiple relationships between the same two entities', () => {
@@ -33,6 +35,7 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render a cyclical ER diagram', () => {
@@ -45,6 +48,7 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render a not-so-simple ER diagram', () => {
@@ -62,6 +66,7 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render multiple ER diagrams', () => {
@@ -80,6 +85,7 @@ describe('Entity Relationship Diagram', () => {
],
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render an ER diagram with blank or empty labels', () => {
@@ -92,6 +98,7 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render an ER diagrams when useMaxWidth is true (default)', () => {
@@ -144,6 +151,7 @@ describe('Entity Relationship Diagram', () => {
`,
{ er: { useMaxWidth: false } }
);
cy.get('svg');
});
it('should render entities with and without attributes', () => {
@@ -156,6 +164,7 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render entities with generic and array attributes', () => {
@@ -170,6 +179,7 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render entities with length in attributes type', () => {
@@ -178,11 +188,12 @@ describe('Entity Relationship Diagram', () => {
erDiagram
CLUSTER {
varchar(99) name
string(255) description
string(255) description
}
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render entities and attributes with big and small entity names', () => {
@@ -198,26 +209,6 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
});
it('should render entities with attributes that begin with asterisk', () => {
imgSnapshotTest(
`
erDiagram
BOOK {
int *id
string name
varchar(99) summary
}
BOOK }o..o{ STORE : soldBy
STORE {
int *id
string name
varchar(50) address
}
`,
{ loglevel: 1 }
);
cy.get('svg');
});
@@ -237,6 +228,7 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render entities with comments', () => {
@@ -255,6 +247,7 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render entities with keys and comments', () => {
@@ -274,6 +267,7 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render entities with aliases', () => {
@@ -291,6 +285,7 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('1433: should render a simple ER diagram with a title', () => {
@@ -305,21 +300,4 @@ ORDER ||--|{ LINE-ITEM : contains
{}
);
});
it('should render entities with entity name aliases', () => {
imgSnapshotTest(
`
erDiagram
p[Person] {
varchar(64) firstName
varchar(64) lastName
}
c["Customer Account"] {
varchar(128) email
}
p ||--o| c : has
`,
{ logLevel: 1 }
);
});
});

View File

@@ -1,45 +0,0 @@
import { imgSnapshotTest } from '../../helpers/util';
describe('Error Diagrams', () => {
beforeEach(() => {
cy.on('uncaught:exception', (err) => {
expect(err.message).to.include('Parse error');
// return false to prevent the error from
// failing this test
return false;
});
});
it('should render a simple ER diagram', () => {
imgSnapshotTest(
`
error
`,
{ logLevel: 1 }
);
});
it('should render error diagram for actual errors', () => {
imgSnapshotTest(
`
flowchart TD
A[Christmas] --|Get money| B(Go shopping)
`,
{ logLevel: 1 }
);
});
it('should render error for wrong ER diagram', () => {
imgSnapshotTest(
`
erDiagram
ATLAS-ORGANIZATION ||--|{ ATLAS-PROJECTS : "has many"
ATLAS-PROJECTS ||--|{ MONGODB-CLUSTERS : "has many"
ATLAS-PROJECTS ||--|{ ATLAS-TEAMS : "has many"
MONGODB-CLUSTERS ||..|{
ATLAS-TEAMS ||..|{
`,
{ logLevel: 1 }
);
});
});

View File

@@ -1,846 +0,0 @@
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
describe.skip('Flowchart ELK', () => {
it('1-elk: should render a simple flowchart', () => {
imgSnapshotTest(
`flowchart-elk TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
C -->|One| D[Laptop]
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
`,
{}
);
imgSnapshotTest(
`flowchart TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
C -->|One| D[Laptop]
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
`,
{ flowchart: { defaultRenderer: 'elk' } }
);
});
it('2-elk: should render a simple flowchart with diagramPadding set to 0', () => {
imgSnapshotTest(
`flowchart-elk TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
%% this is a comment
C -->|One| D[Laptop]
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
`,
{ flowchart: { diagramPadding: 0 } }
);
});
it('3-elk: a link with correct arrowhead to a subgraph', () => {
imgSnapshotTest(
`flowchart-elk TD
P1
P1 -->P1.5
subgraph P1.5
P2
P2.5(( A ))
P3
end
P2 --> P4
P3 --> P6
P1.5 --> P5
`,
{}
);
});
it('4-elk: Length of edges', () => {
imgSnapshotTest(
`flowchart-elk TD
L1 --- L2
L2 --- C
M1 ---> C
R1 .-> R2
R2 <.-> C
C -->|Label 1| E1
C <-- Label 2 ---> E2
C ----> E3
C <-...-> E4
C ======> E5
`,
{}
);
});
it('5-elk: should render escaped without html labels', () => {
imgSnapshotTest(
`flowchart-elk TD
a["<strong>Haiya</strong>"]---->b
`,
{ htmlLabels: false, flowchart: { htmlLabels: false } }
);
});
it('6-elk: should render non-escaped with html labels', () => {
imgSnapshotTest(
`flowchart-elk TD
a["<strong>Haiya</strong>"]===>b
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('7-elk: should render a flowchart when useMaxWidth is true (default)', () => {
renderGraph(
`flowchart-elk TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
C -->|One| D[Laptop]
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
`,
{ flowchart: { useMaxWidth: true } }
);
cy.get('svg').should((svg) => {
expect(svg).to.have.attr('width', '100%');
// expect(svg).to.have.attr('height');
// use within because the absolute value can be slightly different depending on the environment ±5%
// const height = parseFloat(svg.attr('height'));
// expect(height).to.be.within(446 * 0.95, 446 * 1.05);
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
expect(maxWidthValue).to.be.within(230 * 0.95, 230 * 1.05);
});
});
it('8-elk: should render a flowchart when useMaxWidth is false', () => {
renderGraph(
`flowchart-elk TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
C -->|One| D[Laptop]
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
`,
{ flowchart: { useMaxWidth: false } }
);
cy.get('svg').should((svg) => {
// const height = parseFloat(svg.attr('height'));
const width = parseFloat(svg.attr('width'));
// use within because the absolute value can be slightly different depending on the environment ±5%
// expect(height).to.be.within(446 * 0.95, 446 * 1.05);
expect(width).to.be.within(230 * 0.95, 230 * 1.05);
expect(svg).to.not.have.attr('style');
});
});
it('V2 elk - 16: Render Stadium shape', () => {
imgSnapshotTest(
` flowchart-elk TD
A([stadium shape test])
A -->|Get money| B([Go shopping])
B --> C([Let me think...<br />Do I want something for work,<br />something to spend every free second with,<br />or something to get around?])
C -->|One| D([Laptop])
C -->|Two| E([iPhone])
C -->|Three| F([Car<br/>wroom wroom])
click A "index.html#link-clicked" "link test"
click B testClick "click test"
classDef someclass fill:#f96;
class A someclass;
class C someclass;
`,
{ flowchart: { htmlLabels: false }, fontFamily: 'courier' }
);
});
it('50-elk: handle nested subgraphs in reverse order', () => {
imgSnapshotTest(
`flowchart-elk LR
a -->b
subgraph A
B
end
subgraph B
b
end
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('51-elk: handle nested subgraphs in reverse order', () => {
imgSnapshotTest(
`flowchart-elk LR
a -->b
subgraph A
B
end
subgraph B
b
end
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('52-elk: handle nested subgraphs in several levels', () => {
imgSnapshotTest(
`flowchart-elk TB
b-->B
a-->c
subgraph O
A
end
subgraph B
c
end
subgraph A
a
b
B
end
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('53-elk: handle nested subgraphs with edges in and out', () => {
imgSnapshotTest(
`flowchart-elk TB
internet
nat
routeur
lb1
lb2
compute1
compute2
subgraph project
routeur
nat
subgraph subnet1
compute1
lb1
end
subgraph subnet2
compute2
lb2
end
end
internet --> routeur
routeur --> subnet1 & subnet2
subnet1 & subnet2 --> nat --> internet
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('54-elk: handle nested subgraphs with outgoing links', () => {
imgSnapshotTest(
`flowchart-elk TD
subgraph main
subgraph subcontainer
subcontainer-child
end
subcontainer-child--> subcontainer-sibling
end
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('55-elk: handle nested subgraphs with outgoing links 2', () => {
imgSnapshotTest(
`flowchart-elk TD
subgraph one[One]
subgraph sub_one[Sub One]
_sub_one
end
subgraph sub_two[Sub Two]
_sub_two
end
_one
end
%% here, either the first or the second one
sub_one --> sub_two
_one --> b
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('56-elk: handle nested subgraphs with outgoing links 3', () => {
imgSnapshotTest(
`flowchart-elk TB
subgraph container_Beta
process_C-->Process_D
end
subgraph container_Alpha
process_A-->process_B
process_A-->|messages|process_C
end
process_B-->|via_AWSBatch|container_Beta
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('57-elk: handle nested subgraphs with outgoing links 4', () => {
imgSnapshotTest(
`flowchart-elk LR
subgraph A
a -->b
end
subgraph B
b
end
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('57-elk: handle nested subgraphs with outgoing links 2', () => {
imgSnapshotTest(
`flowchart-elk TB
c1-->a2
subgraph one
a1-->a2
end
subgraph two
b1-->b2
end
subgraph three
c1-->c2
end
one --> two
three --> two
two --> c2
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('57.x: handle nested subgraphs with outgoing links 5', () => {
imgSnapshotTest(
`%% this does not produce the desired result
flowchart-elk TB
subgraph container_Beta
process_C-->Process_D
end
subgraph container_Alpha
process_A-->process_B
process_B-->|via_AWSBatch|container_Beta
process_A-->|messages|process_C
end
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('58-elk: handle styling with style expressions', () => {
imgSnapshotTest(
`
flowchart-elk LR
id1(Start)-->id2(Stop)
style id1 fill:#f9f,stroke:#333,stroke-width:4px
style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('59-elk: handle styling of subgraphs and links', () => {
imgSnapshotTest(
`
flowchart-elk TD
A[Christmas] ==> D
A[Christmas] -->|Get money| B(Go shopping)
A[Christmas] ==> C
subgraph T ["Test"]
A
B
C
end
classDef Test fill:#F84E68,stroke:#333,color:white;
class A,T Test
classDef TestSub fill:green;
class T TestSub
linkStyle 0,1 color:orange, stroke: orange;
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('60-elk: handle styling for all node shapes - v2', () => {
imgSnapshotTest(
`
flowchart-elk LR
A[red text] -->|default style| B(blue text)
C([red text]) -->|default style| D[[blue text]]
E[(red text)] -->|default style| F((blue text))
G>red text] -->|default style| H{blue text}
I{{red text}} -->|default style| J[/blue text/]
K[\\ red text\\] -->|default style| L[/blue text\\]
M[\\ red text/] -->|default style| N[blue text];
O(((red text))) -->|default style| P(((blue text)));
linkStyle default color:Sienna;
style A stroke:#ff0000,fill:#ffcccc,color:#ff0000;
style B stroke:#0000ff,fill:#ccccff,color:#0000ff;
style C stroke:#ff0000,fill:#ffcccc,color:#ff0000;
style D stroke:#0000ff,fill:#ccccff,color:#0000ff;
style E stroke:#ff0000,fill:#ffcccc,color:#ff0000;
style F stroke:#0000ff,fill:#ccccff,color:#0000ff;
style G stroke:#ff0000,fill:#ffcccc,color:#ff0000;
style H stroke:#0000ff,fill:#ccccff,color:#0000ff;
style I stroke:#ff0000,fill:#ffcccc,color:#ff0000;
style J stroke:#0000ff,fill:#ccccff,color:#0000ff;
style K stroke:#ff0000,fill:#ffcccc,color:#ff0000;
style L stroke:#0000ff,fill:#ccccff,color:#0000ff;
style M stroke:#ff0000,fill:#ffcccc,color:#ff0000;
style N stroke:#0000ff,fill:#ccccff,color:#0000ff;
style O stroke:#ff0000,fill:#ffcccc,color:#ff0000;
style P stroke:#0000ff,fill:#ccccff,color:#0000ff;
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose', logLevel: 2 }
);
});
it('61-elk: fontawesome icons in edge labels', () => {
imgSnapshotTest(
`
flowchart-elk TD
C -->|fa:fa-car Car| F[fa:fa-car Car]
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('62-elk: should render styled subgraphs', () => {
imgSnapshotTest(
`
flowchart-elk TB
A
B
subgraph foo[Foo SubGraph]
C
D
end
subgraph bar[Bar SubGraph]
E
F
end
G
A-->B
B-->C
C-->D
B-->D
D-->E
E-->A
E-->F
F-->D
F-->G
B-->G
G-->D
style foo fill:#F99,stroke-width:2px,stroke:#F0F,color:darkred
style bar fill:#999,stroke-width:10px,stroke:#0F0,color:blue
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('63-elk: title on subgraphs should be themable', () => {
imgSnapshotTest(
`
%%{init:{"theme":"base", "themeVariables": {"primaryColor":"#411d4e", "titleColor":"white", "darkMode":true}}}%%
flowchart-elk LR
subgraph A
a --> b
end
subgraph B
i -->f
end
A --> B
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('65-elk: text-color from classes', () => {
imgSnapshotTest(
`
flowchart-elk LR
classDef dark fill:#000,stroke:#000,stroke-width:4px,color:#fff
Lorem --> Ipsum --> Dolor
class Lorem,Dolor dark
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('66-elk: More nested subgraph cases (TB)', () => {
imgSnapshotTest(
`
flowchart-elk TB
subgraph two
b1
end
subgraph three
c2
end
three --> two
two --> c2
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('67-elk: More nested subgraph cases (RL)', () => {
imgSnapshotTest(
`
flowchart-elk RL
subgraph two
b1
end
subgraph three
c2
end
three --> two
two --> c2
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('68-elk: More nested subgraph cases (BT)', () => {
imgSnapshotTest(
`
flowchart-elk BT
subgraph two
b1
end
subgraph three
c2
end
three --> two
two --> c2
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('69-elk: More nested subgraph cases (LR)', () => {
imgSnapshotTest(
`
flowchart-elk LR
subgraph two
b1
end
subgraph three
c2
end
three --> two
two --> c2
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('70-elk: Handle nested subgraph cases (TB) link out and link between subgraphs', () => {
imgSnapshotTest(
`
flowchart-elk TB
subgraph S1
sub1 -->sub2
end
subgraph S2
sub4
end
S1 --> S2
sub1 --> sub4
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('71-elk: Handle nested subgraph cases (RL) link out and link between subgraphs', () => {
imgSnapshotTest(
`
flowchart-elk RL
subgraph S1
sub1 -->sub2
end
subgraph S2
sub4
end
S1 --> S2
sub1 --> sub4
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('72-elk: Handle nested subgraph cases (BT) link out and link between subgraphs', () => {
imgSnapshotTest(
`
flowchart-elk BT
subgraph S1
sub1 -->sub2
end
subgraph S2
sub4
end
S1 --> S2
sub1 --> sub4
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('74-elk: Handle nested subgraph cases (RL) link out and link between subgraphs', () => {
imgSnapshotTest(
`
flowchart-elk RL
subgraph S1
sub1 -->sub2
end
subgraph S2
sub4
end
S1 --> S2
sub1 --> sub4
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('74-elk: Handle labels for multiple edges from and to the same couple of nodes', () => {
imgSnapshotTest(
`
flowchart-elk RL
subgraph one
a1 -- l1 --> a2
a1 -- l2 --> a2
end
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('76-elk: handle unicode encoded character with HTML labels true', () => {
imgSnapshotTest(
`flowchart-elk TB
a{{"Lorem 'ipsum' dolor 'sit' amet, 'consectetur' adipiscing 'elit'."}}
--> b{{"Lorem #quot;ipsum#quot; dolor #quot;sit#quot; amet,#quot;consectetur#quot; adipiscing #quot;elit#quot;."}}
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('2050-elk: handling of different rendering direction in subgraphs', () => {
imgSnapshotTest(
`
flowchart-elk LR
subgraph TOP
direction TB
subgraph B1
direction RL
i1 -->f1
end
subgraph B2
direction BT
i2 -->f2
end
end
A --> TOP --> B
B1 --> B2
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('2388-elk: handling default in the node name', () => {
imgSnapshotTest(
`
flowchart-elk LR
default-index.js --> dot.template.js
index.js --> module-utl.js
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('2824-elk: Clipping of edges', () => {
imgSnapshotTest(
`
flowchart-elk TD
A --> B
A --> C
B --> C
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('1433-elk: should render a titled flowchart with titleTopMargin set to 0', () => {
imgSnapshotTest(
`---
title: Simple flowchart
---
flowchart-elk TD
A --> B
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('elk: should include classes on the edges', () => {
renderGraph(
`flowchart-elk TD
A --> B --> C --> D
`,
{}
);
cy.get('svg').should((svg) => {
const edges = svg.querySelectorAll('.edges > path');
edges.forEach((edge) => {
expect(edge).to.have.class('flowchart-link');
});
});
});
describe('Markdown strings flowchart-elk (#4220)', () => {
describe('html labels', () => {
it('With styling and classes', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": true}} }%%
flowchart-elk LR
A:::someclass --> B["\`The **cat** in the hat\`"]:::someclass
id1(Start)-->id2(Stop)
style id1 fill:#f9f,stroke:#333,stroke-width:4px
style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
classDef someclass fill:#f96
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('With formatting in a node', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": true}} }%%
flowchart-elk LR
a{"\`The **cat** in the hat\`"} -- 1o --> b
a -- 2o --> c
a -- 3o --> d
g --2i--> a
d --1i--> a
h --3i -->a
b --> d(The dog in the hog)
c --> d
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('New line in node and formatted edge label', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": true}} }%%
flowchart-elk LR
b("\`The dog in **the** hog.(1)
NL\`") --"\`1o **bold**\`"--> c
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('Wrapping long text with a new line', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": true}} }%%
flowchart-elk LR
b(\`The dog in **the** hog.(1).. a a a a *very long text* about it
Word!
Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. \`) --> c
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('Sub graphs and markdown strings', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": true}} }%%
flowchart-elk LR
subgraph "One"
a("\`The **cat**
in the hat\`") -- "1o" --> b{{"\`The **dog** in the hog\`"}}
end
subgraph "\`**Two**\`"
c("\`The **cat**
in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog")
end
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
});
describe('svg text labels', () => {
it('With styling and classes', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart-elk LR
A:::someclass --> B["\`The **cat** in the hat\`"]:::someclass
id1(Start)-->id2(Stop)
style id1 fill:#f9f,stroke:#333,stroke-width:4px
style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
classDef someclass fill:#f96
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('With formatting in a node', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart-elk LR
a{"\`The **cat** in the hat\`"} -- 1o --> b
a -- 2o --> c
a -- 3o --> d
g --2i--> a
d --1i--> a
h --3i -->a
b --> d(The dog in the hog)
c --> d
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('New line in node and formatted edge label', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart-elk LR
b("\`The dog in **the** hog.(1)
NL\`") --"\`1o **bold**\`"--> c
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('Wrapping long text with a new line', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart-elk LR
b("\`The dog in **the** hog.(1).. a a a a *very long text* about it
Word!
Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. \`") --> c
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('Sub graphs and markdown strings', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart-elk LR
subgraph "One"
a("\`The **cat**
in the hat\`") -- "1o" --> b{{"\`The **dog** in the hog\`"}}
end
subgraph "\`**Two**\`"
c("\`The **cat**
in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog")
end
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
});
});
});

View File

@@ -1,4 +1,4 @@
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
import { imgSnapshotTest, renderGraph } from '../../helpers/util';
describe('Flowchart v2', () => {
it('1: should render a simple flowchart', () => {
@@ -172,7 +172,7 @@ describe('Flowchart v2', () => {
);
});
it('52: handle nested subgraphs in several levels.', () => {
it('52: handle nested subgraphs in several levels', () => {
imgSnapshotTest(
`flowchart TB
b-->B
@@ -449,7 +449,7 @@ flowchart TD
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('65-1: text-color from classes', () => {
it('65: text-color from classes', () => {
imgSnapshotTest(
`
flowchart LR
@@ -460,31 +460,6 @@ flowchart TD
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('65-2: bold text from classes', () => {
imgSnapshotTest(
`
flowchart
classDef cat fill:#f9d5e5, stroke:#233d4d,stroke-width:2px, font-weight:bold;
CS(A long bold text to be viewed):::cat
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('65-3: bigger font from classes', () => {
imgSnapshotTest(
`
flowchart
Node1:::class1 --> Node2:::class2
Node1:::class1 --> Node3:::class2
Node3 --> Node4((I am a circle)):::larger
classDef class1 fill:lightblue
classDef class2 fill:pink
classDef larger font-size:30px,fill:yellow
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('66: More nested subgraph cases (TB)', () => {
imgSnapshotTest(
`
@@ -696,302 +671,7 @@ title: Simple flowchart
flowchart TD
A --> B
`,
{ flowchart: { titleTopMargin: 10 } }
{ titleTopMargin: 0 }
);
});
it('3192: It should be possieble to render flowcharts with invisible edges', () => {
imgSnapshotTest(
`---
title: Simple flowchart with invisible edges
---
flowchart TD
A ~~~ B
`,
{ flowchart: { titleTopMargin: 10 } }
);
});
it('4023: Should render html labels with images and-or text correctly', () => {
imgSnapshotTest(
`flowchart TD
B[<img src='https://mermaid.js.org/mermaid-logo.svg'>]
B-->C[<img src="https://mermaid.js.org/mermaid-logo.svg"> more text <img src='https://mermaid.js.org/mermaid-logo.svg'>]
B-->D(<img src='https://mermaid.js.org/mermaid-logo.svg'> some text)
B-->E(plain)`,
{}
);
});
it('4439: Should render the graph even if some images are missing', () => {
imgSnapshotTest(
`flowchart TD
B[<img>]
B-->C[<img>]`,
{}
);
});
it('5064: Should render when subgraph child has links to outside node and subgraph', () => {
imgSnapshotTest(
`flowchart TB
Out --> In
subgraph Sub
In
end
Sub --> In`
);
});
it('5059: Should render when subgraph contains only subgraphs, has link to outside and itself is part of a link', () => {
imgSnapshotTest(
`flowchart
subgraph Main
subgraph Child1
Node1
Node2
end
subgraph Child2
Node3
Node4
end
end
Main --> Out1
Child2 --> Out2`
);
});
describe('Markdown strings flowchart (#4220)', () => {
describe('html labels', () => {
it('With styling and classes', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": true}} }%%
flowchart LR
A:::someclass --> B["\`The **cat** in the hat\`"]:::someclass
id1(Start)-->id2(Stop)
style id1 fill:#f9f,stroke:#333,stroke-width:4px
style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
classDef someclass fill:#f96
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('With formatting in a node', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": true}} }%%
flowchart LR
a{"\`The **cat** in the hat\`"} -- 1o --> b
a -- 2o --> c
a -- 3o --> d
g --2i--> a
d --1i--> a
h --3i -->a
b --> d(The dog in the hog)
c --> d
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('New line in node and formatted edge label', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": true}} }%%
flowchart LR
b("\`The dog in **the** hog.(1)
NL\`") --"\`1o **bold**\`"--> c
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('Wrapping long text with a new line', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": true}} }%%
flowchart LR
b("\`The dog in **the** hog.(1).. a a a a *very long text* about it
Word!
Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. \`") --> c
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('Sub graphs and markdown strings', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": true}} }%%
flowchart LR
subgraph "One"
a("\`The **cat**
in the hat\`") -- "1o" --> b{{"\`The **dog** in the hog\`"}}
end
subgraph "\`**Two**\`"
c("\`The **cat**
in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog")
end
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
});
describe('svg text labels', () => {
it('With styling and classes', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart LR
A:::someclass --> B["\`The **cat** in the hat\`"]:::someclass
id1(Start)-->id2(Stop)
style id1 fill:#f9f,stroke:#333,stroke-width:4px
style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
classDef someclass fill:#f96
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('With formatting in a node', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart LR
a{"\`The **cat** in the hat\`"} -- 1o --> b
a -- 2o --> c
a -- 3o --> d
g --2i--> a
d --1i--> a
h --3i -->a
b --> d(The dog in the hog)
c --> d
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('New line in node and formatted edge label', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart LR
b("\`The dog in **the** hog.(1)
NL\`") --"\`1o **bold**\`"--> c
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('Wrapping long text with a new line', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart LR
b("\`The dog in **the** hog.(1).. a a a a *very long text* about it
Word!
Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. \`") --> c
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('Sub graphs and markdown strings', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart LR
subgraph "One"
a("\`The **cat**
in the hat\`") -- "1o" --> b{{"\`The **dog** in the hog\`"}}
end
subgraph "\`**Two**\`"
c("\`The **cat**
in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog")
end
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
});
});
describe('Subgraph title margins', () => {
it('Should render subgraphs with title margins set (LR)', () => {
imgSnapshotTest(
`flowchart LR
subgraph TOP
direction TB
subgraph B1
direction RL
i1 -->f1
end
subgraph B2
direction BT
i2 -->f2
end
end
A --> TOP --> B
B1 --> B2
`,
{ flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } } }
);
});
it('Should render subgraphs with title margins set (TD)', () => {
imgSnapshotTest(
`flowchart TD
subgraph TOP
direction LR
subgraph B1
direction RL
i1 -->f1
end
subgraph B2
direction BT
i2 -->f2
end
end
A --> TOP --> B
B1 --> B2
`,
{ flowchart: { subGraphTitleMargin: { top: 8, bottom: 16 } } }
);
});
it('Should render subgraphs with title margins set (LR) and htmlLabels set to false', () => {
imgSnapshotTest(
`flowchart LR
subgraph TOP
direction TB
subgraph B1
direction RL
i1 -->f1
end
subgraph B2
direction BT
i2 -->f2
end
end
A --> TOP --> B
B1 --> B2
`,
{
htmlLabels: false,
flowchart: { htmlLabels: false, subGraphTitleMargin: { top: 10, bottom: 5 } },
}
);
});
it('Should render subgraphs with title margins and edge labels', () => {
imgSnapshotTest(
`flowchart LR
subgraph TOP
direction TB
subgraph B1
direction RL
i1 --lb1-->f1
end
subgraph B2
direction BT
i2 --lb2-->f2
end
end
A --lb3--> TOP --lb4--> B
B1 --lb5--> B2
`,
{ flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } } }
);
});
});
});

View File

@@ -1,4 +1,4 @@
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
import { imgSnapshotTest, renderGraph } from '../../helpers/util';
describe('Graph', () => {
it('1: should render a simple flowchart no htmlLabels', () => {
@@ -891,27 +891,4 @@ graph TD
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('66: apply class called default on node called default', () => {
imgSnapshotTest(
`
graph TD
classDef default fill:#a34,stroke:#000,stroke-width:4px,color:#fff
hello --> default
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('67: should be able to style default node independently', () => {
imgSnapshotTest(
`
flowchart TD
classDef default fill:#a34
hello --> default
style default stroke:#000,stroke-width:4px
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
});

View File

@@ -1,4 +1,4 @@
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
describe('Gantt diagram', () => {
beforeEach(() => {
@@ -133,24 +133,6 @@ describe('Gantt diagram', () => {
);
});
it('should default to showing today marker', () => {
// This test only works if the environment thinks today is 1010-10-10
imgSnapshotTest(
`
gantt
title Show today marker (vertical line should be visible)
dateFormat YYYY-MM-DD
axisFormat %d
%% Should default to being on
%% todayMarker on
section Section1
Yesterday: 1010-10-09, 1d
Today: 1010-10-10, 1d
`,
{}
);
});
it('should hide today marker', () => {
imgSnapshotTest(
`
@@ -160,8 +142,7 @@ describe('Gantt diagram', () => {
axisFormat %d
todayMarker off
section Section1
Yesterday: 1010-10-09, 1d
Today: 1010-10-10, 1d
Today: 1, -1h
`,
{}
);
@@ -176,8 +157,7 @@ describe('Gantt diagram', () => {
axisFormat %d
todayMarker stroke-width:5px,stroke:#00f,opacity:0.5
section Section1
Yesterday: 1010-10-09, 1d
Today: 1010-10-10, 1d
Today: 1, -1h
`,
{}
);
@@ -245,10 +225,7 @@ describe('Gantt diagram', () => {
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
expect(maxWidthValue).to.be.within(
Cypress.config().viewportWidth * 0.95,
Cypress.config().viewportWidth * 1.05
);
expect(maxWidthValue).to.be.within(984 * 0.95, 984 * 1.05);
});
});
@@ -288,11 +265,11 @@ describe('Gantt diagram', () => {
{ gantt: { useMaxWidth: false } }
);
cy.get('svg').should((svg) => {
// const height = parseFloat(svg.attr('height'));
const width = parseFloat(svg.attr('width'));
expect(width).to.be.within(
Cypress.config().viewportWidth * 0.95,
Cypress.config().viewportWidth * 1.05
);
// use within because the absolute value can be slightly different depending on the environment ±5%
// expect(height).to.be.within(484 * 0.95, 484 * 1.05);
expect(width).to.be.within(984 * 0.95, 984 * 1.05);
expect(svg).to.not.have.attr('style');
});
});
@@ -333,48 +310,6 @@ describe('Gantt diagram', () => {
);
});
it('should render a gantt diagram with tick is 2 milliseconds', () => {
imgSnapshotTest(
`
gantt
title A Gantt Diagram
dateFormat SSS
axisFormat %Lms
tickInterval 2millisecond
excludes weekends
section Section
A task : a1, 000, 6ms
Another task : after a1, 6ms
section Another
Task in sec : a2, 006, 3ms
another task : 3ms
`,
{}
);
});
it('should render a gantt diagram with tick is 2 seconds', () => {
imgSnapshotTest(
`
gantt
title A Gantt Diagram
dateFormat ss
axisFormat %Ss
tickInterval 2second
excludes weekends
section Section
A task : a1, 00, 6s
Another task : after a1, 6s
section Another
Task in sec : 06, 3s
another task : 3s
`,
{}
);
});
it('should render a gantt diagram with tick is 15 minutes', () => {
imgSnapshotTest(
`
@@ -459,28 +394,6 @@ describe('Gantt diagram', () => {
);
});
it('should render a gantt diagram with tick is 1 week, with the day starting on monday', () => {
imgSnapshotTest(
`
gantt
title A Gantt Diagram
dateFormat YYYY-MM-DD
axisFormat %m-%d
tickInterval 1week
weekday monday
excludes weekends
section Section
A task : a1, 2022-10-01, 30d
Another task : after a1, 20d
section Another
Task in sec : 2022-10-20, 12d
another task : 24d
`,
{}
);
});
it('should render a gantt diagram with tick is 1 month', () => {
imgSnapshotTest(
`
@@ -522,65 +435,4 @@ describe('Gantt diagram', () => {
{ gantt: { topAxis: true } }
);
});
// TODO: fix it
//
// This test is skipped deliberately
// because it fails and blocks our development pipeline
// It was added as an attempt to fix gantt performance issues
//
// https://github.com/mermaid-js/mermaid/issues/3274
//
it.skip('should render a gantt diagram with very large intervals, skipping excludes if interval > 5 years', () => {
imgSnapshotTest(
`gantt
title A long Gantt Diagram
dateFormat YYYY-MM-DD
axisFormat %m-%d
tickInterval 1day
excludes weekends
section Section
A task : a1, 9999-10-01, 30d
Another task : after a1, 20d
section Another
Task in sec : 2022-10-20, 12d
another task : 24d
`
);
});
it('should render when compact is true', () => {
imgSnapshotTest(
`
---
displayMode: compact
---
gantt
title GANTT compact
dateFormat HH:mm:ss
axisFormat %Hh%M
section DB Clean
Clean: 12:00:00, 10m
Clean: 12:30:00, 12m
Clean: 13:00:00, 8m
Clean: 13:30:00, 9m
Clean: 14:00:00, 13m
Clean: 14:30:00, 10m
Clean: 15:00:00, 11m
section Sessions
A: 12:00:00, 63m
B: 12:30:00, 12m
C: 13:05:00, 12m
D: 13:06:00, 33m
E: 13:15:00, 55m
F: 13:20:00, 12m
G: 13:32:00, 18m
H: 13:50:00, 20m
I: 14:10:00, 10m
`,
{}
);
});
});

View File

@@ -1,4 +1,4 @@
import { imgSnapshotTest } from '../../helpers/util.ts';
import { imgSnapshotTest } from '../../helpers/util.js';
describe('Git Graph diagram', () => {
it('1: should render a simple gitgraph with commit on main branch', () => {
@@ -26,7 +26,7 @@ describe('Git Graph diagram', () => {
`gitGraph
commit id: "Normal Commit"
commit id: "Reverse Commit" type: REVERSE
commit id: "Highlight Commit" type: HIGHLIGHT
commit id: "Hightlight Commit" type: HIGHLIGHT
`,
{}
);
@@ -36,7 +36,7 @@ describe('Git Graph diagram', () => {
`gitGraph
commit id: "Normal Commit with tag" tag: "v1.0.0"
commit id: "Reverse Commit with tag" type: REVERSE tag: "RC_1"
commit id: "Highlight Commit" type: HIGHLIGHT tag: "8.8.4"
commit id: "Hightlight 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 branches & overriding variables', () => {
it('8: should render a simple gitgraph with more than 8 branchs & overriding variables', () => {
imgSnapshotTest(
`%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': {
'gitBranchLabel0': '#ffffff',
@@ -333,614 +333,4 @@ gitGraph
{}
);
});
it('15: should render a simple gitgraph with commit on main branch | Vertical Branch', () => {
imgSnapshotTest(
`gitGraph TB:
commit id: "1"
commit id: "2"
commit id: "3"
`,
{}
);
});
it('16: should render a simple gitgraph with commit on main branch with Id | Vertical Branch', () => {
imgSnapshotTest(
`gitGraph TB:
commit id: "One"
commit id: "Two"
commit id: "Three"
`,
{}
);
});
it('17: should render a simple gitgraph with different commitTypes on main branch | Vertical Branch', () => {
imgSnapshotTest(
`gitGraph TB:
commit id: "Normal Commit"
commit id: "Reverse Commit" type: REVERSE
commit id: "Highlight Commit" type: HIGHLIGHT
`,
{}
);
});
it('18: should render a simple gitgraph with tags commitTypes on main branch | Vertical Branch', () => {
imgSnapshotTest(
`gitGraph TB:
commit id: "Normal Commit with tag" tag: "v1.0.0"
commit id: "Reverse Commit with tag" type: REVERSE tag: "RC_1"
commit id: "Highlight Commit" type: HIGHLIGHT tag: "8.8.4"
`,
{}
);
});
it('19: should render a simple gitgraph with two branches | Vertical Branch', () => {
imgSnapshotTest(
`gitGraph TB:
commit id: "1"
commit id: "2"
branch develop
checkout develop
commit id: "3"
commit id: "4"
checkout main
commit id: "5"
commit id: "6"
`,
{}
);
});
it('20: should render a simple gitgraph with two branches and merge commit | Vertical Branch', () => {
imgSnapshotTest(
`gitGraph TB:
commit id: "1"
commit id: "2"
branch develop
checkout develop
commit id: "3"
commit id: "4"
checkout main
merge develop
commit id: "5"
commit id: "6"
`,
{}
);
});
it('21: should render a simple gitgraph with three branches and tagged merge commit | Vertical Branch', () => {
imgSnapshotTest(
`gitGraph TB:
commit id: "1"
commit id: "2"
branch nice_feature
checkout nice_feature
commit id: "3"
checkout main
commit id: "4"
checkout nice_feature
branch very_nice_feature
checkout very_nice_feature
commit id: "5"
checkout main
commit id: "6"
checkout nice_feature
commit id: "7"
checkout main
merge nice_feature id: "12345" tag: "my merge commit"
checkout very_nice_feature
commit id: "8"
checkout main
commit id: "9"
`,
{}
);
});
it('22: should render a simple gitgraph with more than 8 branches & overriding variables | Vertical Branch', () => {
imgSnapshotTest(
`%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': {
'gitBranchLabel0': '#ffffff',
'gitBranchLabel1': '#ffffff',
'gitBranchLabel2': '#ffffff',
'gitBranchLabel3': '#ffffff',
'gitBranchLabel4': '#ffffff',
'gitBranchLabel5': '#ffffff',
'gitBranchLabel6': '#ffffff',
'gitBranchLabel7': '#ffffff',
} } }%%
gitGraph TB:
checkout main
branch branch1
branch branch2
branch branch3
branch branch4
branch branch5
branch branch6
branch branch7
branch branch8
branch branch9
checkout branch1
commit id: "1"
`,
{}
);
});
it('23: should render a simple gitgraph with rotated labels | Vertical Branch', () => {
imgSnapshotTest(
`%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'gitGraph': {
'rotateCommitLabel': true
} } }%%
gitGraph TB:
commit id: "75f7219e83b321cd3fdde7dcf83bc7c1000a6828"
commit id: "0db4784daf82736dec4569e0dc92980d328c1f2e"
commit id: "7067e9973f9eaa6cd4a4b723c506d1eab598e83e"
commit id: "66972321ad6c199013b5b31f03b3a86fa3f9817d"
`,
{}
);
});
it('24: should render a simple gitgraph with horizontal labels | Vertical Branch', () => {
imgSnapshotTest(
`%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'gitGraph': {
'rotateCommitLabel': false
} } }%%
gitGraph TB:
commit id: "Alpha"
commit id: "Beta"
commit id: "Gamma"
commit id: "Delta"
`,
{}
);
});
it('25: should render a simple gitgraph with cherry pick commit | Vertical Branch', () => {
imgSnapshotTest(
`
gitGraph TB:
commit id: "ZERO"
branch develop
commit id:"A"
checkout main
commit id:"ONE"
checkout develop
commit id:"B"
checkout main
commit id:"TWO"
cherry-pick id:"A"
commit id:"THREE"
checkout develop
commit id:"C"
`,
{}
);
});
it('26: should render a gitgraph with cherry pick commit with custom tag | Vertical Branch', () => {
imgSnapshotTest(
`
gitGraph TB:
commit id: "ZERO"
branch develop
commit id:"A"
checkout main
commit id:"ONE"
checkout develop
commit id:"B"
checkout main
commit id:"TWO"
cherry-pick id:"A" tag: "snapshot"
commit id:"THREE"
checkout develop
commit id:"C"
`,
{}
);
});
it('27: should render a gitgraph with cherry pick commit with no tag | Vertical Branch', () => {
imgSnapshotTest(
`
gitGraph TB:
commit id: "ZERO"
branch develop
commit id:"A"
checkout main
commit id:"ONE"
checkout develop
commit id:"B"
checkout main
commit id:"TWO"
cherry-pick id:"A" tag: ""
commit id:"THREE"
checkout develop
commit id:"C"
`,
{}
);
});
it('28: should render a simple gitgraph with two cherry pick commit | Vertical Branch', () => {
imgSnapshotTest(
`
gitGraph TB:
commit id: "ZERO"
branch develop
commit id:"A"
checkout main
commit id:"ONE"
checkout develop
commit id:"B"
branch featureA
commit id:"FIX"
commit id: "FIX-2"
checkout main
commit id:"TWO"
cherry-pick id:"A"
commit id:"THREE"
cherry-pick id:"FIX"
checkout develop
commit id:"C"
merge featureA
`,
{}
);
});
it('29: should render commits for more than 8 branches | Vertical Branch', () => {
imgSnapshotTest(
`
gitGraph TB:
checkout main
%% Make sure to manually set the ID of all commits, for consistent visual tests
commit id: "1-abcdefg"
checkout main
branch branch1
commit id: "2-abcdefg"
checkout main
merge branch1
branch branch2
commit id: "3-abcdefg"
checkout main
merge branch2
branch branch3
commit id: "4-abcdefg"
checkout main
merge branch3
branch branch4
commit id: "5-abcdefg"
checkout main
merge branch4
branch branch5
commit id: "6-abcdefg"
checkout main
merge branch5
branch branch6
commit id: "7-abcdefg"
checkout main
merge branch6
branch branch7
commit id: "8-abcdefg"
checkout main
merge branch7
branch branch8
commit id: "9-abcdefg"
checkout main
merge branch8
branch branch9
commit id: "10-abcdefg"
`,
{}
);
});
it('30: should render a simple gitgraph with three branches,custom merge commit id,tag,type | Vertical Branch', () => {
imgSnapshotTest(
`gitGraph TB:
commit id: "1"
commit id: "2"
branch nice_feature
checkout nice_feature
commit id: "3"
checkout main
commit id: "4"
checkout nice_feature
branch very_nice_feature
checkout very_nice_feature
commit id: "5"
checkout main
commit id: "6"
checkout nice_feature
commit id: "7"
checkout main
merge nice_feature id: "customID" tag: "customTag" type: REVERSE
checkout very_nice_feature
commit id: "8"
checkout main
commit id: "9"
`,
{}
);
});
it('31: should render a simple gitgraph with a title | Vertical Branch', () => {
imgSnapshotTest(
`---
title: simple gitGraph
---
gitGraph TB:
commit id: "1-abcdefg"
`,
{}
);
});
it('32: should render a simple gitgraph overlapping commits | Vertical Branch', () => {
imgSnapshotTest(
`gitGraph TB:
commit id:"s1"
commit id:"s2"
branch branch1
commit id:"s3"
commit id:"s4"
checkout main
commit id:"s5"
checkout branch1
commit id:"s6"
commit id:"s7"
merge main
`,
{}
);
});
it('33: should render a simple gitgraph overlapping commits', () => {
imgSnapshotTest(
`gitGraph
commit id:"s1"
commit id:"s2"
branch branch1
commit id:"s3"
commit id:"s4"
checkout main
commit id:"s5"
checkout branch1
commit id:"s6"
commit id:"s7"
merge main
`,
{}
);
});
it('34: should render a simple gitgraph with two branches from same commit', () => {
imgSnapshotTest(
`gitGraph
commit id:"1-abcdefg"
commit id:"2-abcdefg"
branch feature-001
commit id:"3-abcdefg"
commit id:"4-abcdefg"
checkout main
branch feature-002
commit id:"5-abcdefg"
checkout feature-001
merge feature-002
`,
{}
);
});
it('35: should render a simple gitgraph with two branches from same commit | Vertical Branch', () => {
imgSnapshotTest(
`gitGraph TB:
commit id:"1-abcdefg"
commit id:"2-abcdefg"
branch feature-001
commit id:"3-abcdefg"
commit id:"4-abcdefg"
checkout main
branch feature-002
commit id:"5-abcdefg"
checkout feature-001
merge feature-002
`,
{}
);
});
it('36: should render GitGraph with branch that is not used immediately', () => {
imgSnapshotTest(
`gitGraph LR:
commit id:"1-abcdefg"
branch x
checkout main
commit id:"2-abcdefg"
checkout x
commit id:"3-abcdefg"
checkout main
merge x
`,
{}
);
});
it('37: should render GitGraph with branch that is not used immediately | Vertical Branch', () => {
imgSnapshotTest(
`gitGraph TB:
commit id:"1-abcdefg"
branch x
checkout main
commit id:"2-abcdefg"
checkout x
commit id:"3-abcdefg"
checkout main
merge x
`,
{}
);
});
it('38: should render GitGraph with branch and sub-branch neither of which used immediately', () => {
imgSnapshotTest(
`gitGraph LR:
commit id:"1-abcdefg"
branch x
checkout main
commit id:"2-abcdefg"
checkout x
commit id:"3-abcdefg"
checkout main
merge x
checkout x
branch y
checkout x
commit id:"4-abcdefg"
checkout y
commit id:"5-abcdefg"
checkout x
merge y
`,
{}
);
});
it('39: should render GitGraph with branch and sub-branch neither of which used immediately | Vertical Branch', () => {
imgSnapshotTest(
`gitGraph TB:
commit id:"1-abcdefg"
branch x
checkout main
commit id:"2-abcdefg"
checkout x
commit id:"3-abcdefg"
checkout main
merge x
checkout x
branch y
checkout x
commit id:"4-abcdefg"
checkout y
commit id:"5-abcdefg"
checkout x
merge y
`,
{}
);
});
it('40: should render a simple gitgraph with cherry pick merge commit', () => {
imgSnapshotTest(
`gitGraph
commit id: "ZERO"
branch feature
branch release
checkout feature
commit id: "A"
commit id: "B"
checkout main
merge feature id: "M"
checkout release
cherry-pick id: "M" parent:"B"`
);
});
it('41: should render default GitGraph with parallelCommits set to false', () => {
imgSnapshotTest(
`gitGraph
commit id:"1-abcdefg"
commit id:"2-abcdefg"
branch develop
commit id:"3-abcdefg"
commit id:"4-abcdefg"
checkout main
branch feature
commit id:"5-abcdefg"
commit id:"6-abcdefg"
checkout main
commit id:"7-abcdefg"
commit id:"8-abcdefg"
`,
{ gitGraph: { parallelCommits: false } }
);
});
it('42: should render GitGraph with parallel commits', () => {
imgSnapshotTest(
`gitGraph
commit id:"1-abcdefg"
commit id:"2-abcdefg"
branch develop
commit id:"3-abcdefg"
commit id:"4-abcdefg"
checkout main
branch feature
commit id:"5-abcdefg"
commit id:"6-abcdefg"
checkout main
commit id:"7-abcdefg"
commit id:"8-abcdefg"
`,
{ gitGraph: { parallelCommits: true } }
);
});
it('43: should render GitGraph with parallel commits | Vertical Branch', () => {
imgSnapshotTest(
`gitGraph TB:
commit id:"1-abcdefg"
commit id:"2-abcdefg"
branch develop
commit id:"3-abcdefg"
commit id:"4-abcdefg"
checkout main
branch feature
commit id:"5-abcdefg"
commit id:"6-abcdefg"
checkout main
commit id:"7-abcdefg"
commit id:"8-abcdefg"
`,
{ gitGraph: { parallelCommits: true } }
);
});
it('44: should render GitGraph with unconnected branches and no parallel commits', () => {
imgSnapshotTest(
`gitGraph
branch dev
branch v2
branch feat
commit id:"1-abcdefg"
commit id:"2-abcdefg"
checkout main
commit id:"3-abcdefg"
checkout dev
commit id:"4-abcdefg"
checkout v2
commit id:"5-abcdefg"
checkout main
commit id:"6-abcdefg"
`,
{ gitGraph: { parallelCommits: false } }
);
});
it('45: should render GitGraph with unconnected branches and parallel commits', () => {
imgSnapshotTest(
`gitGraph
branch dev
branch v2
branch feat
commit id:"1-abcdefg"
commit id:"2-abcdefg"
checkout main
commit id:"3-abcdefg"
checkout dev
commit id:"4-abcdefg"
checkout v2
commit id:"5-abcdefg"
checkout main
commit id:"6-abcdefg"
`,
{ gitGraph: { parallelCommits: true } }
);
});
it('46: should render GitGraph with unconnected branches and parallel commits | Vertical Branch', () => {
imgSnapshotTest(
`gitGraph TB:
branch dev
branch v2
branch feat
commit id:"1-abcdefg"
commit id:"2-abcdefg"
checkout main
commit id:"3-abcdefg"
checkout dev
commit id:"4-abcdefg"
checkout v2
commit id:"5-abcdefg"
checkout main
commit id:"6-abcdefg"
`,
{ gitGraph: { parallelCommits: true } }
);
});
});

View File

@@ -0,0 +1,13 @@
import { imgSnapshotTest } from '../../helpers/util.js';
describe('Sequencediagram', () => {
it('should render a simple info diagrams', () => {
imgSnapshotTest(
`
info
showInfo
`,
{}
);
});
});

View File

@@ -1,11 +0,0 @@
import { imgSnapshotTest } from '../../helpers/util.ts';
describe('info diagram', () => {
it('should handle an info definition', () => {
imgSnapshotTest(`info`);
});
it('should handle an info definition with showInfo', () => {
imgSnapshotTest(`info showInfo`);
});
});

View File

@@ -1,4 +1,4 @@
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
describe('User journey diagram', () => {
it('Simple test', () => {

View File

@@ -1,10 +0,0 @@
import { urlSnapshotTest } from '../../helpers/util.ts';
describe('Marker Unique IDs Per Diagram', () => {
it('should render a blue arrow tip in second digram', () => {
urlSnapshotTest('http://localhost:9000/marker_unique_id.html', {
logLevel: 1,
flowchart: { htmlLabels: false },
});
});
});

View File

@@ -1,4 +1,4 @@
import { imgSnapshotTest } from '../../helpers/util.ts';
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
/**
* Check whether the SVG Element has a Mindmap root
@@ -52,17 +52,6 @@ root[A root with a long text that wraps to keep the node size in check]
);
});
it('a root with wrapping text and long words that exceed width', () => {
imgSnapshotTest(
`mindmap
root[A few smaller words but then averylongsetofcharacterswithoutwhitespacetoseparate that we expect to wrapontonextlinesandnotexceedwidthparameters]
`,
{},
undefined,
shouldHaveRoot
);
});
it('a root with an icon', () => {
imgSnapshotTest(
`mindmap
@@ -169,6 +158,7 @@ mindmap
undefined,
shouldHaveRoot
);
cy.get('svg');
});
it('rounded rect shape', () => {
imgSnapshotTest(
@@ -182,6 +172,7 @@ mindmap
undefined,
shouldHaveRoot
);
cy.get('svg');
});
it('circle shape', () => {
imgSnapshotTest(
@@ -195,6 +186,7 @@ mindmap
undefined,
shouldHaveRoot
);
cy.get('svg');
});
it('default shape', () => {
imgSnapshotTest(
@@ -206,6 +198,7 @@ mindmap
undefined,
shouldHaveRoot
);
cy.get('svg');
});
it('adding children', () => {
imgSnapshotTest(
@@ -219,6 +212,7 @@ mindmap
undefined,
shouldHaveRoot
);
cy.get('svg');
});
it('adding grand children', () => {
imgSnapshotTest(
@@ -233,18 +227,7 @@ mindmap
undefined,
shouldHaveRoot
);
});
describe('Markdown strings mindmaps (#4220)', () => {
it('Formatted label with linebreak and a wrapping label and emojis', () => {
imgSnapshotTest(
`mindmap
id1[\`**Start** with
a second line 😎\`]
id2[\`The dog in **the** hog... a *very long text* about it
Word!\`]
`
);
});
cy.get('svg');
});
/* The end */
});

View File

@@ -0,0 +1,78 @@
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
describe('Pie Chart', () => {
it('should render a simple pie diagram', () => {
imgSnapshotTest(
`
pie title Sports in Sweden
"Bandy" : 40
"Ice-Hockey" : 80
"Football" : 90
`,
{}
);
cy.get('svg');
});
it('should render a simple pie diagram with long labels', () => {
imgSnapshotTest(
`
pie title NETFLIX
"Time spent looking for movie" : 90
"Time spent watching it" : 10
`,
{}
);
cy.get('svg');
});
it('should render a simple pie diagram with capital letters for labels', () => {
imgSnapshotTest(
`
pie title What Voldemort doesn't have?
"FRIENDS" : 2
"FAMILY" : 3
"NOSE" : 45
`,
{}
);
cy.get('svg');
});
it('should render a pie diagram when useMaxWidth is true (default)', () => {
renderGraph(
`
pie title Sports in Sweden
"Bandy" : 40
"Ice-Hockey" : 80
"Football" : 90
`,
{ pie: { useMaxWidth: true } }
);
cy.get('svg').should((svg) => {
expect(svg).to.have.attr('width', '100%');
// expect(svg).to.have.attr('height');
// const height = parseFloat(svg.attr('height'));
// expect(height).to.eq(450);
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
expect(maxWidthValue).to.eq(984);
});
});
it('should render a pie diagram when useMaxWidth is false', () => {
renderGraph(
`
pie title Sports in Sweden
"Bandy" : 40
"Ice-Hockey" : 80
"Football" : 90
`,
{ pie: { useMaxWidth: false } }
);
cy.get('svg').should((svg) => {
// const height = parseFloat(svg.attr('height'));
const width = parseFloat(svg.attr('width'));
// expect(height).to.eq(450);
expect(width).to.eq(984);
expect(svg).to.not.have.attr('style');
});
});
});

View File

@@ -1,85 +0,0 @@
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
describe('pie chart', () => {
it('should render a simple pie diagram', () => {
imgSnapshotTest(
`pie title Sports in Sweden
"Bandy": 40
"Ice-Hockey": 80
"Football": 90
`
);
});
it('should render a simple pie diagram with long labels', () => {
imgSnapshotTest(
`pie title NETFLIX
"Time spent looking for movie": 90
"Time spent watching it": 10
`
);
});
it('should render a simple pie diagram with capital letters for labels', () => {
imgSnapshotTest(
`pie title What Voldemort doesn't have?
"FRIENDS": 2
"FAMILY": 3
"NOSE": 45
`
);
});
it('should render a pie diagram when useMaxWidth is true (default)', () => {
renderGraph(
`pie title Sports in Sweden
"Bandy": 40
"Ice-Hockey": 80
"Football": 90
`,
{ pie: { useMaxWidth: true } }
);
cy.get('svg').should((svg) => {
expect(svg).to.have.attr('width', '100%');
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
expect(maxWidthValue).to.be.within(590, 600); // depends on installed fonts: 596.2 on my PC, 597.5 on CI
});
});
it('should render a pie diagram when useMaxWidth is false', () => {
renderGraph(
`pie title Sports in Sweden
"Bandy": 40
"Ice-Hockey": 80
"Football": 90
`,
{ pie: { useMaxWidth: false } }
);
cy.get('svg').should((svg) => {
const width = parseFloat(svg.attr('width'));
expect(width).to.be.within(590, 600); // depends on installed fonts: 596.2 on my PC, 597.5 on CI
expect(svg).to.not.have.attr('style');
});
});
it('should render a pie diagram when textPosition is setted', () => {
imgSnapshotTest(
`pie
"Dogs": 50
"Cats": 25
`,
{ logLevel: 1, pie: { textPosition: 0.9 } }
);
});
it('should render a pie diagram with showData', () => {
imgSnapshotTest(
`pie showData
"Dogs": 50
"Cats": 25
`
);
});
});

View File

@@ -1,229 +0,0 @@
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
describe('Quadrant Chart', () => {
it('should render if only chart type is provided', () => {
imgSnapshotTest(
`
quadrantChart
`,
{}
);
cy.get('svg');
});
it('should render a complete quadrant chart', () => {
imgSnapshotTest(
`
quadrantChart
title Reach and engagement of campaigns
x-axis Low Reach --> High Reach
y-axis Low Engagement --> High Engagement
quadrant-1 We should expand
quadrant-2 Need to promote
quadrant-3 Re-evaluate
quadrant-4 May be improved
Campaign A: [0.3, 0.6]
Campaign B: [0.45, 0.23]
Campaign C: [0.57, 0.69]
Campaign D: [0.78, 0.34]
Campaign E: [0.40, 0.34]
Campaign F: [0.35, 0.78]
`,
{}
);
cy.get('svg');
});
it('should render without points', () => {
imgSnapshotTest(
`
quadrantChart
title Reach and engagement of campaigns
x-axis Low Reach --> High Reach
y-axis Low Engagement --> High Engagement
quadrant-1 We should expand
quadrant-2 Need to promote
quadrant-3 Re-evaluate
quadrant-4 May be improved
`,
{}
);
cy.get('svg');
});
it('should able to render y-axix on right side', () => {
imgSnapshotTest(
`
%%{init: {"quadrantChart": {"yAxisPosition": "right"}}}%%
quadrantChart
title Reach and engagement of campaigns
x-axis Low Reach --> High Reach
y-axis Low Engagement --> High Engagement
quadrant-1 We should expand
quadrant-2 Need to promote
quadrant-3 Re-evaluate
quadrant-4 May be improved
`,
{}
);
cy.get('svg');
});
it('should able to render x-axix on bottom', () => {
imgSnapshotTest(
`
%%{init: {"quadrantChart": {"xAxisPosition": "bottom"}}}%%
quadrantChart
title Reach and engagement of campaigns
x-axis Low Reach --> High Reach
y-axis Low Engagement --> High Engagement
quadrant-1 We should expand
quadrant-2 Need to promote
quadrant-3 Re-evaluate
quadrant-4 May be improved
`,
{}
);
cy.get('svg');
});
it('should able to render x-axix on bottom and y-axis on right', () => {
imgSnapshotTest(
`
%%{init: {"quadrantChart": {"xAxisPosition": "bottom", "yAxisPosition": "right"}}}%%
quadrantChart
title Reach and engagement of campaigns
x-axis Low Reach --> High Reach
y-axis Low Engagement --> High Engagement
quadrant-1 We should expand
quadrant-2 Need to promote
quadrant-3 Re-evaluate
quadrant-4 May be improved
`,
{}
);
cy.get('svg');
});
it('should render without title', () => {
imgSnapshotTest(
`
quadrantChart
x-axis Low Reach --> High Reach
y-axis Low Engagement --> High Engagement
quadrant-1 We should expand
quadrant-2 Need to promote
quadrant-3 Re-evaluate
quadrant-4 May be improved
`,
{}
);
cy.get('svg');
});
it('should use all the config', () => {
imgSnapshotTest(
`
%%{init: {"quadrantChart": {"chartWidth": 600, "chartHeight": 600, "titlePadding": 20, "titleFontSize": 10, "quadrantPadding": 20, "quadrantTextTopPadding": 40, "quadrantLabelFontSize": 20, "quadrantInternalBorderStrokeWidth": 3, "quadrantExternalBorderStrokeWidth": 5, "xAxisLabelPadding": 20, "xAxisLabelFontSize": 20, "yAxisLabelPadding": 20, "yAxisLabelFontSize": 20, "pointTextPadding": 20, "pointLabelFontSize": 20, "pointRadius": 10 }}}%%
quadrantChart
title Reach and engagement of campaigns
x-axis Low Reach --> High Reach
y-axis Low Engagement --> High Engagement
quadrant-1 We should expand
quadrant-2 Need to promote
quadrant-3 Re-evaluate
quadrant-4 May be improved
Campaign A: [0.3, 0.6]
Campaign B: [0.45, 0.23]
Campaign C: [0.57, 0.69]
Campaign D: [0.78, 0.34]
Campaign E: [0.40, 0.34]
Campaign F: [0.35, 0.78]
`,
{}
);
cy.get('svg');
});
it('should use all the theme variable', () => {
imgSnapshotTest(
`
%%{init: {"themeVariables": {"quadrant1Fill": "#b4dcff","quadrant2Fill": "#fef0ff", "quadrant3Fill": "#fffaf0", "quadrant4Fill": "#f0fff2", "quadrant1TextFill": "#ff0000", "quadrant2TextFill": "#2d00df", "quadrant3TextFill": "#00ffda", "quadrant4TextFill": "#e68300", "quadrantPointFill": "#0149ff", "quadrantPointTextFill": "#dc00ff", "quadrantXAxisTextFill": "#ffb500", "quadrantYAxisTextFill": "#fae604", "quadrantInternalBorderStrokeFill": "#3636f2", "quadrantExternalBorderStrokeFill": "#ff1010", "quadrantTitleFill": "#00ea19"} }}%%
quadrantChart
title Reach and engagement of campaigns
x-axis Low Reach --> High Reach
y-axis Low Engagement --> High Engagement
quadrant-1 We should expand
quadrant-2 Need to promote
quadrant-3 Re-evaluate
quadrant-4 May be improved
Campaign A: [0.3, 0.6]
Campaign B: [0.45, 0.23]
Campaign C: [0.57, 0.69]
Campaign D: [0.78, 0.34]
Campaign E: [0.40, 0.34]
Campaign F: [0.35, 0.78]
`,
{}
);
cy.get('svg');
});
it('should render x-axis labels in the center, if x-axis has two labels', () => {
imgSnapshotTest(
`
quadrantChart
title Reach and engagement of campaigns
x-axis Low Reach --> High Reach
y-axis Low Engagement
quadrant-1 We should expand
quadrant-2 Need to promote
quadrant-3 Re-evaluate
quadrant-4 May be improved
Campaign A: [0.3, 0.6]
Campaign B: [0.45, 0.23]
Campaign C: [0.57, 0.69]
Campaign D: [0.78, 0.34]
Campaign E: [0.40, 0.34]
Campaign F: [0.35, 0.78]
`,
{}
);
cy.get('svg');
});
it('should render y-axis labels in the center, if y-axis has two labels', () => {
imgSnapshotTest(
`
quadrantChart
title Reach and engagement of campaigns
x-axis Low Reach
y-axis Low Engagement --> High Engagement
quadrant-1 We should expand
quadrant-2 Need to promote
quadrant-3 Re-evaluate
quadrant-4 May be improved
Campaign A: [0.3, 0.6]
Campaign B: [0.45, 0.23]
Campaign C: [0.57, 0.69]
Campaign D: [0.78, 0.34]
Campaign E: [0.40, 0.34]
Campaign F: [0.35, 0.78]
`,
{}
);
cy.get('svg');
});
it('should render both axes labels on the left and bottom, if both axes have only one label', () => {
imgSnapshotTest(
`
quadrantChart
title Reach and engagement of campaigns
x-axis Reach -->
y-axis Engagement -->
quadrant-1 We should expand
quadrant-2 Need to promote
quadrant-3 Re-evaluate
quadrant-4 May be improved
Campaign A: [0.3, 0.6]
Campaign B: [0.45, 0.23]
Campaign C: [0.57, 0.69]
Campaign D: [0.78, 0.34]
Campaign E: [0.40, 0.34]
Campaign F: [0.35, 0.78]
`,
{}
);
cy.get('svg');
});
});

View File

@@ -1,4 +1,4 @@
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
describe('Requirement diagram', () => {
it('sample', () => {

View File

@@ -1,144 +0,0 @@
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
describe('Sankey Diagram', () => {
it('should render a simple example', () => {
imgSnapshotTest(
`
sankey-beta
sourceNode,targetNode,10
`,
{}
);
});
describe('when given a linkColor', function () {
this.beforeAll(() => {
cy.wrap(
`sankey-beta
a,b,10
`
).as('graph');
});
it('links should use hex color', function () {
renderGraph(this.graph, { sankey: { linkColor: '#636465' } });
cy.get('.link path').should((link) => {
expect(link.attr('stroke')).to.equal('#636465');
});
});
it('links should be the same color as source node', function () {
renderGraph(this.graph, { sankey: { linkColor: 'source' } });
cy.get('.link path').then((link) => {
cy.get('.node[id="node-1"] rect').should((node) =>
expect(link.attr('stroke')).to.equal(node.attr('fill'))
);
});
});
it('links should be the same color as target node', function () {
renderGraph(this.graph, { sankey: { linkColor: 'target' } });
cy.get('.link path').then((link) => {
cy.get('.node[id="node-2"] rect').should((node) =>
expect(link.attr('stroke')).to.equal(node.attr('fill'))
);
});
});
it('links must be gradient', function () {
renderGraph(this.graph, { sankey: { linkColor: 'gradient' } });
cy.get('.link path').should((link) => {
expect(link.attr('stroke')).to.equal('url(#linearGradient-3)');
});
});
});
describe('when given a nodeAlignment', function () {
this.beforeAll(() => {
cy.wrap(
`
sankey-beta
a,b,8
b,c,8
c,d,8
d,e,8
x,c,4
c,y,4
`
).as('graph');
});
this.afterEach(() => {
cy.get('.node[id="node-1"]').should((node) => {
expect(node.attr('x')).to.equal('0');
});
cy.get('.node[id="node-2"]').should((node) => {
expect(node.attr('x')).to.equal('100');
});
cy.get('.node[id="node-3"]').should((node) => {
expect(node.attr('x')).to.equal('200');
});
cy.get('.node[id="node-4"]').should((node) => {
expect(node.attr('x')).to.equal('300');
});
cy.get('.node[id="node-5"]').should((node) => {
expect(node.attr('x')).to.equal('400');
});
});
it('should justify nodes', function () {
renderGraph(this.graph, {
sankey: { nodeAlignment: 'justify', width: 410, useMaxWidth: false },
});
cy.get('.node[id="node-6"]').should((node) => {
expect(node.attr('x')).to.equal('0');
});
cy.get('.node[id="node-7"]').should((node) => {
expect(node.attr('x')).to.equal('400');
});
});
it('should align nodes left', function () {
renderGraph(this.graph, {
sankey: { nodeAlignment: 'left', width: 410, useMaxWidth: false },
});
cy.get('.node[id="node-6"]').should((node) => {
expect(node.attr('x')).to.equal('0');
});
cy.get('.node[id="node-7"]').should((node) => {
expect(node.attr('x')).to.equal('300');
});
});
it('should align nodes right', function () {
renderGraph(this.graph, {
sankey: { nodeAlignment: 'right', width: 410, useMaxWidth: false },
});
cy.get('.node[id="node-6"]').should((node) => {
expect(node.attr('x')).to.equal('100');
});
cy.get('.node[id="node-7"]').should((node) => {
expect(node.attr('x')).to.equal('400');
});
});
it('should center nodes', function () {
renderGraph(this.graph, {
sankey: { nodeAlignment: 'center', width: 410, useMaxWidth: false },
});
cy.get('.node[id="node-6"]').should((node) => {
expect(node.attr('x')).to.equal('100');
});
cy.get('.node[id="node-7"]').should((node) => {
expect(node.attr('x')).to.equal('300');
});
});
});
});

View File

@@ -1,44 +1,8 @@
/// <reference types="Cypress" />
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
import { imgSnapshotTest, renderGraph } from '../../helpers/util';
context('Sequence diagram', () => {
it('should render a sequence diagram with boxes', () => {
renderGraph(
`
sequenceDiagram
box LightGrey Alice and Bob
participant Alice
participant Bob
end
participant John as John<br/>Second Line
Alice ->> Bob: Hello Bob, how are you?
Bob-->>John: How about you John?
Bob--x Alice: I am good thanks!
Bob-x John: I am good thanks!
Note right of John: Bob thinks a long<br/>long time, so long<br/>that the text does<br/>not fit on a row.
Bob-->Alice: Checking with John...
alt either this
Alice->>John: Yes
else or this
Alice->>John: No
else or this will happen
Alice->John: Maybe
end
par this happens in parallel
Alice -->> Bob: Parallel message 1
and
Alice -->> John: Parallel message 2
end
`,
{ sequence: { useMaxWidth: false } }
);
cy.get('svg').should((svg) => {
const width = parseFloat(svg.attr('width'));
expect(width).to.be.within(830 * 0.95, 830 * 1.05);
expect(svg).to.not.have.attr('style');
});
});
it('should render a simple sequence diagram', () => {
imgSnapshotTest(
`
@@ -88,16 +52,6 @@ context('Sequence diagram', () => {
{}
);
});
it('should handle empty lines', () => {
imgSnapshotTest(
`
sequenceDiagram
Alice->>John: Hello John<br/>
John-->>Alice: Great<br/><br/>day!
`,
{}
);
});
it('should handle line breaks and wrap annotations', () => {
imgSnapshotTest(
`
@@ -126,109 +80,7 @@ context('Sequence diagram', () => {
loop Loopy
Bob->>Alice: Pasten
end `,
{
sequence: {
wrap: true,
},
}
);
});
it('should render a sequence diagram with par_over', () => {
imgSnapshotTest(
`
sequenceDiagram
participant Alice
participant Bob
participant John
par_over Section title
Alice ->> Bob: Message 1<br>Second line
Bob ->> John: Message 2
end
par_over Two line<br>section title
Note over Alice: Alice note
Note over Bob: Bob note<br>Second line
Note over John: John note
end
par_over Mixed section
Alice ->> Bob: Message 1
Note left of Bob: Alice/Bob Note
end
`
);
});
it('should render a sequence diagram with basic actor creation and destruction', () => {
imgSnapshotTest(
`
sequenceDiagram
Alice ->> Bob: Hello Bob, how are you ?
Bob ->> Alice: Fine, thank you. And you?
create participant Polo
Alice ->> Polo: Hi Polo!
create actor Ola1 as Ola
Polo ->> Ola1: Hiii
Ola1 ->> Alice: Hi too
destroy Ola1
Alice --x Ola1: Bye!
Alice ->> Bob: And now?
create participant Ola2 as Ola
Alice ->> Ola2: Hello again
destroy Alice
Alice --x Ola2: Bye for me!
destroy Bob
Ola2 --> Bob: The end
`
);
});
it('should render a sequence diagram with actor creation and destruction coupled with backgrounds, loops and notes', () => {
imgSnapshotTest(
`
sequenceDiagram
accTitle: test the accTitle
accDescr: Test a description
participant Alice
participant Bob
autonumber 10 10
rect rgb(200, 220, 100)
rect rgb(200, 255, 200)
Alice ->> Bob: Hello Bob, how are you?
create participant John as John<br />Second Line
Bob-->>John: How about you John?
end
Bob--x Alice: I am good thanks!
Bob-x John: I am good thanks!
Note right of John: John thinks a long<br />long time, so long<br />that the text does<br />not fit on a row.
Bob-->Alice: Checking with John...
Note over John:wrap: John looks like he's still thinking, so Bob prods him a bit.
Bob-x John: Hey John - we're still waiting to know<br />how you're doing
Note over John:nowrap: John's trying hard not to break his train of thought.
destroy John
Bob-x John: John! Cmon!
Note over John: After a few more moments, John<br />finally snaps out of it.
end
autonumber off
alt either this
create actor Lola
Alice->>+Lola: Yes
Lola-->>-Alice: OK
else or this
autonumber
Alice->>Lola: No
else or this will happen
Alice->Lola: Maybe
end
autonumber 200
par this happens in parallel
destroy Bob
Alice -->> Bob: Parallel message 1
and
Alice -->> Lola: Parallel message 2
end
`
{ wrap: true }
);
});
context('font settings', () => {
@@ -930,36 +782,4 @@ context('Sequence diagram', () => {
});
});
});
context('render after error', () => {
it('should render diagram after fixing destroy participant error', () => {
cy.on('uncaught:exception', (err) => {
return false;
});
renderGraph([
`sequenceDiagram
Alice->>Bob: Hello Bob, how are you ?
Bob->>Alice: Fine, thank you. And you?
create participant Carl
Alice->>Carl: Hi Carl!
create actor D as Donald
Carl->>D: Hi!
destroy Carl
Alice-xCarl: We are too many
destroy Bo
Bob->>Alice: I agree`,
`sequenceDiagram
Alice->>Bob: Hello Bob, how are you ?
Bob->>Alice: Fine, thank you. And you?
create participant Carl
Alice->>Carl: Hi Carl!
create actor D as Donald
Carl->>D: Hi!
destroy Carl
Alice-xCarl: We are too many
destroy Bob
Bob->>Alice: I agree`,
]);
});
});
});

View File

@@ -1,4 +1,4 @@
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
import { imgSnapshotTest, renderGraph } from '../../helpers/util';
describe('State diagram', () => {
it('v2 should render a simple info', () => {
@@ -530,7 +530,7 @@ stateDiagram-v2
[*] --> A
A --> B: test({ foo#colon; 'far' })
B --> [*]
classDef badBadEvent fill:#f00,color:white,font-weight:bold
classDef badBadEvent fill:#f00,color:white,font-weight:bold
class B badBadEvent
`,
{ logLevel: 0, fontFamily: 'courier' }
@@ -543,14 +543,14 @@ stateDiagram-v2
classDef notMoving fill:white
classDef movement font-style:italic;
classDef badBadEvent fill:#f00,color:white,font-weight:bold
[*] --> Still
Still --> [*]
Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*]
class Still notMoving
class Moving, Crash movement
class Crash badBadEvent

View File

@@ -1,4 +1,4 @@
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
import { imgSnapshotTest, renderGraph } from '../../helpers/util';
describe('State diagram', () => {
it('should render a simple state diagrams', () => {

View File

@@ -1,4 +1,4 @@
import { imgSnapshotTest } from '../../helpers/util.ts';
import { imgSnapshotTest } from '../../helpers/util.js';
describe('themeCSS balancing, it', () => {
it('should not allow unbalanced CSS definitions', () => {

View File

@@ -1,164 +0,0 @@
import { imgSnapshotTest } from '../../helpers/util.ts';
describe('Timeline diagram', () => {
it('1: should render a simple timeline with no specific sections', () => {
imgSnapshotTest(
`timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : Youtube
2006 : Twitter
`,
{}
);
});
it('2: should render a timeline diagram with sections', () => {
imgSnapshotTest(
`timeline
title Timeline of Industrial Revolution
section 17th-20th century
Industry 1.0 : Machinery, Water power, Steam <br>power
Industry 2.0 : Electricity, Internal combustion engine, Mass production
Industry 3.0 : Electronics, Computers, Automation
section 21st century
Industry 4.0 : Internet, Robotics, Internet of Things
Industry 5.0 : Artificial intelligence, Big data,3D printing
`,
{}
);
});
it('3: should render a complex timeline with sections, and long events text with <br>', () => {
imgSnapshotTest(
`timeline
title England's History Timeline
section Stone Age
7600 BC : Britain's oldest known house was built in Orkney, Scotland
6000 BC : Sea levels rise and Britain becomes an island.<br> The people who live here are hunter-gatherers.
section Broze Age
2300 BC : People arrive from Europe and settle in Britain. <br>They bring farming and metalworking.
: New styles of pottery and ways of burying the dead appear.
2200 BC : The last major building works are completed at Stonehenge.<br> People now bury their dead in stone circles.
: The first metal objects are made in Britain.Some other nice things happen. it is a good time to be alive.
`,
{}
);
});
it('4: should render a simple timeline with directives and disableMultiColor:true ', () => {
imgSnapshotTest(
`%%{init: { 'logLevel': 'debug', 'theme': 'base', 'timeline': {'disableMulticolor': true}}}%%
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : Youtube
2006 : Twitter
`,
{}
);
});
it('5: should render a simple timeline with directive overridden colors', () => {
imgSnapshotTest(
` %%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': {
'cScale0': '#ff0000',
'cScale1': '#00ff00',
'cScale2': '#0000ff'
} } }%%
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : Youtube
2006 : Twitter
2007 : Tumblr
2008 : Instagram
2010 : Pinterest
`,
{}
);
});
it('6: should render a simple timeline in base theme', () => {
imgSnapshotTest(
`%%{init: { 'logLevel': 'debug', 'theme': 'base' } }%%
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : Youtube
2006 : Twitter
2007 : Tumblr
2008 : Instagram
2010 : Pinterest
`,
{}
);
});
it('7: should render a simple timeline in default theme', () => {
imgSnapshotTest(
`%%{init: { 'logLevel': 'debug', 'theme': 'default' } }%%
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : Youtube
2006 : Twitter
2007 : Tumblr
2008 : Instagram
2010 : Pinterest
`,
{}
);
});
it('8: should render a simple timeline in dark theme', () => {
imgSnapshotTest(
`%%{init: { 'logLevel': 'debug', 'theme': 'dark' } }%%
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : Youtube
2006 : Twitter
2007 : Tumblr
2008 : Instagram
2010 : Pinterest
`,
{}
);
});
it('9: should render a simple timeline in neutral theme', () => {
imgSnapshotTest(
`%%{init: { 'logLevel': 'debug', 'theme': 'neutral' } }%%
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : Youtube
2006 : Twitter
2007 : Tumblr
2008 : Instagram
2010 : Pinterest
`,
{}
);
});
it('10: should render a simple timeline in forest theme', () => {
imgSnapshotTest(
`%%{init: { 'logLevel': 'debug', 'theme': 'forest' } }%%
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : Youtube
2006 : Twitter
2007 : Tumblr
2008 : Instagram
2010 : Pinterest
`,
{}
);
});
});

View File

@@ -1,322 +0,0 @@
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

@@ -1,19 +0,0 @@
import { imgSnapshotTest } from '../../helpers/util.ts';
describe('Zen UML', () => {
it('Basic Zen UML diagram', () => {
imgSnapshotTest(
`
zenuml
A.method() {
if(x) {
B.method() {
selfCall() { return X }
}
}
}
`,
{}
);
});
});

View File

@@ -1,231 +0,0 @@
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
rel="stylesheet"
/>
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 {
color: grey;
}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
background-color: #eee;
background-image: radial-gradient(#fff 1%, transparent 11%),
radial-gradient(#fff 1%, transparent 11%);
background-size: 20px 20px;
background-position: 0 0, 10px 10px;
background-repeat: repeat;
}
.malware {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
</head>
<body>
<div>Security check</div>
<pre id="diagram" class="mermaid2">
timeline
title My day
section section with no tasks
section Go to work at the dog office
1930 : first step : second step is a long step
: third step
1940 : fourth step : fifth step
section Go home
1950 : India got independent and already won war against Pakistan
1960 : India fights poverty, looses war to China and gets nuclear weapons from USA and USSR
1970 : Green Revolution comes to india
section Another section with no tasks
I am a big big big tasks
I am not so big tasks
</pre>
<pre id="diagram" class="mermaid">
timeline
title MermaidChart 2023 Timeline
section 2023 Q1 <br> Release Personal Tier
Buttet 1 : sub-point 1a : sub-point 1b
: sub-point 1c
Bullet 2 : sub-point 2a : sub-point 2b
section 2023 Q2 <br> Release XYZ Tier
Buttet 3 : sub-point <br> 3a : sub-point 3b
: sub-point 3c
Bullet 4 : sub-point 4a : sub-point 4b
</pre>
<pre id="diagram" class="mermaid">
timeline
title England's History Timeline
section Stone Age
7600 BC : Britain's oldest known house was built in Orkney, Scotland
6000 BC : Sea levels rise and Britain becomes an island. The people who live here are hunter-gatherers.
section Broze Age
2300 BC : People arrive from Europe and settle in Britain. They bring farming and metalworking.
: New styles of pottery and ways of burying the dead appear.
2200 BC : The last major building works are completed at Stonehenge. People now bury their dead in stone circles.
: The first metal objects are made in Britain.Some other nice things happen. it is a good time to be alive.
</pre>
<pre id="diagram" class="mermaid2">
%%{'init': { 'logLevel': 'debug', 'theme': 'default', 'timeline': {'disableMulticolor':false} } }%%
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google : Pixar
2005 : Youtube
2006 : Twitter
2007 : Tumblr
2008s : Instagram
2010 : Pinterest
</pre>
<pre id="diagram" class="mermaid2">
%%{init: { 'logLevel': 'debug', 'theme': 'base', 'themeVariables': {
'cScale0': '#ff0000',
'cScale1': '#00ff00',
'cScale2': '#ff0000'
} } }%%
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google : Pixar
2005 : Youtube
2006 : Twitter
2007 : Tumblr
2008s : Instagram
2010 : Pinterest
</pre>
<pre id="diagram" class="mermaid2">
%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': {
'cScale0': '#ff0000',
'cScale1': '#00ff00',
'cScale2': '#0000ff'
} } }%%
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : Youtube
2006 : Twitter
2007 : Tumblr
2008 : Instagram
2010 : Pinterest
</pre>
<pre id="diagram" class="mermaid2">
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : Youtube
2006 : Twitter
2007 : Tumblr
2008s : Instagram
2010 : Pinterest
</pre>
<pre id="diagram" class="mermaid2">
mindmap
root
child1((Circle))
grandchild 1
grandchild 2
child2(Round rectangle)
grandchild 3
grandchild 4
child3[Square]
grandchild 5
::icon(mdi mdi-fire)
gc6((grand<br/>child 6))
::icon(mdi mdi-fire)
gc7((grand<br/>grand<br/>child 8))
</pre>
<pre id="diagram" class="mermaid2">
flowchart-elk TB
a --> b
a --> c
b --> d
c --> d
</pre>
<!-- <div id="cy"></div> -->
<!-- <script src="http://localhost:9000/packages/mermaid-mindmap/dist/mermaid-mindmap-detector.js"></script> -->
<!-- <script src="./mermaid-example-diagram-detector.js"></script> -->
<!-- <script src="//cdn.jsdelivr.net/npm/mermaid@9.1.7/dist/mermaid.min.js"></script> -->
<script type="module">
//import mindmap from '../../packages/mermaid-mindmap/src/detector';
// import example from '../../packages/mermaid-example-diagram/src/detector';
// import timeline from '../../packages/mermaid-timeline/src/detector';
import mermaid from './mermaid.esm.mjs';
// await mermaid.registerExternalDiagrams([]);
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'base',
startOnLoad: true,
logLevel: 0,
flowchart: {
useMaxWidth: false,
htmlLabels: true,
},
gantt: {
useMaxWidth: false,
},
timeline: {
disableMulticolor: false,
htmlLabels: false,
},
useMaxWidth: true,
lazyLoadedDiagrams: [
// './mermaid-mindmap-detector.esm.mjs',
// './mermaid-example-diagram-detector.esm.mjs',
//'./mermaid-timeline-detector.esm.mjs',
],
});
function callback() {
alert('It worked');
}
mermaid.parseError = function (err, hash) {
console.error('In parse error:');
console.error(err);
};
// mermaid.test1('first_slow', 1200).then((r) => console.info(r));
// mermaid.test1('second_fast', 200).then((r) => console.info(r));
// mermaid.test1('third_fast', 200).then((r) => console.info(r));
// mermaid.test1('forth_slow', 1200).then((r) => console.info(r));
</script>
</body>
</html>

View File

@@ -1,5 +1,4 @@
// TODO: this file should be testing the ./mermaid.core.mjs file, as that's the file listed in the package.json file that users will use
import mermaid from './mermaid.esm.mjs';
import mermaid from '../../packages/mermaid/src/mermaid';
let code = `flowchart LR
Power_Supply --> Transmitter_A
@@ -50,9 +49,13 @@ mermaid.initialize({
],
},
});
void (async () => {
const { svg } = await mermaid.render('the-id-of-the-svg', code);
console.log(svg);
const elem = document.querySelector('#graph-to-be');
elem.innerHTML = svg;
})();
mermaid.render(
'the-id-of-the-svg',
code,
(svg) => {
console.log(svg);
const elem = document.querySelector('#graph-to-be');
elem.innerHTML = svg;
}
// ,document.querySelector('#tmp')
);

View File

@@ -12,6 +12,7 @@
<style>
body {
background: rgb(221, 208, 208);
/*background:#333;*/
font-family: 'Arial';
}
h1 {
@@ -45,9 +46,13 @@
<pre class="mermaid" style="width: 100%; height: 20%">
%%{init: {'theme': 'base', 'fontFamily': 'courier', 'themeVariables': { 'primaryColor': '#fff000'}}}%%
classDiagram-v2
classA <|-- classB : implements
classC *-- classD : composition
classE o-- classF : aggregation
class BankAccount{
+String owner
+BigDecimal balance
+deposit(amount) bool
+withdrawl(amount) int
}
cssClass "BankAccount" customCss
</pre>
<pre class="mermaid2" style="width: 100%; height: 20%">
%%{init: {'theme': 'base', 'fontFamily': 'courier', 'themeVariables': { 'primaryColor': '#fff000'}}}%%
@@ -112,16 +117,24 @@ classE o-- classF : aggregation
callback Shape "callbackFunction" "This is a tooltip for a callback"
</pre>
<script type="module">
import mermaid from './mermaid.esm.mjs';
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'default',
// arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
flowchart: { curve: 'linear', htmlLabels: true },
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50, showSequenceNumbers: true },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"arial", sans-serif',
// themeVariables: {
// fontFamily: '"arial", sans-serif',
// },
curve: 'linear',
securityLevel: 'loose',
});

View File

@@ -125,6 +125,7 @@
</pre>
</div>
<script src="./mermaid.js"></script>
<script>
function clickByFlow(elemName) {
const div = document.createElement('div');
@@ -161,9 +162,6 @@
document.getElementsByTagName('body')[0].appendChild(div);
}
</script>
<script type="module">
import mermaid from './mermaid.esm.mjs';
mermaid.initialize({ startOnLoad: true, securityLevel: 'loose', logLevel: 1 });
</script>
</body>

View File

@@ -59,8 +59,8 @@
Add another diagram to demo page : 48h
</pre>
<script type="module">
import mermaid from './mermaid.esm.mjs';
<script src="./mermaid.js"></script>
<script>
function clickByFlow(elemName) {
const div = document.createElement('div');
div.className = 'created-by-click';

View File

@@ -125,8 +125,8 @@
</pre>
</div>
<script type="module">
import mermaid from './mermaid.esm.mjs';
<script src="./mermaid.js"></script>
<script>
function clickByFlow(elemName) {
const div = document.createElement('div');
div.className = 'created-by-click';

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