diff --git a/.build/jsonSchema.ts b/.build/jsonSchema.ts index 7a700c1e2..48a9883de 100644 --- a/.build/jsonSchema.ts +++ b/.build/jsonSchema.ts @@ -27,6 +27,7 @@ const MERMAID_CONFIG_DIAGRAM_KEYS = [ 'block', 'packet', 'architecture', + 'radar', ] as const; /** diff --git a/.changeset/angry-bags-brake.md b/.changeset/angry-bags-brake.md deleted file mode 100644 index 472e486ec..000000000 --- a/.changeset/angry-bags-brake.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'mermaid': patch ---- - -fix: architecture diagrams no longer grow to extreme heights due to conflicting alignments diff --git a/.changeset/bright-ads-exist.md b/.changeset/bright-ads-exist.md deleted file mode 100644 index ef2f76f4c..000000000 --- a/.changeset/bright-ads-exist.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'mermaid': patch ---- - -Fixes for consistent edge id creation & handling edge cases for animate edge feature diff --git a/.changeset/chatty-elephants-warn.md b/.changeset/chatty-elephants-warn.md deleted file mode 100644 index 225047ece..000000000 --- a/.changeset/chatty-elephants-warn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'mermaid': patch ---- - -Fix for issue #6195 - allowing @ signs inside node labels diff --git a/.changeset/chilly-years-cheat.md b/.changeset/chilly-years-cheat.md deleted file mode 100644 index e665af75b..000000000 --- a/.changeset/chilly-years-cheat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'mermaid': patch ---- - -fix: `mermaidAPI.getDiagramFromText()` now returns a new different db for each class diagram diff --git a/.changeset/dull-tips-cough.md b/.changeset/dull-tips-cough.md deleted file mode 100644 index 1f5179417..000000000 --- a/.changeset/dull-tips-cough.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'mermaid': patch ---- - -fix: revert state db to resolve getData returning empty nodes and edges diff --git a/.changeset/gold-shoes-camp.md b/.changeset/gold-shoes-camp.md new file mode 100644 index 000000000..3018e7381 --- /dev/null +++ b/.changeset/gold-shoes-camp.md @@ -0,0 +1,5 @@ +--- +'mermaid': patch +--- + +fix: Remove incorrect `style="undefined;"` attributes in some Mermaid diagrams diff --git a/.changeset/great-ghosts-rule.md b/.changeset/great-ghosts-rule.md deleted file mode 100644 index f11c6e2a9..000000000 --- a/.changeset/great-ghosts-rule.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'mermaid': minor ---- - -Flowchart new syntax for node metadata bugs - -- Incorrect label mapping for nodes when using `&` -- Syntax error when `}` with trailing spaces before new line diff --git a/.changeset/grumpy-cheetahs-deliver.md b/.changeset/grumpy-cheetahs-deliver.md deleted file mode 100644 index fa6736d42..000000000 --- a/.changeset/grumpy-cheetahs-deliver.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'mermaid': patch ---- - -`mermaidAPI.getDiagramFromText()` now returns a new db instance on each call for state diagrams diff --git a/.changeset/heavy-moose-mix.md b/.changeset/heavy-moose-mix.md deleted file mode 100644 index c02d62446..000000000 --- a/.changeset/heavy-moose-mix.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'mermaid': patch ---- - -Added versioning to StateDB and updated tests and diagrams to use it. diff --git a/.changeset/honest-trees-dress.md b/.changeset/honest-trees-dress.md new file mode 100644 index 000000000..054f1bedb --- /dev/null +++ b/.changeset/honest-trees-dress.md @@ -0,0 +1,7 @@ +--- +'@mermaid-js/mermaid-zenuml': patch +--- + +chore: bump minimum ZenUML version to 3.23.28 + +commit: 9d06d8f31e7f12af9e9e092214f907f2dc93ad75 diff --git a/.changeset/many-brooms-promise.md b/.changeset/many-brooms-promise.md deleted file mode 100644 index fec442b34..000000000 --- a/.changeset/many-brooms-promise.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'mermaid': minor ---- - -Adding support for animation of flowchart edges diff --git a/.changeset/new-kiwis-listen.md b/.changeset/new-kiwis-listen.md deleted file mode 100644 index 24306573c..000000000 --- a/.changeset/new-kiwis-listen.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'mermaid': patch ---- - -fix: `mermaidAPI.getDiagramFromText()` now returns a new different db for each flowchart diff --git a/.changeset/sad-mails-accept.md b/.changeset/sad-mails-accept.md new file mode 100644 index 000000000..11dd69d8d --- /dev/null +++ b/.changeset/sad-mails-accept.md @@ -0,0 +1,6 @@ +--- +'mermaid': patch +'@mermaid-js/parser': patch +--- + +Refactor grammar so that title don't break Architecture Diagrams diff --git a/.changeset/silver-olives-marry.md b/.changeset/silver-olives-marry.md deleted file mode 100644 index d709b17ba..000000000 --- a/.changeset/silver-olives-marry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'mermaid': patch ---- - -fix: `mermaidAPI.getDiagramFromText()` now returns a new different db for each sequence diagram. Added unique IDs for messages. diff --git a/.changeset/stupid-dots-do.md b/.changeset/stupid-dots-do.md deleted file mode 100644 index 594fa9536..000000000 --- a/.changeset/stupid-dots-do.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'mermaid': patch ---- - -fix: Gantt, Sankey and User Journey diagram are now able to pick font-family from mermaid config. diff --git a/.changeset/weak-trees-perform.md b/.changeset/weak-trees-perform.md deleted file mode 100644 index 17175301d..000000000 --- a/.changeset/weak-trees-perform.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'mermaid': patch ---- - -fix: `getDirection` and `setDirection` in `stateDb` refactored to return and set actual direction diff --git a/.changeset/witty-crews-smell.md b/.changeset/witty-crews-smell.md deleted file mode 100644 index 4213083f2..000000000 --- a/.changeset/witty-crews-smell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'mermaid': patch ---- - -`mermaidAPI.getDiagramFromText()` now returns a new different db for each state diagram diff --git a/.changeset/yellow-mirrors-change.md b/.changeset/yellow-mirrors-change.md new file mode 100644 index 000000000..09a766104 --- /dev/null +++ b/.changeset/yellow-mirrors-change.md @@ -0,0 +1,7 @@ +--- +'@mermaid-js/mermaid-zenuml': patch +--- + +fix(zenuml): limit `peerDependencies` to Mermaid v10 and v11 + +commit: 0ad44c12feead9d20c6a870a49327ada58d6e657 diff --git a/.esbuild/build.ts b/.esbuild/build.ts index 423e8f047..05002cb16 100644 --- a/.esbuild/build.ts +++ b/.esbuild/build.ts @@ -34,6 +34,19 @@ const buildPackage = async (entryName: keyof typeof packageOptions) => { { ...iifeOptions, minify: true, metafile: shouldVisualize } ); } + if (entryName === 'mermaid-zenuml') { + const iifeOptions: MermaidBuildOptions = { + ...commonOptions, + format: 'iife', + globalName: 'mermaid-zenuml', + }; + buildConfigs.push( + // mermaid-zenuml.js + { ...iifeOptions }, + // mermaid-zenuml.min.js + { ...iifeOptions, minify: true, metafile: shouldVisualize } + ); + } const results = await Promise.all(buildConfigs.map((option) => build(getBuildConfig(option)))); diff --git a/.esbuild/util.ts b/.esbuild/util.ts index 6d6d1d59b..dde0352af 100644 --- a/.esbuild/util.ts +++ b/.esbuild/util.ts @@ -58,6 +58,7 @@ export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => { format, minify, options: { name, file, packageName }, + globalName = 'mermaid', } = options; const external: string[] = ['require', 'fs', 'path']; const outFileName = getFileName(name, options); @@ -68,6 +69,7 @@ export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => { }, metafile, minify, + globalName, logLevel: 'info', chunkNames: `chunks/${outFileName}/[name]-[hash]`, define: { @@ -89,11 +91,12 @@ export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => { if (format === 'iife') { output.format = 'iife'; output.splitting = false; - output.globalName = '__esbuild_esm_mermaid'; + const originalGlobalName = output.globalName ?? 'mermaid'; + output.globalName = `__esbuild_esm_mermaid_nm[${JSON.stringify(originalGlobalName)}]`; // Workaround for removing the .default access in esbuild IIFE. // https://github.com/mermaid-js/mermaid/pull/4109#discussion_r1292317396 output.footer = { - js: 'globalThis.mermaid = globalThis.__esbuild_esm_mermaid.default;', + js: `globalThis[${JSON.stringify(originalGlobalName)}] = globalThis.${output.globalName}.default;`, }; output.outExtension = { '.js': '.js' }; } else { diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 6be6f3b5d..b7313b621 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -4,7 +4,7 @@ contact_links: url: https://github.com/mermaid-js/mermaid/discussions about: Ask the Community questions or share your own graphs in our discussions. - name: Discord - url: https://discord.gg/AgrbSrBer3 + url: https://discord.gg/sKeNQX4Wtj about: Join our Community on Discord for Help and a casual chat. - name: Documentation url: https://mermaid.js.org diff --git a/.github/workflows/autofix.yml b/.github/workflows/autofix.yml index 7280278d2..5b1066661 100644 --- a/.github/workflows/autofix.yml +++ b/.github/workflows/autofix.yml @@ -13,13 +13,13 @@ jobs: autofix: runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 # uses version from "packageManager" field in package.json - name: Setup Node.js - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: cache: pnpm node-version-file: '.node-version' diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 79e9deea1..79ed53de1 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -18,12 +18,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node.js - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: cache: pnpm node-version-file: '.node-version' diff --git a/.github/workflows/check-readme-in-sync.yml b/.github/workflows/check-readme-in-sync.yml index 5c940c087..ed5c70208 100644 --- a/.github/workflows/check-readme-in-sync.yml +++ b/.github/workflows/check-readme-in-sync.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Check for difference in README.md and docs/README.md run: | diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index a5cbbf8d5..a6400a86a 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -32,11 +32,11 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13 + uses: github/codeql-action/init@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 with: config-file: ./.github/codeql/codeql-config.yml languages: ${{ matrix.language }} @@ -48,7 +48,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13 + uses: github/codeql-action/autobuild@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 # โน๏ธ Command-line programs to run using the OS shell. # ๐ See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -62,4 +62,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13 + uses: github/codeql-action/analyze@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index dce9ad2b2..69c435631 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -15,6 +15,6 @@ jobs: runs-on: ubuntu-latest steps: - name: 'Checkout Repository' - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: 'Dependency Review' - uses: actions/dependency-review-action@a6993e2c61fd5dc440b409aa1d6904921c5e1894 # v4.3.5 + uses: actions/dependency-review-action@3b139cfc5fae8b618d3eae3675e383bb1769c019 # v4.5.0 diff --git a/.github/workflows/e2e-applitools.yml b/.github/workflows/e2e-applitools.yml index b1eb70674..9c357a581 100644 --- a/.github/workflows/e2e-applitools.yml +++ b/.github/workflows/e2e-applitools.yml @@ -32,13 +32,13 @@ jobs: run: | echo "::error,title=Not using Applitools::APPLITOOLS_API_KEY is empty, disabling Applitools for this run." - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 # uses version from "packageManager" field in package.json - name: Setup Node.js - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version-file: '.node-version' @@ -54,7 +54,7 @@ jobs: APPLITOOLS_SERVER_URL: 'https://eyesapi.applitools.com' - name: Cypress run - uses: cypress-io/github-action@d79d2d530a66e641eb4a5f227e13bc985c60b964 # v4.2.2 + uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 id: cypress with: start: pnpm run dev diff --git a/.github/workflows/e2e-timings.yml b/.github/workflows/e2e-timings.yml index 42760e222..f45551988 100644 --- a/.github/workflows/e2e-timings.yml +++ b/.github/workflows/e2e-timings.yml @@ -11,6 +11,7 @@ concurrency: ${{ github.workflow }}-${{ github.ref }} permissions: contents: write + pull-requests: write jobs: timings: @@ -19,18 +20,19 @@ jobs: image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1 options: --user 1001 steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node.js - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version-file: '.node-version' - name: Install dependencies - uses: cypress-io/github-action@57b70560982e6a11d23d4b8bec7f8a487cdbb71b # v6.7.8 + uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 with: runTests: false + - name: Cypress run - uses: cypress-io/github-action@57b70560982e6a11d23d4b8bec7f8a487cdbb71b # v6.7.8 + uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 id: cypress with: install: false @@ -44,10 +46,17 @@ jobs: SPLIT: 1 SPLIT_INDEX: 0 SPLIT_FILE: 'cypress/timings.json' - - name: Commit changes - uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4 + + - name: Compare timings + run: pnpm tsx scripts/compare-timings.ts + + - name: Commit and create pull request + uses: peter-evans/create-pull-request@a7b20e1da215b3ef3ccddb48ff65120256ed6226 with: - add: 'cypress/timings.json' - author_name: 'github-actions[bot]' - author_email: '41898282+github-actions[bot]@users.noreply.github.com' - message: 'chore: update E2E timings' + add-paths: | + cypress/timings.json + commit-message: 'chore: update E2E timings' + branch: update-timings + title: Update E2E Timings + delete-branch: true + sign-commits: true diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 4922da76f..56883b987 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -37,10 +37,10 @@ jobs: image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1 options: --user 1001 steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node.js - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version-file: '.node-version' - name: Cache snapshots @@ -53,13 +53,13 @@ jobs: # 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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ env.targetHash }} - name: Install dependencies if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }} - uses: cypress-io/github-action@57b70560982e6a11d23d4b8bec7f8a487cdbb71b # v6.7.8 + uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 with: # just perform install runTests: false @@ -82,13 +82,13 @@ jobs: matrix: containers: [1, 2, 3, 4, 5] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 # uses version from "packageManager" field in package.json - name: Setup Node.js - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version-file: '.node-version' @@ -101,7 +101,7 @@ jobs: key: ${{ runner.os }}-snapshots-${{ env.targetHash }} - name: Install dependencies - uses: cypress-io/github-action@57b70560982e6a11d23d4b8bec7f8a487cdbb71b # v6.7.8 + uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 with: runTests: false @@ -117,7 +117,7 @@ jobs: # Install NPM dependencies, cache them correctly # and run all Cypress tests - name: Cypress run - uses: cypress-io/github-action@57b70560982e6a11d23d4b8bec7f8a487cdbb71b # v6.7.8 + uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 id: cypress with: install: false @@ -139,7 +139,7 @@ jobs: VITEST_COVERAGE: true - name: Upload Coverage to Codecov - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 + uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 # 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: diff --git a/.github/workflows/link-checker.yml b/.github/workflows/link-checker.yml index d2f5d7744..f855ed23b 100644 --- a/.github/workflows/link-checker.yml +++ b/.github/workflows/link-checker.yml @@ -29,7 +29,7 @@ jobs: # lychee only uses the GITHUB_TOKEN to avoid rate-limiting contents: read steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Restore lychee cache uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 @@ -39,7 +39,7 @@ jobs: restore-keys: cache-lychee- - name: Link Checker - uses: lycheeverse/lychee-action@c053181aa0c3d17606addfe97a9075a32723548a # v1.9.3 + uses: lycheeverse/lychee-action@f613c4a64e50d792e0b31ec34bbcbba12263c6a6 # v2.3.0 with: args: >- --config .github/lychee.toml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 24e7ee35d..50edaa271 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -15,7 +15,7 @@ jobs: docker-lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: hadolint/hadolint-action@54c9adbab1582c2ef04b2016b760714a4bfde3cf # v3.1.0 with: @@ -23,13 +23,13 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 # uses version from "packageManager" field in package.json - name: Setup Node.js - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: cache: pnpm node-version-file: '.node-version' diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml index c9faaa062..44860845f 100644 --- a/.github/workflows/pr-labeler.yml +++ b/.github/workflows/pr-labeler.yml @@ -22,7 +22,7 @@ jobs: pull-requests: write # write permission is required to label PRs steps: - name: Label PR - uses: release-drafter/release-drafter@3f0f87098bd6b5c5b9a36d49c41d998ea58f9348 # v6.0.0 + uses: release-drafter/release-drafter@b1476f6e6eb133afa41ed8589daba6dc69b4d3f5 # v6.1.0 with: config-name: pr-labeler.yml disable-autolabeler: false diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml index 587ddae08..1a9ccafb6 100644 --- a/.github/workflows/publish-docs.yml +++ b/.github/workflows/publish-docs.yml @@ -23,12 +23,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node.js - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: cache: pnpm node-version-file: '.node-version' @@ -37,7 +37,7 @@ jobs: run: pnpm install --frozen-lockfile - name: Setup Pages - uses: actions/configure-pages@1f0c5cde4bc74cd7e1254d0cb4de8d49e9068c7d # v4.0.0 + uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0 - name: Run Build run: pnpm --filter mermaid run docs:build:vitepress diff --git a/.github/workflows/release-preview-publish.yml b/.github/workflows/release-preview-publish.yml index fa48d3659..665222b35 100644 --- a/.github/workflows/release-preview-publish.yml +++ b/.github/workflows/release-preview-publish.yml @@ -9,14 +9,14 @@ jobs: publish-preview: runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node.js - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: cache: pnpm node-version-file: '.node-version' diff --git a/.github/workflows/release-preview.yml b/.github/workflows/release-preview.yml index 7b7dba987..38938dff4 100644 --- a/.github/workflows/release-preview.yml +++ b/.github/workflows/release-preview.yml @@ -26,12 +26,12 @@ jobs: timeout-minutes: 5 steps: - name: Checkout Repo - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node.js - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: cache: pnpm node-version-file: '.node-version' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d4e349d08..649c40034 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,12 +21,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Repo - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node.js - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: cache: pnpm node-version-file: '.node-version' diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 5b4fdc342..4901b3781 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -16,22 +16,22 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: Run analysis - uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3 + uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 with: results_file: results.sarif results_format: sarif publish_results: true - name: Upload artifact - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 with: name: SARIF file path: results.sarif retention-days: 5 - name: Upload to code-scanning - uses: github/codeql-action/upload-sarif@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13 + uses: github/codeql-action/upload-sarif@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 with: sarif_file: results.sarif diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7323ec027..527ab7401 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,13 +9,13 @@ jobs: unit-test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 # uses version from "packageManager" field in package.json - name: Setup Node.js - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: cache: pnpm node-version-file: '.node-version' @@ -43,7 +43,7 @@ jobs: pnpm test:check:tsc - name: Upload Coverage to Codecov - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 + uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 # Run step only pushes to develop and pull_requests if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/develop' }} with: diff --git a/.github/workflows/update-browserlist.yml b/.github/workflows/update-browserlist.yml index 1b26271f7..94de12ad3 100644 --- a/.github/workflows/update-browserlist.yml +++ b/.github/workflows/update-browserlist.yml @@ -8,8 +8,8 @@ jobs: update-browser-list: runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - run: npx update-browserslist-db@latest - name: Commit changes uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4 @@ -19,7 +19,7 @@ jobs: message: 'chore: update browsers list' push: false - name: Create Pull Request - uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c # v6.1.0 + uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6 with: branch: update-browserslist title: Update Browserslist diff --git a/.node-version b/.node-version index 87834047a..7d41c735d 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -20.12.2 +22.14.0 diff --git a/Dockerfile b/Dockerfile index 7be53d24e..533604407 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:20.12.2-alpine3.19@sha256:7a91aa397f2e2dfbfcdad2e2d72599f374e0b0172be1d86eeb73f1d33f36a4b2 +FROM node:22.12.0-alpine3.19@sha256:40dc4b415c17b85bea9be05314b4a753f45a4e1716bb31c01182e6c53d51a654 USER 0:0 diff --git a/README.md b/README.md index 047f8254c..2fca46b25 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Generate diagrams from markdown-like text. Live Editor!
- ๐ Documentation | ๐ Getting Started | ๐ CDN | ๐ Join Us + ๐ Documentation | ๐ Getting Started | ๐ CDN | ๐ Join Us
็ฎไฝไธญๆ @@ -33,7 +33,7 @@ Try Live Editor previews of future releases: ๅฎๆถ็ผ่พๅจ!
- ๐ ๆๆกฃ | ๐ ๅ ฅ้จ | ๐ CDN | ๐ ๅ ๅ ฅๆไปฌ + ๐ ๆๆกฃ | ๐ ๅ ฅ้จ | ๐ CDN | ๐ ๅ ๅ ฅๆไปฌ
English
@@ -34,7 +34,7 @@ Mermaid
[](https://app.codecov.io/github/mermaid-js/mermaid/tree/develop)
[](https://www.jsdelivr.com/package/npm/mermaid)
[](https://www.npmjs.com/package/mermaid)
-[](https://discord.gg/AgrbSrBer3)
+[](https://discord.gg/sKeNQX4Wtj)
[](https://twitter.com/mermaidjs_)
diff --git a/cypress.config.ts b/cypress.config.ts
index d077ba915..50ea940e9 100644
--- a/cypress.config.ts
+++ b/cypress.config.ts
@@ -1,8 +1,8 @@
import eyesPlugin from '@applitools/eyes-cypress';
import { registerArgosTask } from '@argos-ci/cypress/task';
-import coverage from '@cypress/code-coverage/task';
+import coverage from '@cypress/code-coverage/task.js';
import { defineConfig } from 'cypress';
-import { addMatchImageSnapshotPlugin } from 'cypress-image-snapshot/plugin';
+import { addMatchImageSnapshotPlugin } from 'cypress-image-snapshot/plugin.js';
import cypressSplit from 'cypress-split';
export default eyesPlugin(
diff --git a/cypress/integration/rendering/architecture.spec.ts b/cypress/integration/rendering/architecture.spec.ts
index 25326ff80..ec74a5dd5 100644
--- a/cypress/integration/rendering/architecture.spec.ts
+++ b/cypress/integration/rendering/architecture.spec.ts
@@ -19,6 +19,25 @@ describe.skip('architecture diagram', () => {
`
);
});
+ it('should render a simple architecture diagram with titleAndAccessabilities', () => {
+ imgSnapshotTest(
+ `architecture-beta
+ title Simple Architecture Diagram
+ accTitle: Accessibility Title
+ accDescr: Accessibility Description
+ group api(cloud)[API]
+
+ service db(database)[Database] in api
+ service disk1(disk)[Storage] in api
+ service disk2(disk)[Storage] in api
+ service server(server)[Server] in api
+
+ db:L -- R:server
+ disk1:T -- B:server
+ disk2:T -- B:db
+ `
+ );
+ });
it('should render an architecture diagram with groups within groups', () => {
imgSnapshotTest(
`architecture-beta
@@ -172,7 +191,7 @@ describe.skip('architecture diagram', () => {
);
});
- it('should render an architecture diagram with a resonable height', () => {
+ it('should render an architecture diagram with a reasonable height', () => {
imgSnapshotTest(
`architecture-beta
group federated(cloud)[Federated Environment]
diff --git a/cypress/integration/rendering/erDiagram-unified.spec.js b/cypress/integration/rendering/erDiagram-unified.spec.js
new file mode 100644
index 000000000..8cecba21d
--- /dev/null
+++ b/cypress/integration/rendering/erDiagram-unified.spec.js
@@ -0,0 +1,652 @@
+import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
+
+const testOptions = [
+ { description: '', options: { logLevel: 1 } },
+ { description: 'ELK: ', options: { logLevel: 1, layout: 'elk' } },
+ { description: 'HD: ', options: { logLevel: 1, look: 'handDrawn' } },
+];
+
+describe('Entity Relationship Diagram Unified', () => {
+ testOptions.forEach(({ description, options }) => {
+ it(`${description}should render a simple ER diagram`, () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ CUSTOMER ||--o{ ORDER : places
+ ORDER ||--|{ LINE-ITEM : contains
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render a simple ER diagram without htmlLabels`, () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ CUSTOMER ||--o{ ORDER : places
+ ORDER ||--|{ LINE-ITEM : contains
+ `,
+ { ...options, htmlLabels: false }
+ );
+ });
+
+ it(`${description}should render an ER diagram with a recursive relationship`, () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ CUSTOMER ||..o{ CUSTOMER : refers
+ CUSTOMER ||--o{ ORDER : places
+ ORDER ||--|{ LINE-ITEM : contains
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render an ER diagram with multiple relationships between the same two entities`, () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ CUSTOMER ||--|{ ADDRESS : "invoiced at"
+ CUSTOMER ||--|{ ADDRESS : "receives goods at"
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render a cyclical ER diagram`, () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ A ||--|{ B : likes
+ B ||--|{ C : likes
+ C ||--|{ A : likes
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render a not-so-simple ER diagram`, () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ CUSTOMER }|..|{ DELIVERY-ADDRESS : has
+ CUSTOMER ||--o{ ORDER : places
+ CUSTOMER ||--o{ INVOICE : "liable for"
+ DELIVERY-ADDRESS ||--o{ ORDER : receives
+ INVOICE ||--|{ ORDER : covers
+ ORDER ||--|{ ORDER-ITEM : includes
+ PRODUCT-CATEGORY ||--|{ PRODUCT : contains
+ PRODUCT ||--o{ ORDER-ITEM : "ordered in"
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render a not-so-simple ER diagram without htmlLabels`, () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ CUSTOMER }|..|{ DELIVERY-ADDRESS : has
+ CUSTOMER ||--o{ ORDER : places
+ CUSTOMER ||--o{ INVOICE : "liable for"
+ DELIVERY-ADDRESS ||--o{ ORDER : receives
+ INVOICE ||--|{ ORDER : covers
+ ORDER ||--|{ ORDER-ITEM : includes
+ PRODUCT-CATEGORY ||--|{ PRODUCT : contains
+ PRODUCT ||--o{ ORDER-ITEM : "ordered in"
+ `,
+ { ...options, htmlLabels: false }
+ );
+ });
+
+ it(`${description}should render multiple ER diagrams`, () => {
+ imgSnapshotTest(
+ [
+ `
+ erDiagram
+ CUSTOMER ||--o{ ORDER : places
+ ORDER ||--|{ LINE-ITEM : contains
+ `,
+ `
+ erDiagram
+ CUSTOMER ||--o{ ORDER : places
+ ORDER ||--|{ LINE-ITEM : contains
+ `,
+ ],
+ options
+ );
+ });
+
+ it(`${description}should render an ER diagram with blank or empty labels`, () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ BOOK }|..|{ AUTHOR : ""
+ BOOK }|..|{ GENRE : " "
+ AUTHOR }|..|{ GENRE : " "
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render entities that have no relationships`, () => {
+ renderGraph(
+ `
+ erDiagram
+ DEAD_PARROT
+ HERMIT
+ RECLUSE
+ SOCIALITE }o--o{ SOCIALITE : "interacts with"
+ RECLUSE }o--o{ SOCIALITE : avoids
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render entities with and without attributes`, () => {
+ renderGraph(
+ `
+ erDiagram
+ BOOK { string title }
+ AUTHOR }|..|{ BOOK : writes
+ BOOK { float price }
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render entities with generic and array attributes`, () => {
+ renderGraph(
+ `
+ erDiagram
+ BOOK {
+ string title
+ string[] authors
+ type~T~ type
+ }
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render entities with generic and array attributes without htmlLabels`, () => {
+ renderGraph(
+ `
+ erDiagram
+ BOOK {
+ string title
+ string[] authors
+ type~T~ type
+ }
+ `,
+ { ...options, htmlLabels: false }
+ );
+ });
+
+ it(`${description}should render entities with length in attributes type`, () => {
+ renderGraph(
+ `
+ erDiagram
+ CLUSTER {
+ varchar(99) name
+ string(255) description
+ }
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render entities with length in attributes type without htmlLabels`, () => {
+ renderGraph(
+ `
+ erDiagram
+ CLUSTER {
+ varchar(99) name
+ string(255) description
+ }
+ `,
+ { ...options, htmlLabels: false }
+ );
+ });
+
+ it(`${description}should render entities and attributes with big and small entity names`, () => {
+ renderGraph(
+ `
+ erDiagram
+ PRIVATE_FINANCIAL_INSTITUTION {
+ string name
+ int turnover
+ }
+ PRIVATE_FINANCIAL_INSTITUTION ||..|{ EMPLOYEE : employs
+ EMPLOYEE { bool officer_of_firm }
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render entities and attributes with big and small entity names without htmlLabels`, () => {
+ renderGraph(
+ `
+ erDiagram
+ PRIVATE_FINANCIAL_INSTITUTION {
+ string name
+ int turnover
+ }
+ PRIVATE_FINANCIAL_INSTITUTION ||..|{ EMPLOYEE : employs
+ EMPLOYEE { bool officer_of_firm }
+ `,
+ { ...options, htmlLabels: false }
+ );
+ });
+
+ it(`${description}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
+ }
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render entities with attributes that begin with asterisk without htmlLabels`, () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ BOOK {
+ int *id
+ string name
+ varchar(99) summary
+ }
+ BOOK }o..o{ STORE : soldBy
+ STORE {
+ int *id
+ string name
+ varchar(50) address
+ }
+ `,
+ { ...options, htmlLabels: false }
+ );
+ });
+
+ it(`${description}should render entities with keys`, () => {
+ renderGraph(
+ `
+ erDiagram
+ AUTHOR_WITH_LONG_ENTITY_NAME {
+ string name PK
+ }
+ AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
+ BOOK {
+ float price
+ string author FK
+ string title PK
+ }
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render entities with keys without htmlLabels`, () => {
+ renderGraph(
+ `
+ erDiagram
+ AUTHOR_WITH_LONG_ENTITY_NAME {
+ string name PK
+ }
+ AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
+ BOOK {
+ float price
+ string author FK
+ string title PK
+ }
+ `,
+ { ...options, htmlLabels: false }
+ );
+ });
+
+ it(`${description}should render entities with comments`, () => {
+ renderGraph(
+ `
+ erDiagram
+ AUTHOR_WITH_LONG_ENTITY_NAME {
+ string name "comment"
+ }
+ AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
+ BOOK {
+ string author
+ string title "author comment"
+ float price "price comment"
+ }
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render entities with comments without htmlLabels`, () => {
+ renderGraph(
+ `
+ erDiagram
+ AUTHOR_WITH_LONG_ENTITY_NAME {
+ string name "comment"
+ }
+ AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
+ BOOK {
+ string author
+ string title "author comment"
+ float price "price comment"
+ }
+ `,
+ { ...options, htmlLabels: false }
+ );
+ });
+
+ it(`${description}should render entities with keys and comments`, () => {
+ renderGraph(
+ `
+ erDiagram
+ AUTHOR_WITH_LONG_ENTITY_NAME {
+ string name PK "comment"
+ }
+ AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
+ BOOK {
+ string description
+ float price "price comment"
+ string title PK "title comment"
+ string author FK
+ }
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render entities with keys and comments without htmlLabels`, () => {
+ renderGraph(
+ `
+ erDiagram
+ AUTHOR_WITH_LONG_ENTITY_NAME {
+ string name PK "comment"
+ }
+ AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
+ BOOK {
+ string description
+ float price "price comment"
+ string title PK "title comment"
+ string author FK
+ }
+ `,
+ { ...options, htmlLabels: false }
+ );
+ });
+
+ it(`${description}should render entities with aliases`, () => {
+ renderGraph(
+ `
+ erDiagram
+ T1 one or zero to one or more T2 : test
+ T2 one or many optionally to zero or one T3 : test
+ T3 zero or more to zero or many T4 : test
+ T4 many(0) to many(1) T5 : test
+ T5 many optionally to one T6 : test
+ T6 only one optionally to only one T1 : test
+ T4 0+ to 1+ T6 : test
+ T1 1 to 1 T3 : test
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render a simple ER diagram with a title`, () => {
+ imgSnapshotTest(
+ `---
+ title: simple ER diagram
+ ---
+ erDiagram
+ CUSTOMER ||--o{ ORDER : places
+ ORDER ||--|{ LINE-ITEM : contains
+ `,
+ options
+ );
+ });
+
+ it(`${description}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
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render relationship labels with line breaks`, () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ p[Person] {
+ string firstName
+ string lastName
+ }
+ a["Customer Account"] {
+ string email
+ }
+
+ b["Customer Account Secondary"] {
+ string email
+ }
+
+ c["Customer Account Tertiary"] {
+ string email
+ }
+
+ d["Customer Account Nth"] {
+ string email
+ }
+
+ p ||--o| a : "has
one"
+ p ||--o| b : "has
one
two"
+ p ||--o| c : "has
one
two
three"
+ p ||--o| d : "has
one
two
three
...
Nth"
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render an ER diagram with unicode text`, () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ _**testแบฝฮถโร๐ใใผ**_ {
+ *__List~List~int~~sdfds__* **driversLicense** PK "***The l๐icense #***"
+ *string(99)~T~~~~~~* firstName "Only __99__
characters are a
llowed dsfsdfsdfsdfs"
+ string last*Name*
+ string __phone__ UK
+ int _age_
+ }
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render an ER diagram with unicode text without htmlLabels`, () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ _**testแบฝฮถโร๐ใใผ**_ {
+ *__List~List~int~~sdfds__* **driversLicense** PK "***The l๐icense #***"
+ *string(99)~T~~~~~~* firstName "Only __99__
characters are a
llowed dsfsdfsdfsdfs"
+ string last*Name*
+ string __phone__ UK
+ int _age_
+ }
+ `,
+ { ...options, htmlLabels: false }
+ );
+ });
+
+ it(`${description}should render an ER diagram with relationships with unicode text`, () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ person[๐] {
+ string *first*Name
+ string _**last**Name_
+ }
+ a["*Customer Account*"] {
+ **string** ema*i*l
+ }
+ person ||--o| a : __hแบฝ๐__
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render an ER diagram with relationships with unicode text without htmlLabels`, () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ person[๐] {
+ string *first*Name
+ string _**last**Name_
+ }
+ a["*Customer Account*"] {
+ **string** ema*i*l
+ }
+ person ||--o| a : __hแบฝ๐__
+ `,
+ { ...options, htmlLabels: false }
+ );
+ });
+
+ it(`${description}should render an ER diagram with TB direction`, () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ direction TB
+ CAR ||--|{ NAMED-DRIVER : allows
+ PERSON ||..o{ NAMED-DRIVER : is
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render an ER diagram with BT direction`, () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ direction BT
+ CAR ||--|{ NAMED-DRIVER : allows
+ PERSON ||..o{ NAMED-DRIVER : is
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render an ER diagram with LR direction`, () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ direction LR
+ CAR ||--|{ NAMED-DRIVER : allows
+ PERSON ||..o{ NAMED-DRIVER : is
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render an ER diagram with RL direction`, () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ direction RL
+ CAR ||--|{ NAMED-DRIVER : allows
+ PERSON ||..o{ NAMED-DRIVER : is
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render entities with styles applied from style statement`, () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ c[CUSTOMER]
+ p[PERSON]
+ style c,p fill:#f9f,stroke:blue, color:grey, font-size:24px,font-weight:bold
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render entities with styles applied from style statement without htmlLabels`, () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ c[CUSTOMER]
+ p[PERSON]
+ style c,p fill:#f9f,stroke:blue, color:grey, font-size:24px,font-weight:bold
+ `,
+ { ...options, htmlLabels: false }
+ );
+ });
+
+ it(`${description}should render entities with styles applied from class statement`, () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ c[CUSTOMER]
+ p[PERSON]:::blue
+ classDef bold font-size:24px, font-weight: bold
+ classDef blue stroke:lightblue, color: #0000FF
+ class c,p bold
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render entities with styles applied from class statement without htmlLabels`, () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ c[CUSTOMER]
+ p[PERSON]:::blue
+ classDef bold font-size:24px, font-weight: bold
+ classDef blue stroke:lightblue, color: #0000FF
+ class c,p bold
+ `,
+ { ...options, htmlLabels: false }
+ );
+ });
+
+ it(`${description}should render entities with styles applied from the default class and other styles`, () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ c[CUSTOMER]
+ p[PERSON]:::blue
+ classDef blue stroke:lightblue, color: #0000FF
+ classDef default fill:pink
+ style c color:green
+ `,
+ { ...options }
+ );
+ });
+ });
+});
diff --git a/cypress/integration/rendering/erDiagram.spec.js b/cypress/integration/rendering/erDiagram.spec.js
index aad9b1cf7..cbfec8218 100644
--- a/cypress/integration/rendering/erDiagram.spec.js
+++ b/cypress/integration/rendering/erDiagram.spec.js
@@ -109,8 +109,8 @@ describe('Entity Relationship Diagram', () => {
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
- // use within because the absolute value can be slightly different depending on the environment ยฑ5%
- expect(maxWidthValue).to.be.within(140 * 0.95, 140 * 1.05);
+ // use within because the absolute value can be slightly different depending on the environment ยฑ6%
+ expect(maxWidthValue).to.be.within(140 * 0.96, 140 * 1.06);
});
});
@@ -125,8 +125,8 @@ describe('Entity Relationship Diagram', () => {
);
cy.get('svg').should((svg) => {
const width = parseFloat(svg.attr('width'));
- // use within because the absolute value can be slightly different depending on the environment ยฑ5%
- expect(width).to.be.within(140 * 0.95, 140 * 1.05);
+ // use within because the absolute value can be slightly different depending on the environment ยฑ6%
+ expect(width).to.be.within(140 * 0.96, 140 * 1.06);
// expect(svg).to.have.attr('height', '465');
expect(svg).to.not.have.attr('style');
});
diff --git a/cypress/integration/rendering/flowchart.spec.js b/cypress/integration/rendering/flowchart.spec.js
index d3a83ae5f..7b986cd2f 100644
--- a/cypress/integration/rendering/flowchart.spec.js
+++ b/cypress/integration/rendering/flowchart.spec.js
@@ -895,7 +895,7 @@ graph TD
imgSnapshotTest(
`
graph TD
- classDef default fill:#a34,stroke:#000,stroke-width:4px,color:#fff
+ classDef default fill:#a34,stroke:#000,stroke-width:4px,color:#fff
hello --> default
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
@@ -917,4 +917,21 @@ graph TD
}
);
});
+ it('#6369: edge color should affect arrow head', () => {
+ imgSnapshotTest(
+ `
+ flowchart LR
+ A --> B
+ A --> C
+ C --> D
+
+ linkStyle 0 stroke:#D50000
+ linkStyle 2 stroke:#D50000
+ `,
+ {
+ flowchart: { htmlLabels: true },
+ securityLevel: 'loose',
+ }
+ );
+ });
});
diff --git a/cypress/integration/rendering/journey.spec.js b/cypress/integration/rendering/journey.spec.js
index d8bef6d1b..2d6c14c9d 100644
--- a/cypress/integration/rendering/journey.spec.js
+++ b/cypress/integration/rendering/journey.spec.js
@@ -63,4 +63,165 @@ section Checkout from website
{ journey: { useMaxWidth: false } }
);
});
+
+ it('should initialize with a left margin of 150px for user journeys', () => {
+ renderGraph(
+ `
+ ---
+ config:
+ journey:
+ maxLabelWidth: 320
+ ---
+ journey
+ title User Journey Example
+ section Onboarding
+ Sign Up: 5:
+ Browse Features: 3:
+ Use Core Functionality: 4:
+ section Engagement
+ Browse Features: 3
+ Use Core Functionality: 4
+ `,
+ { journey: { useMaxWidth: true } }
+ );
+
+ let diagramStartX;
+
+ cy.contains('foreignobject', 'Sign Up').then(($diagram) => {
+ diagramStartX = parseFloat($diagram.attr('x'));
+ expect(diagramStartX).to.be.closeTo(150, 2);
+ });
+ });
+
+ it('should maintain sufficient space between legend and diagram when legend labels are longer', () => {
+ renderGraph(
+ `journey
+ title Web hook life cycle
+ section Darkoob
+ Make preBuilt:5: Darkoob user
+ register slug : 5: Darkoob userf deliberately increasing the size of this label to check if distance between legend and diagram is maintained
+ Map slug to a Prebuilt Job:5: Darkoob user
+ section External Service
+ set Darkoob slug as hook for an Event : 5 : admin Exjjjnjjjj qwerty
+ listen to the events : 5 : External Service
+ call darkoob endpoint : 5 : External Service
+ section Darkoob
+ check for inputs : 5 : DarkoobAPI
+ run the prebuilt job : 5 : DarkoobAPI
+ `,
+ { journey: { useMaxWidth: true } }
+ );
+
+ let LabelEndX, diagramStartX;
+
+ // Get right edge of the legend
+ cy.contains('tspan', 'Darkoob userf').then((textBox) => {
+ const bbox = textBox[0].getBBox();
+ LabelEndX = bbox.x + bbox.width;
+ });
+
+ // Get left edge of the diagram
+ cy.contains('foreignobject', 'Make preBuilt').then((rect) => {
+ diagramStartX = parseFloat(rect.attr('x'));
+ });
+
+ // Assert right edge of the diagram is greater than or equal to the right edge of the label
+ cy.then(() => {
+ expect(diagramStartX).to.be.gte(LabelEndX);
+ });
+ });
+
+ it('should wrap a single long word with hyphenation', () => {
+ renderGraph(
+ `
+ ---
+ config:
+ journey:
+ maxLabelWidth: 100
+ ---
+ journey
+ title Long Word Test
+ section Test
+ VeryLongWord: 5: Supercalifragilisticexpialidocious
+ `,
+ { journey: { useMaxWidth: true } }
+ );
+
+ // Verify that the line ends with a hyphen, indicating proper hyphenation for words exceeding maxLabelWidth.
+ cy.get('tspan').then((tspans) => {
+ const hasHyphen = [...tspans].some((t) => t.textContent.trim().endsWith('-'));
+ return expect(hasHyphen).to.be.true;
+ });
+ });
+
+ it('should wrap text on whitespace without adding hyphens', () => {
+ renderGraph(
+ `
+ ---
+ config:
+ journey:
+ maxLabelWidth: 200
+ ---
+ journey
+ title Whitespace Test
+ section Test
+ TextWithSpaces: 5: Gustavo Fring is played by Giancarlo Esposito and is a character in Breaking Bad.
+ `,
+ { journey: { useMaxWidth: true } }
+ );
+
+ // Verify that none of the text spans end with a hyphen.
+ cy.get('tspan').each(($el) => {
+ const text = $el.text();
+ expect(text.trim()).not.to.match(/-$/);
+ });
+ });
+
+ it('should wrap long labels into multiple lines, keep them under max width, and maintain margins', () => {
+ renderGraph(
+ `
+ ---
+ config:
+ journey:
+ maxLabelWidth: 320
+ ---
+ journey
+ title User Journey Example
+ section Onboarding
+ Sign Up: 5: This is a long label that will be split into multiple lines to test the wrapping functionality
+ Browse Features: 3: This is another long label that will be split into multiple lines to test the wrapping functionality
+ Use Core Functionality: 4: This is yet another long label that will be split into multiple lines to test the wrapping functionality
+ section Engagement
+ Browse Features: 3
+ Use Core Functionality: 4
+ `,
+ { journey: { useMaxWidth: true } }
+ );
+
+ let diagramStartX, maxLineWidth;
+
+ // Get the diagram's left edge x-coordinate
+ cy.contains('foreignobject', 'Sign Up')
+ .then(($diagram) => {
+ diagramStartX = parseFloat($diagram.attr('x'));
+ })
+ .then(() => {
+ cy.get('text.legend').then(($lines) => {
+ // Check that there are multiple lines
+ expect($lines.length).to.be.equal(9);
+
+ // Check that all lines are under the maxLabelWidth
+ $lines.each((index, el) => {
+ const bbox = el.getBBox();
+ expect(bbox.width).to.be.lte(320);
+ maxLineWidth = Math.max(maxLineWidth || 0, bbox.width);
+ });
+
+ /** The expected margin between the diagram and the legend is 150px, as defined by
+ * conf.leftMargin in user-journey-config.js
+ */
+ expect(diagramStartX - maxLineWidth).to.be.closeTo(150, 2);
+ });
+ });
+ });
});
diff --git a/cypress/integration/rendering/radar.spec.js b/cypress/integration/rendering/radar.spec.js
new file mode 100644
index 000000000..b0bc3f6e0
--- /dev/null
+++ b/cypress/integration/rendering/radar.spec.js
@@ -0,0 +1,79 @@
+import { imgSnapshotTest } from '../../helpers/util';
+
+describe('radar structure', () => {
+ it('should render a simple radar diagram', () => {
+ imgSnapshotTest(
+ `radar-beta
+ title Best Radar Ever
+ axis A, B, C
+ curve c1{1, 2, 3}
+ `
+ );
+ });
+
+ it('should render a radar diagram with multiple curves', () => {
+ imgSnapshotTest(
+ `radar-beta
+ title Best Radar Ever
+ axis A, B, C
+ curve c1{1, 2, 3}
+ curve c2{2, 3, 1}
+ `
+ );
+ });
+
+ it('should render a complex radar diagram', () => {
+ imgSnapshotTest(
+ `radar-beta
+ title My favorite ninjas
+ axis Agility, Speed, Strength
+ axis Stam["Stamina"] , Intel["Intelligence"]
+
+ curve Ninja1["Naruto Uzumaki"]{
+ Agility 2, Speed 2,
+ Strength 3, Stam 5,
+ Intel 0
+ }
+ curve Ninja2["Sasuke"]{2, 3, 4, 1, 5}
+ curve Ninja3 {3, 2, 1, 5, 4}
+
+ showLegend true
+ ticks 3
+ max 8
+ min 0
+ graticule polygon
+ `
+ );
+ cy.get('svg').should((svg) => {
+ expect(svg).to.have.length(1);
+ });
+ });
+
+ it('should render radar diagram with config override', () => {
+ imgSnapshotTest(
+ `radar-beta
+ title Best Radar Ever
+ axis A,B,C
+ curve mycurve{1,2,3}`,
+ { radar: { marginTop: 100, axisScaleFactor: 0.5 } }
+ );
+ });
+
+ it('should parse radar diagram with theme override', () => {
+ imgSnapshotTest(
+ `radar-beta
+ axis A,B,C
+ curve mycurve{1,2,3}`,
+ { theme: 'base', themeVariables: { fontSize: 80, cScale0: '#FF0000' } }
+ );
+ });
+
+ it('should handle radar diagram with radar style override', () => {
+ imgSnapshotTest(
+ `radar-beta
+ axis A,B,C
+ curve mycurve{1,2,3}`,
+ { theme: 'base', themeVariables: { radar: { axisColor: '#FF0000' } } }
+ );
+ });
+});
diff --git a/cypress/integration/rendering/requirementDiagram-unified.spec.js b/cypress/integration/rendering/requirementDiagram-unified.spec.js
new file mode 100644
index 000000000..48b1a0d61
--- /dev/null
+++ b/cypress/integration/rendering/requirementDiagram-unified.spec.js
@@ -0,0 +1,703 @@
+import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
+
+const testOptions = [
+ { description: '', options: { logLevel: 1 } },
+ { description: 'ELK: ', options: { logLevel: 1, layout: 'elk' } },
+ { description: 'HD: ', options: { logLevel: 1, look: 'handDrawn' } },
+];
+
+describe('Requirement Diagram Unified', () => {
+ testOptions.forEach(({ description, options }) => {
+ it(`${description}should render a simple Requirement diagram`, () => {
+ imgSnapshotTest(
+ `
+ requirementDiagram
+ requirement test_req {
+ id: 1
+ text: the test text.
+ risk: high
+ verifymethod: test
+ }
+
+ element test_entity {
+ type: simulation
+ }
+
+ test_entity - satisfies -> test_req
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render a simple Requirement diagram without htmlLabels`, () => {
+ imgSnapshotTest(
+ `
+ requirementDiagram
+ requirement test_req {
+ id: 1
+ text: the test text.
+ risk: high
+ verifymethod: test
+ }
+
+ element test_entity {
+ type: simulation
+ }
+
+ test_entity - satisfies -> test_req
+ `,
+ { ...options, htmlLabels: false }
+ );
+ });
+
+ it(`${description}should render a not-so-simple Requirement diagram`, () => {
+ imgSnapshotTest(
+ `
+ requirementDiagram
+
+ requirement test_req {
+ id: 1
+ text: the test text.
+ risk: high
+ verifymethod: test
+ }
+
+ functionalRequirement test_req2 {
+ id: 1.1
+ text: the second test text.
+ risk: low
+ verifymethod: inspection
+ }
+
+ performanceRequirement test_req3 {
+ id: 1.2
+ text: the third test text.
+ risk: medium
+ verifymethod: demonstration
+ }
+
+ interfaceRequirement test_req4 {
+ id: 1.2.1
+ text: the fourth test text.
+ risk: medium
+ verifymethod: analysis
+ }
+
+ physicalRequirement test_req5 {
+ id: 1.2.2
+ text: the fifth test text.
+ risk: medium
+ verifymethod: analysis
+ }
+
+ designConstraint test_req6 {
+ id: 1.2.3
+ text: the sixth test text.
+ risk: medium
+ verifymethod: analysis
+ }
+
+ element test_entity {
+ type: simulation
+ }
+
+ element test_entity2 {
+ type: word doc
+ docRef: reqs/test_entity
+ }
+
+ element test_entity3 {
+ type: "test suite"
+ docRef: github.com/all_the_tests
+ }
+
+
+ test_entity - satisfies -> test_req2
+ test_req - traces -> test_req2
+ test_req - contains -> test_req3
+ test_req3 - contains -> test_req4
+ test_req4 - derives -> test_req5
+ test_req5 - refines -> test_req6
+ test_entity3 - verifies -> test_req5
+ test_req <- copies - test_entity2
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render a not-so-simple Requirement diagram without htmlLabels`, () => {
+ imgSnapshotTest(
+ `
+ requirementDiagram
+
+ requirement test_req {
+ id: 1
+ text: the test text.
+ risk: high
+ verifymethod: test
+ }
+
+ functionalRequirement test_req2 {
+ id: 1.1
+ text: the second test text.
+ risk: low
+ verifymethod: inspection
+ }
+
+ performanceRequirement test_req3 {
+ id: 1.2
+ text: the third test text.
+ risk: medium
+ verifymethod: demonstration
+ }
+
+ interfaceRequirement test_req4 {
+ id: 1.2.1
+ text: the fourth test text.
+ risk: medium
+ verifymethod: analysis
+ }
+
+ physicalRequirement test_req5 {
+ id: 1.2.2
+ text: the fifth test text.
+ risk: medium
+ verifymethod: analysis
+ }
+
+ designConstraint test_req6 {
+ id: 1.2.3
+ text: the sixth test text.
+ risk: medium
+ verifymethod: analysis
+ }
+
+ element test_entity {
+ type: simulation
+ }
+
+ element test_entity2 {
+ type: word doc
+ docRef: reqs/test_entity
+ }
+
+ element test_entity3 {
+ type: "test suite"
+ docRef: github.com/all_the_tests
+ }
+
+
+ test_entity - satisfies -> test_req2
+ test_req - traces -> test_req2
+ test_req - contains -> test_req3
+ test_req3 - contains -> test_req4
+ test_req4 - derives -> test_req5
+ test_req5 - refines -> test_req6
+ test_entity3 - verifies -> test_req5
+ test_req <- copies - test_entity2
+ `,
+ { ...options, htmlLabels: false }
+ );
+ });
+
+ it(`${description}should render multiple Requirement diagrams`, () => {
+ imgSnapshotTest(
+ [
+ `
+ requirementDiagram
+
+ requirement test_req {
+ id: 1
+ text: the test text.
+ risk: high
+ verifymethod: test
+ }
+
+ element test_entity {
+ type: simulation
+ }
+
+ test_entity - satisfies -> test_req
+ `,
+ `
+ requirementDiagram
+
+ requirement test_req {
+ id: 1
+ text: the test text.
+ risk: high
+ verifymethod: test
+ }
+
+ element test_entity {
+ type: simulation
+ }
+
+ test_entity - satisfies -> test_req
+ `,
+ ],
+ options
+ );
+ });
+
+ it(`${description}should render a Requirement diagram with empty information`, () => {
+ imgSnapshotTest(
+ `
+ requirementDiagram
+ requirement test_req {
+ }
+ element test_entity {
+ }
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render requirements and elements with and without information`, () => {
+ renderGraph(
+ `
+ requirementDiagram
+ requirement test_req {
+ id: 1
+ text: the test text.
+ risk: high
+ verifymethod: test
+ }
+ element test_entity {
+ }
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render requirements and elements with long and short text`, () => {
+ renderGraph(
+ `
+ requirementDiagram
+ requirement test_req {
+ id: 1
+ text: the test text that is long and takes up a lot of space.
+ risk: high
+ verifymethod: test
+ }
+ element test_entity_name_that_is_extra_long {
+ }
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render requirements and elements with long and short text without htmlLabels`, () => {
+ renderGraph(
+ `
+ requirementDiagram
+ requirement test_req {
+ id: 1
+ text: the test text that is long and takes up a lot of space.
+ risk: high
+ verifymethod: test
+ }
+ element test_entity_name_that_is_extra_long {
+ }
+ `,
+ { ...options, htmlLabels: false }
+ );
+ });
+
+ it(`${description}should render requirements and elements with quoted text for spaces`, () => {
+ renderGraph(
+ `
+ requirementDiagram
+ requirement "test req name with spaces" {
+ id: 1
+ text: the test text that is long and takes up a lot of space.
+ risk: high
+ verifymethod: test
+ }
+ element "test entity name that is extra long with spaces" {
+ }
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render requirements and elements with markdown text`, () => {
+ renderGraph(
+ `
+ requirementDiagram
+ requirement "__my bolded name__" {
+ id: 1
+ text: "**Bolded text** _italicized text_"
+ risk: high
+ verifymethod: test
+ }
+ element "*my italicized name*" {
+ type: "**Bolded type** _italicized type_"
+ docref: "*Italicized* __Bolded__"
+ }
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render requirements and elements with markdown text without htmlLabels`, () => {
+ renderGraph(
+ `
+ requirementDiagram
+ requirement "__my bolded name__" {
+ id: 1
+ text: "**Bolded text** _italicized text_"
+ risk: high
+ verifymethod: test
+ }
+ element "*my italicized name*" {
+ type: "**Bolded type** _italicized type_"
+ docref: "*Italicized* __Bolded__"
+ }
+ `,
+ { ...options, htmlLabels: false }
+ );
+ });
+
+ it(`${description}should render a simple Requirement diagram with a title`, () => {
+ imgSnapshotTest(
+ `---
+ title: simple Requirement diagram
+ ---
+ requirementDiagram
+
+ requirement test_req {
+ id: 1
+ text: the test text.
+ risk: high
+ verifymethod: test
+ }
+
+ element test_entity {
+ type: simulation
+ }
+
+ test_entity - satisfies -> test_req
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render a Requirement diagram with TB direction`, () => {
+ imgSnapshotTest(
+ `
+ requirementDiagram
+ direction TB
+
+ requirement test_req {
+ id: 1
+ text: the test text.
+ risk: high
+ verifymethod: test
+ }
+
+ element test_entity {
+ type: simulation
+ }
+
+ test_entity - satisfies -> test_req
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render a Requirement diagram with BT direction`, () => {
+ imgSnapshotTest(
+ `
+ requirementDiagram
+ direction BT
+
+ requirement test_req {
+ id: 1
+ text: the test text.
+ risk: high
+ verifymethod: test
+ }
+
+ element test_entity {
+ type: simulation
+ }
+
+ test_entity - satisfies -> test_req
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render a Requirement diagram with LR direction`, () => {
+ imgSnapshotTest(
+ `
+ requirementDiagram
+ direction LR
+
+ requirement test_req {
+ id: 1
+ text: the test text.
+ risk: high
+ verifymethod: test
+ }
+
+ element test_entity {
+ type: simulation
+ }
+
+ test_entity - satisfies -> test_req
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render a Requirement diagram with RL direction`, () => {
+ imgSnapshotTest(
+ `
+ requirementDiagram
+ direction RL
+
+ requirement test_req {
+ id: 1
+ text: the test text.
+ risk: high
+ verifymethod: test
+ }
+
+ element test_entity {
+ type: simulation
+ }
+
+ test_entity - satisfies -> test_req
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render requirements and elements with styles applied from style statement`, () => {
+ imgSnapshotTest(
+ `
+ requirementDiagram
+
+ requirement test_req {
+ id: 1
+ text: the test text.
+ risk: high
+ verifymethod: test
+ }
+
+ element test_entity {
+ type: simulation
+ }
+
+ test_entity - satisfies -> test_req
+
+ style test_req,test_entity fill:#f9f,stroke:blue, color:grey, font-weight:bold
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render requirements and elements with styles applied from style statement without htmlLabels`, () => {
+ imgSnapshotTest(
+ `
+ requirementDiagram
+
+ requirement test_req {
+ id: 1
+ text: the test text.
+ risk: high
+ verifymethod: test
+ }
+
+ element test_entity {
+ type: simulation
+ }
+
+ test_entity - satisfies -> test_req
+
+ style test_req,test_entity fill:#f9f,stroke:blue, color:grey, font-weight:bold
+ `,
+ { ...options, htmlLabels: false }
+ );
+ });
+
+ it(`${description}should render requirements and elements with styles applied from class statement`, () => {
+ imgSnapshotTest(
+ `
+requirementDiagram
+
+ requirement test_req {
+ id: 1
+ text: the test text.
+ risk: high
+ verifymethod: test
+ }
+
+ element test_entity {
+ type: simulation
+ }
+
+ test_entity - satisfies -> test_req
+ classDef bold font-weight: bold
+ classDef blue stroke:lightblue, color: #0000FF
+ class test_entity bold
+ class test_req blue, bold
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render requirements and elements with styles applied from class statement without htmlLabels`, () => {
+ imgSnapshotTest(
+ `
+ requirementDiagram
+
+ requirement test_req {
+ id: 1
+ text: the test text.
+ risk: high
+ verifymethod: test
+ }
+
+ element test_entity {
+ type: simulation
+ }
+
+ test_entity - satisfies -> test_req
+ classDef bold font-weight: bold
+ classDef blue stroke:lightblue, color: #0000FF
+ class test_entity bold
+ class test_req blue, bold
+ `,
+ { ...options, htmlLabels: false }
+ );
+ });
+
+ it(`${description}should render requirements and elements with styles applied from classes with shorthand syntax`, () => {
+ imgSnapshotTest(
+ `
+ requirementDiagram
+
+ requirement test_req:::blue {
+ id: 1
+ text: the test text.
+ risk: high
+ verifymethod: test
+ }
+
+ element test_entity {
+ type: simulation
+ }
+
+ test_entity - satisfies -> test_req
+ classDef bold font-weight: bold
+ classDef blue stroke:lightblue, color: #0000FF
+ test_entity:::bold
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render requirements and elements with styles applied from classes with shorthand syntax without htmlLabels`, () => {
+ imgSnapshotTest(
+ `
+ requirementDiagram
+
+ requirement test_req:::blue {
+ id: 1
+ text: the test text.
+ risk: high
+ verifymethod: test
+ }
+
+ element test_entity {
+ type: simulation
+ }
+
+ test_entity - satisfies -> test_req
+ classDef bold font-weight: bold
+ classDef blue stroke:lightblue, color: #0000FF
+ test_entity:::bold
+ `,
+ { ...options, htmlLabels: false }
+ );
+ });
+
+ it(`${description}should render requirements and elements with styles applied from the default class and other styles`, () => {
+ imgSnapshotTest(
+ `
+requirementDiagram
+
+ requirement test_req:::blue {
+ id: 1
+ text: the test text.
+ risk: high
+ verifymethod: test
+ }
+
+ element test_entity {
+ type: simulation
+ }
+
+ test_entity - satisfies -> test_req
+ classDef blue stroke:lightblue, color:blue
+ classDef default fill:pink
+ style test_entity color:green
+ `,
+ options
+ );
+ });
+
+ it(`${description}should render requirements and elements with styles applied from the default class and other styles without htmlLabels`, () => {
+ imgSnapshotTest(
+ `
+ requirementDiagram
+
+ requirement test_req:::blue {
+ id: 1
+ text: the test text.
+ risk: high
+ verifymethod: test
+ }
+
+ element test_entity {
+ type: simulation
+ }
+
+ test_entity - satisfies -> test_req
+ classDef blue stroke:lightblue, color:blue
+ classDef default fill:pink
+ style test_entity color:green
+ `,
+ { ...options, htmlLabels: false }
+ );
+ });
+
+ it(`${description}should render a Requirement diagram with a theme`, () => {
+ imgSnapshotTest(
+ `
+---
+ theme: forest
+---
+ requirementDiagram
+
+ requirement test_req:::blue {
+ id: 1
+ text: the test text.
+ risk: high
+ verifymethod: test
+ }
+
+ element test_entity {
+ type: simulation
+ }
+
+ test_entity - satisfies -> test_req
+ `,
+ options
+ );
+ });
+ });
+});
diff --git a/cypress/platform/ashish2.html b/cypress/platform/ashish2.html
index f9132d2e2..351dcabc2 100644
--- a/cypress/platform/ashish2.html
+++ b/cypress/platform/ashish2.html
@@ -4,7 +4,7 @@
-
+
diff --git a/cypress/platform/xss10.html b/cypress/platform/xss10.html
index 91b0b94ac..9814fed41 100644
--- a/cypress/platform/xss10.html
+++ b/cypress/platform/xss10.html
@@ -4,7 +4,7 @@
+
+ --- + config: + htmlLabels: false + look: handDrawn + theme: forest + --- + erDiagram + _**hiร**_[*test*] { + *__List~List~int~~sdfds__* __driversLicense__ PK "***The l๐icense #***" + *string(99)~T~~~~~~* firstName "Only 99+
characters are a
llowed dsfsdfsdfsdfs" + ~str ing~ lastName + string phone UK + int age + } + style PERSON color:red, stroke:blue,fill:#f9f + classDef test,test2 stroke:red + class PERSON test,test2 +
+ erDiagram + CAR { + string registrationNumber + string make + string model + } + PERSON { + string firstName + string lastName + int age + } + + CAR:::someclass + PERSON:::anotherclass,someclass + + classDef someclass fill:#f96 + classDef anotherclass color:blue ++
+ --- + config: + htmlLabels: false + layout: elk + look: handDrawn + theme: forest + --- + erDiagram + "hi" }o..o{ ORDER : places + style hi fill:lightblue ++
+ --- + config: + htmlLabels: false + look: handDrawn + layout: elk + --- + erDiagram + CAR ||--|{ NAMED-DRIVER : allows + PERSON ||..o{ NAMED-DRIVER : is ++
+ --- + config: + htmlLabels: true + look: handDrawn + theme: forest + --- + erDiagram + CAR ||--o{ NAMED-DRIVER : allows + CAR { + test test PK "comment" + string make + string model + string[] parts + } + PERSON ||--o{ NAMED-DRIVER : is + PERSON ||--o{ CAR : is + PERSON { + string driversLicense PK "The license #" + string(99) firstName "Only 99 characters are allowed" + string lastName + string phone UK + int age + } + NAMED-DRIVER { + string carRegistrationNumber PK, FK + string driverLicence PK, FK + } + MANUFACTURER only one to zero or more CAR : makes ++
+ --- + title: simple ER diagram + config: + theme: forest + --- + erDiagram + direction TB + p[Pers๐on] { + string firstName + string lastName + } + a["Customer Account"] { + string email + } + p ||--o| a : has + ++
+ --- + config: + layout: elk + --- + erDiagram + CUSTOMER }|..|{ DELIVERY-ADDRESS : has + CUSTOMER ||--o{ ORDER : places + CUSTOMER ||--o{ INVOICE : "liable for" + DELIVERY-ADDRESS ||--o{ ORDER : receives + INVOICE ||--|{ ORDER : covers + ORDER ||--|{ ORDER-ITEM : includes + PRODUCT-CATEGORY ||--|{ PRODUCT : contains + PRODUCT ||--o{ ORDER-ITEM : "ordered in" ++
+--- + config: + layout: elk +--- + erDiagram + rental{ + ~timestamp with time zone~ rental_date "NN" + ~integer~ inventory_id "NN" + ~integer~ customer_id "NN" + ~timestamp with time zone~ return_date + ~integer~ staff_id "NN" + ~integer~ rental_id "NN" + ~timestamp with time zone~ last_update "NN" + } + film_actor{ + ~integer~ actor_id "NN" + ~integer~ film_id "NN" + ~timestamp with time zone~ last_update "NN" + } + film{ + ~text~ title "NN" + ~text~ description + ~public.year~ release_year + ~integer~ language_id "NN" + ~integer~ original_language_id + ~smallint~ length + ~text[]~ special_features + ~tsvector~ fulltext "NN" + ~integer~ film_id "NN" + ~smallint~ rental_duration "NN" + ~numeric(4,2)~ rental_rate "NN" + ~numeric(5,2)~ replacement_cost "NN" + ~public.mpaa_rating~ rating + ~timestamp with time zone~ last_update "NN" + } + customer{ + ~integer~ store_id "NN" + ~text~ first_name "NN" + ~text~ last_name "NN" + ~text~ email + ~integer~ address_id "NN" + ~integer~ active + ~integer~ customer_id "NN" + ~boolean~ activebool "NN" + ~date~ create_date "NN" + ~timestamp with time zone~ last_update + } + film_category{ + ~integer~ film_id "NN" + ~integer~ category_id "NN" + ~timestamp with time zone~ last_update "NN" + } + actor{ + ~text~ first_name "NN" + ~text~ last_name "NN" + ~integer~ actor_id "NN" + ~timestamp with time zone~ last_update "NN" + } + store{ + ~integer~ manager_staff_id "NN" + ~integer~ address_id "NN" + ~integer~ store_id "NN" + ~timestamp with time zone~ last_update "NN" + } + city{ + ~text~ city "NN" + ~integer~ country_id "NN" + ~integer~ city_id "NN" + ~timestamp with time zone~ last_update "NN" + } + language{ + ~character(20)~ name "NN" + ~integer~ language_id "NN" + ~timestamp with time zone~ last_update "NN" + } + payment{ + ~integer~ customer_id "NN" + ~integer~ staff_id "NN" + ~integer~ rental_id "NN" + ~numeric(5,2)~ amount "NN" + ~timestamp with time zone~ payment_date "NN" + ~integer~ payment_id "NN" + } + category{ + ~text~ name "NN" + ~integer~ category_id "NN" + ~timestamp with time zone~ last_update "NN" + } + inventory{ + ~integer~ film_id "NN" + ~integer~ store_id "NN" + ~integer~ inventory_id "NN" + ~timestamp with time zone~ last_update "NN" + } + address{ + ~text~ address "NN" + ~text~ address2 + ~text~ district "NN" + ~integer~ city_id "NN" + ~text~ postal_code + ~text~ phone "NN" + ~integer~ address_id "NN" + ~timestamp with time zone~ last_update "NN" + } + staff{ + ~text~ first_name "NN" + ~text~ last_name "NN" + ~integer~ address_id "NN" + ~text~ email + ~integer~ store_id "NN" + ~text~ username "NN" + ~text~ password + ~bytea~ picture + ~integer~ staff_id "NN" + ~boolean~ active "NN" + ~timestamp with time zone~ last_update "NN" + } + country{ + ~text~ country "NN" + ~integer~ country_id "NN" + ~timestamp with time zone~ last_update "NN" + } + film_actor }|..|| film : film_actor_film_id_fkey + film_actor }|..|| actor : film_actor_actor_id_fkey + address }|..|| city : address_city_id_fkey + city }|..|| country : city_country_id_fkey + customer }|..|| store : customer_store_id_fkey + customer }|..|| address : customer_address_id_fkey + film }|..|| language : film_original_language_id_fkey + film }|..|| language : film_language_id_fkey + film_category }|..|| film : film_category_film_id_fkey + film_category }|..|| category : film_category_category_id_fkey + inventory }|..|| store : inventory_store_id_fkey ++