Compare commits

..

6 Commits

Author SHA1 Message Date
Sidharth Vinod
cb5e157bbc Fix config 2024-08-22 19:33:53 +05:30
Sidharth Vinod
a0c56d8448 Fix versions 2024-08-22 19:23:22 +05:30
Sidharth Vinod
ddb927b75e Fix peer dependency 2024-08-22 19:01:13 +05:30
Sidharth Vinod
c5c74e7fe2 bump version 2024-08-22 18:51:58 +05:30
Sidharth Vinod
1931d8d67b Fix versions 2024-08-22 18:37:48 +05:30
Sidharth Vinod
a84c2bdf75 Fix versions 2024-08-22 18:30:25 +05:30
500 changed files with 15487 additions and 45876 deletions

View File

@@ -1,9 +1,3 @@
export interface PackageOptions {
name: string;
packageName: string;
file: string;
}
/** /**
* Shared common options for both ESBuild and Vite * Shared common options for both ESBuild and Vite
*/ */
@@ -33,4 +27,4 @@ export const packageOptions = {
packageName: 'mermaid-layout-elk', packageName: 'mermaid-layout-elk',
file: 'layouts.ts', file: 'layouts.ts',
}, },
} as const satisfies Record<string, PackageOptions>; } as const;

View File

@@ -19,15 +19,12 @@ const MERMAID_CONFIG_DIAGRAM_KEYS = [
'xyChart', 'xyChart',
'requirement', 'requirement',
'mindmap', 'mindmap',
'kanban',
'timeline', 'timeline',
'gitGraph', 'gitGraph',
'c4', 'c4',
'sankey', 'sankey',
'block', 'block',
'packet', 'packet',
'architecture',
'radar',
] as const; ] as const;
/** /**

View File

@@ -26,7 +26,6 @@ concat
controlx controlx
controly controly
CSSCLASS CSSCLASS
curv
CYLINDEREND CYLINDEREND
CYLINDERSTART CYLINDERSTART
DAGA DAGA
@@ -56,7 +55,6 @@ GENERICTYPE
getBoundarys getBoundarys
grammr grammr
graphtype graphtype
halign
iife iife
interp interp
introdcued introdcued
@@ -68,7 +66,6 @@ Kaufmann
keyify keyify
LABELPOS LABELPOS
LABELTYPE LABELTYPE
layoutstop
lcov lcov
LEFTOF LEFTOF
Lexa Lexa
@@ -141,7 +138,6 @@ tsdoc
typeof typeof
typestr typestr
unshift unshift
urlsafe
verifymethod verifymethod
VERIFYMTHD VERIFYMTHD
WARN_DOCSDIR_DOESNT_MATCH WARN_DOCSDIR_DOESNT_MATCH

View File

@@ -28,9 +28,6 @@ dictionaryDefinitions:
- name: suggestions - name: suggestions
words: words:
- none - none
- disp
- subproc
- tria
suggestWords: suggestWords:
- seperator:separator - seperator:separator
- vertice:vertex - vertice:vertex

View File

@@ -24,14 +24,11 @@ Doctave
DokuWiki DokuWiki
dompurify dompurify
elkjs elkjs
fcose
fontawesome fontawesome
Forgejo
Foswiki Foswiki
Gitea Gitea
graphlib graphlib
Grav Grav
icones
iconify iconify
Inkdrop Inkdrop
jiti jiti
@@ -61,7 +58,6 @@ rehype
roughjs roughjs
rscratch rscratch
shiki shiki
Slidev
sparkline sparkline
sphinxcontrib sphinxcontrib
ssim ssim

View File

@@ -1,18 +1,15 @@
Adamiecki Adamiecki
arrowend arrowend
Bendpoints
bmatrix bmatrix
braintree braintree
catmull catmull
compositTitleSize compositTitleSize
curv
doublecircle doublecircle
elems elems
gantt gantt
gitgraph gitgraph
gzipped gzipped
handDrawn handDrawn
kanban
knsv knsv
Knut Knut
marginx marginx
@@ -26,7 +23,6 @@ multigraph
nodesep nodesep
NOTEGROUP NOTEGROUP
Pinterest Pinterest
procs
rankdir rankdir
ranksep ranksep
rect rect

View File

@@ -4,4 +4,3 @@ handDrawn
KOEPF KOEPF
neato neato
newbranch newbranch
validify

View File

@@ -8,10 +8,7 @@ import { defaultOptions, getBuildConfig } from './util.js';
const shouldVisualize = process.argv.includes('--visualize'); const shouldVisualize = process.argv.includes('--visualize');
const buildPackage = async (entryName: keyof typeof packageOptions) => { const buildPackage = async (entryName: keyof typeof packageOptions) => {
const commonOptions: MermaidBuildOptions = { const commonOptions: MermaidBuildOptions = { ...defaultOptions, entryName } as const;
...defaultOptions,
options: packageOptions[entryName],
} as const;
const buildConfigs: MermaidBuildOptions[] = [ const buildConfigs: MermaidBuildOptions[] = [
// package.mjs // package.mjs
{ ...commonOptions }, { ...commonOptions },
@@ -43,7 +40,7 @@ const buildPackage = async (entryName: keyof typeof packageOptions) => {
continue; continue;
} }
const fileName = Object.keys(metafile.outputs) const fileName = Object.keys(metafile.outputs)
.find((file) => !file.includes('chunks') && file.endsWith('js'))! .find((file) => !file.includes('chunks') && file.endsWith('js'))
.replace('dist/', ''); .replace('dist/', '');
// Upload metafile into https://esbuild.github.io/analyze/ // Upload metafile into https://esbuild.github.io/analyze/
await writeFile(`stats/${fileName}.meta.json`, JSON.stringify(metafile)); await writeFile(`stats/${fileName}.meta.json`, JSON.stringify(metafile));

View File

@@ -9,18 +9,13 @@ import { generateLangium } from '../.build/generateLangium.js';
import { defaultOptions, getBuildConfig } from './util.js'; import { defaultOptions, getBuildConfig } from './util.js';
const configs = Object.values(packageOptions).map(({ packageName }) => const configs = Object.values(packageOptions).map(({ packageName }) =>
getBuildConfig({ getBuildConfig({ ...defaultOptions, minify: false, core: false, entryName: packageName })
...defaultOptions,
minify: false,
core: false,
options: packageOptions[packageName],
})
); );
const mermaidIIFEConfig = getBuildConfig({ const mermaidIIFEConfig = getBuildConfig({
...defaultOptions, ...defaultOptions,
minify: false, minify: false,
core: false, core: false,
options: packageOptions.mermaid, entryName: 'mermaid',
format: 'iife', format: 'iife',
}); });
configs.push(mermaidIIFEConfig); configs.push(mermaidIIFEConfig);

View File

@@ -3,7 +3,7 @@ import { fileURLToPath } from 'url';
import type { BuildOptions } from 'esbuild'; import type { BuildOptions } from 'esbuild';
import { readFileSync } from 'fs'; import { readFileSync } from 'fs';
import jsonSchemaPlugin from './jsonSchemaPlugin.js'; import jsonSchemaPlugin from './jsonSchemaPlugin.js';
import type { PackageOptions } from '../.build/common.js'; import { packageOptions } from '../.build/common.js';
import { jisonPlugin } from './jisonPlugin.js'; import { jisonPlugin } from './jisonPlugin.js';
const __dirname = fileURLToPath(new URL('.', import.meta.url)); const __dirname = fileURLToPath(new URL('.', import.meta.url));
@@ -13,10 +13,10 @@ export interface MermaidBuildOptions extends BuildOptions {
core: boolean; core: boolean;
metafile: boolean; metafile: boolean;
format: 'esm' | 'iife'; format: 'esm' | 'iife';
options: PackageOptions; entryName: keyof typeof packageOptions;
} }
export const defaultOptions: Omit<MermaidBuildOptions, 'entryName' | 'options'> = { export const defaultOptions: Omit<MermaidBuildOptions, 'entryName'> = {
minify: false, minify: false,
metafile: false, metafile: false,
core: false, core: false,
@@ -52,14 +52,9 @@ const getFileName = (fileName: string, { core, format, minify }: MermaidBuildOpt
}; };
export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => { export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => {
const { const { core, entryName, metafile, format, minify } = options;
core,
metafile,
format,
minify,
options: { name, file, packageName },
} = options;
const external: string[] = ['require', 'fs', 'path']; const external: string[] = ['require', 'fs', 'path'];
const { name, file, packageName } = packageOptions[entryName];
const outFileName = getFileName(name, options); const outFileName = getFileName(name, options);
const output: BuildOptions = buildOptions({ const output: BuildOptions = buildOptions({
absWorkingDir: resolve(__dirname, `../packages/${packageName}`), absWorkingDir: resolve(__dirname, `../packages/${packageName}`),

View File

@@ -4,7 +4,7 @@ contact_links:
url: https://github.com/mermaid-js/mermaid/discussions url: https://github.com/mermaid-js/mermaid/discussions
about: Ask the Community questions or share your own graphs in our discussions. about: Ask the Community questions or share your own graphs in our discussions.
- name: Discord - name: Discord
url: https://discord.gg/sKeNQX4Wtj url: https://discord.gg/AgrbSrBer3
about: Join our Community on Discord for Help and a casual chat. about: Join our Community on Discord for Help and a casual chat.
- name: Documentation - name: Documentation
url: https://mermaid.js.org url: https://mermaid.js.org

8
.github/lychee.toml vendored
View File

@@ -44,13 +44,7 @@ exclude = [
"https://chromewebstore.google.com", "https://chromewebstore.google.com",
# Drupal 403 # Drupal 403
"https://(www.)?drupal.org", "https://(www.)?drupal.org"
# Swimm returns 404, eventhough the link is valid
"https://docs.swimm.io",
# Timeout
"https://huehive.co"
] ]
# Exclude all private IPs from checking. # Exclude all private IPs from checking.

View File

@@ -7,19 +7,17 @@ on:
permissions: permissions:
contents: read contents: read
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs: jobs:
autofix: autofix:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@v4
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - uses: pnpm/action-setup@v4
# uses version from "packageManager" field in package.json # uses version from "packageManager" field in package.json
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 uses: actions/setup-node@v4
with: with:
cache: pnpm cache: pnpm
node-version-file: '.node-version' node-version-file: '.node-version'
@@ -42,4 +40,4 @@ jobs:
working-directory: ./packages/mermaid working-directory: ./packages/mermaid
run: pnpm run docs:build run: pnpm run docs:build
- uses: autofix-ci/action@551dded8c6cc8a1054039c8bc0b8b48c51dfc6ef # main - uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c

View File

@@ -8,8 +8,6 @@ on:
pull_request: pull_request:
merge_group: merge_group:
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions: permissions:
contents: read contents: read
@@ -18,12 +16,12 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - uses: pnpm/action-setup@v4
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 uses: actions/setup-node@v4
with: with:
cache: pnpm cache: pnpm
node-version-file: '.node-version' node-version-file: '.node-version'

49
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,49 @@
name: Build
on:
push: {}
merge_group:
pull_request:
types:
- opened
- synchronize
- ready_for_review
permissions:
contents: read
jobs:
build-mermaid:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
# uses version from "packageManager" field in package.json
- name: Setup Node.js
uses: actions/setup-node@v4
with:
cache: pnpm
node-version-file: '.node-version'
- name: Install Packages
run: |
pnpm install --frozen-lockfile
env:
CYPRESS_CACHE_FOLDER: .cache/Cypress
- name: Run Build
run: pnpm run build
- name: Upload Mermaid Build as Artifact
uses: actions/upload-artifact@v4
with:
name: mermaid-build
path: packages/mermaid/dist
- name: Upload Mermaid Mindmap Build as Artifact
uses: actions/upload-artifact@v4
with:
name: mermaid-mindmap-build
path: packages/mermaid-mindmap/dist

View File

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

26
.github/workflows/checks.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
on:
push:
merge_group:
pull_request:
types:
- opened
- synchronize
- ready_for_review
name: Static analysis on Test files
jobs:
check-tests:
runs-on: ubuntu-latest
name: check tests
if: github.repository_owner == 'mermaid-js'
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: testomatio/check-tests@stable
with:
framework: cypress
tests: './cypress/e2e/**/**.spec.js'
token: ${{ secrets.GITHUB_TOKEN }}
has-tests-label: true

View File

@@ -11,9 +11,6 @@ on:
- synchronize - synchronize
- ready_for_review - ready_for_review
permissions: # added using https://github.com/step-security/secure-repo
contents: read
jobs: jobs:
analyze: analyze:
name: Analyze name: Analyze
@@ -32,11 +29,11 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 uses: github/codeql-action/init@v3
with: with:
config-file: ./.github/codeql/codeql-config.yml config-file: ./.github/codeql/codeql-config.yml
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
@@ -48,7 +45,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # 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) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 uses: github/codeql-action/autobuild@v3
# Command-line programs to run using the OS shell. # 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 # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@@ -62,4 +59,4 @@ jobs:
# make release # make release
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 uses: github/codeql-action/analyze@v3

View File

@@ -15,6 +15,6 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: 'Checkout Repository' - name: 'Checkout Repository'
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
- name: 'Dependency Review' - name: 'Dependency Review'
uses: actions/dependency-review-action@3b139cfc5fae8b618d3eae3675e383bb1769c019 # v4.5.0 uses: actions/dependency-review-action@v4

View File

@@ -11,8 +11,6 @@ on:
default: master default: master
description: 'Parent branch to use for PRs' description: 'Parent branch to use for PRs'
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions: permissions:
contents: read contents: read
@@ -32,13 +30,13 @@ jobs:
run: | run: |
echo "::error,title=Not using Applitools::APPLITOOLS_API_KEY is empty, disabling Applitools for this run." echo "::error,title=Not using Applitools::APPLITOOLS_API_KEY is empty, disabling Applitools for this run."
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@v4
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - uses: pnpm/action-setup@v4
# uses version from "packageManager" field in package.json # uses version from "packageManager" field in package.json
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 uses: actions/setup-node@v4
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
@@ -54,7 +52,7 @@ jobs:
APPLITOOLS_SERVER_URL: 'https://eyesapi.applitools.com' APPLITOOLS_SERVER_URL: 'https://eyesapi.applitools.com'
- name: Cypress run - name: Cypress run
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 uses: cypress-io/github-action@v4
id: cypress id: cypress
with: with:
start: pnpm run dev start: pnpm run dev

View File

@@ -1,58 +0,0 @@
name: E2E - Generate Timings
on:
# run this workflow every night at 3am
schedule:
- cron: '28 3 * * *'
# or when the user triggers it from GitHub Actions page
workflow_dispatch:
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions:
contents: write
jobs:
timings:
runs-on: ubuntu-latest
container:
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@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Setup Node.js
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version-file: '.node-version'
- name: Install dependencies
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
with:
runTests: false
- name: Cypress run
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
id: cypress
with:
install: false
start: pnpm run dev:coverage
wait-on: 'http://localhost:9000'
browser: chrome
publish-summary: false
env:
VITEST_COVERAGE: true
CYPRESS_COMMIT: ${{ github.sha }}
SPLIT: 1
SPLIT_INDEX: 0
SPLIT_FILE: 'cypress/timings.json'
- name: Commit changes
uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4
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'
- name: Create Pull Request
uses: peter-evans/create-pull-request@v5
with:
branch: release-promotion
title: Update E2E Timings

View File

@@ -2,15 +2,11 @@ name: E2E
on: on:
push: push:
branches: branches-ignore:
- develop - 'gh-readonly-queue/**'
- master
- release/**
pull_request: pull_request:
merge_group: merge_group:
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions: permissions:
contents: read contents: read
@@ -28,8 +24,7 @@ env:
) || ) ||
github.event.before github.event.before
}} }}
RUN_VISUAL_TEST: >- shouldRunParallel: ${{ secrets.CYPRESS_RECORD_KEY != '' && !(github.event_name == 'push' && github.ref == 'refs/heads/develop') }}
${{ github.repository == 'mermaid-js/mermaid' && (github.event_name != 'pull_request' || !startsWith(github.head_ref, 'renovate/')) }}
jobs: jobs:
cache: cache:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -37,29 +32,30 @@ jobs:
image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1 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 options: --user 1001
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@v4
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - uses: pnpm/action-setup@v4
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 uses: actions/setup-node@v4
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
- name: Cache snapshots - name: Cache snapshots
id: cache-snapshot id: cache-snapshot
uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 uses: actions/cache@v4
with: with:
save-always: true
path: ./cypress/snapshots path: ./cypress/snapshots
key: ${{ runner.os }}-snapshots-${{ env.targetHash }} 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. # 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 - name: Switch to base branch
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }} if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
with: with:
ref: ${{ env.targetHash }} ref: ${{ env.targetHash }}
- name: Install dependencies - name: Install dependencies
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }} if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 uses: cypress-io/github-action@v6
with: with:
# just perform install # just perform install
runTests: false runTests: false
@@ -80,28 +76,28 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
containers: [1, 2, 3, 4, 5] containers: [1, 2, 3, 4]
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@v4
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - uses: pnpm/action-setup@v4
# uses version from "packageManager" field in package.json # uses version from "packageManager" field in package.json
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 uses: actions/setup-node@v4
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
# These cached snapshots are downloaded, providing the reference snapshots. # These cached snapshots are downloaded, providing the reference snapshots.
- name: Cache snapshots - name: Cache snapshots
id: cache-snapshot id: cache-snapshot
uses: actions/cache/restore@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 uses: actions/cache/restore@v4
with: with:
path: ./cypress/snapshots path: ./cypress/snapshots
key: ${{ runner.os }}-snapshots-${{ env.targetHash }} key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
- name: Install dependencies - name: Install dependencies
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 uses: cypress-io/github-action@v6
with: with:
runTests: false runTests: false
@@ -117,8 +113,11 @@ jobs:
# Install NPM dependencies, cache them correctly # Install NPM dependencies, cache them correctly
# and run all Cypress tests # and run all Cypress tests
- name: Cypress run - name: Cypress run
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 uses: cypress-io/github-action@v6
id: cypress 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.shouldRunParallel == 'true' || ( matrix.containers == 1 ) }}
with: with:
install: false install: false
start: pnpm run dev:coverage start: pnpm run dev:coverage
@@ -126,20 +125,19 @@ jobs:
browser: chrome browser: chrome
# Disable recording if we don't have an API key # Disable recording if we don't have an API key
# e.g. if this action was run from a fork # e.g. if this action was run from a fork
record: ${{ env.RUN_VISUAL_TEST == 'true' && secrets.CYPRESS_RECORD_KEY != '' }} record: ${{ env.shouldRunParallel == 'true' }}
parallel: ${{ env.shouldRunParallel == 'true' }}
env: env:
ARGOS_PARALLEL: ${{ env.RUN_VISUAL_TEST == 'true' }} CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
ARGOS_PARALLEL_TOTAL: ${{ env.RUN_VISUAL_TEST == 'true' && strategy.job-total || 1 }}
ARGOS_PARALLEL_INDEX: ${{ env.RUN_VISUAL_TEST == 'true' && matrix.containers || 1 }}
CYPRESS_COMMIT: ${{ github.sha }}
CYPRESS_RECORD_KEY: ${{ env.RUN_VISUAL_TEST == 'true' && secrets.CYPRESS_RECORD_KEY || ''}}
SPLIT: ${{ strategy.job-total }}
SPLIT_INDEX: ${{ strategy.job-index }}
SPLIT_FILE: 'cypress/timings.json'
VITEST_COVERAGE: true VITEST_COVERAGE: true
CYPRESS_COMMIT: ${{ github.sha }}
ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}
ARGOS_PARALLEL: ${{ env.shouldRunParallel == 'true' }}
ARGOS_PARALLEL_TOTAL: 4
ARGOS_PARALLEL_INDEX: ${{ matrix.containers }}
- name: Upload Coverage to Codecov - name: Upload Coverage to Codecov
uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 uses: codecov/codecov-action@v4
# Run step only pushes to develop and pull_requests # Run step only pushes to develop and pull_requests
if: ${{ steps.cypress.conclusion == 'success' && (github.event_name == 'pull_request' || github.ref == 'refs/heads/develop')}} if: ${{ steps.cypress.conclusion == 'success' && (github.event_name == 'pull_request' || github.ref == 'refs/heads/develop')}}
with: with:

View File

@@ -4,17 +4,11 @@ on:
issues: issues:
types: [opened] types: [opened]
permissions: # added using https://github.com/step-security/secure-repo
contents: read
jobs: jobs:
triage: triage:
permissions:
issues: write # for andymckay/labeler to label issues
pull-requests: write # for andymckay/labeler to label PRs
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: andymckay/labeler@e6c4322d0397f3240f0e7e30a33b5c5df2d39e90 # 1.0.4 - uses: andymckay/labeler@1.0.4
with: with:
repo-token: '${{ secrets.GITHUB_TOKEN }}' repo-token: '${{ secrets.GITHUB_TOKEN }}'
add-labels: 'Status: Triage' add-labels: 'Status: Triage'

View File

@@ -19,9 +19,6 @@ on:
# * is a special character in YAML so you have to quote this string # * is a special character in YAML so you have to quote this string
- cron: '30 8 * * *' - cron: '30 8 * * *'
permissions: # added using https://github.com/step-security/secure-repo
contents: read
jobs: jobs:
link-checker: link-checker:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -29,17 +26,17 @@ jobs:
# lychee only uses the GITHUB_TOKEN to avoid rate-limiting # lychee only uses the GITHUB_TOKEN to avoid rate-limiting
contents: read contents: read
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@v4
- name: Restore lychee cache - name: Restore lychee cache
uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 uses: actions/cache@v4
with: with:
path: .lycheecache path: .lycheecache
key: cache-lychee-${{ github.sha }} key: cache-lychee-${{ github.sha }}
restore-keys: cache-lychee- restore-keys: cache-lychee-
- name: Link Checker - name: Link Checker
uses: lycheeverse/lychee-action@f613c4a64e50d792e0b31ec34bbcbba12263c6a6 # v2.3.0 uses: lycheeverse/lychee-action@v1.9.3
with: with:
args: >- args: >-
--config .github/lychee.toml --config .github/lychee.toml

View File

@@ -4,32 +4,26 @@ on:
push: push:
merge_group: merge_group:
pull_request: pull_request:
types:
- opened
- synchronize
- ready_for_review
workflow_dispatch: workflow_dispatch:
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions: permissions:
contents: write contents: write
jobs: jobs:
docker-lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: hadolint/hadolint-action@54c9adbab1582c2ef04b2016b760714a4bfde3cf # v3.1.0
with:
verbose: true
lint: lint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@v4
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - uses: pnpm/action-setup@v4
# uses version from "packageManager" field in package.json # uses version from "packageManager" field in package.json
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 uses: actions/setup-node@v4
with: with:
cache: pnpm cache: pnpm
node-version-file: '.node-version' node-version-file: '.node-version'
@@ -88,10 +82,3 @@ jobs:
working-directory: ./packages/mermaid working-directory: ./packages/mermaid
continue-on-error: ${{ github.event_name == 'push' }} continue-on-error: ${{ github.event_name == 'push' }}
run: pnpm run docs:verify run: pnpm run docs:verify
- uses: testomatio/check-tests@0ea638fcec1820cf2e7b9854fdbdd04128a55bd4 # stable
with:
framework: cypress
tests: './cypress/e2e/**/**.spec.js'
token: ${{ secrets.GITHUB_TOKEN }}
has-tests-label: true

View File

@@ -22,7 +22,7 @@ jobs:
pull-requests: write # write permission is required to label PRs pull-requests: write # write permission is required to label PRs
steps: steps:
- name: Label PR - name: Label PR
uses: release-drafter/release-drafter@b1476f6e6eb133afa41ed8589daba6dc69b4d3f5 # v6.1.0 uses: release-drafter/release-drafter@v6
with: with:
config-name: pr-labeler.yml config-name: pr-labeler.yml
disable-autolabeler: false disable-autolabeler: false

View File

@@ -23,12 +23,12 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v4
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - uses: pnpm/action-setup@v4
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 uses: actions/setup-node@v4
with: with:
cache: pnpm cache: pnpm
node-version-file: '.node-version' node-version-file: '.node-version'
@@ -37,13 +37,13 @@ jobs:
run: pnpm install --frozen-lockfile run: pnpm install --frozen-lockfile
- name: Setup Pages - name: Setup Pages
uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0 uses: actions/configure-pages@v4
- name: Run Build - name: Run Build
run: pnpm --filter mermaid run docs:build:vitepress run: pnpm --filter mermaid run docs:build:vitepress
- name: Upload artifact - name: Upload artifact
uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1 uses: actions/upload-pages-artifact@v3
with: with:
path: packages/mermaid/src/vitepress/.vitepress/dist path: packages/mermaid/src/vitepress/.vitepress/dist
@@ -56,4 +56,4 @@ jobs:
steps: steps:
- name: Deploy to GitHub Pages - name: Deploy to GitHub Pages
id: deployment id: deployment
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 uses: actions/deploy-pages@v4

View File

@@ -9,14 +9,14 @@ jobs:
publish-preview: publish-preview:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - uses: pnpm/action-setup@v4
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 uses: actions/setup-node@v4
with: with:
cache: pnpm cache: pnpm
node-version-file: '.node-version' node-version-file: '.node-version'
@@ -28,7 +28,7 @@ jobs:
CYPRESS_CACHE_FOLDER: .cache/Cypress CYPRESS_CACHE_FOLDER: .cache/Cypress
- name: Install Json - name: Install Json
run: npm i json@11.0.0 --global run: npm i json --global
- name: Publish - name: Publish
working-directory: ./packages/mermaid working-directory: ./packages/mermaid

View File

@@ -1,43 +0,0 @@
name: Preview release
on:
pull_request:
branches: [develop]
types: [opened, synchronize, labeled, ready_for_review]
concurrency:
group: ${{ github.workflow }}-${{ github.event.number }}
cancel-in-progress: true
permissions:
contents: read
actions: write
jobs:
preview:
if: ${{ github.repository_owner == 'mermaid-js' }}
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
issues: write
pull-requests: write
name: Publish preview release
timeout-minutes: 5
steps:
- name: Checkout Repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Setup Node.js
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
cache: pnpm
node-version-file: '.node-version'
- name: Install Packages
run: pnpm install --frozen-lockfile
- name: Publish packages
run: pnpx pkg-pr-new publish --pnpm './packages/*'

47
.github/workflows/release-publish.yml vendored Normal file
View File

@@ -0,0 +1,47 @@
name: Publish release
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: fregante/setup-git-user@v2
- uses: pnpm/action-setup@v4
# uses version from "packageManager" field in package.json
- name: Setup Node.js
uses: actions/setup-node@v4
with:
cache: pnpm
node-version-file: '.node-version'
- name: Install Packages
run: |
pnpm install --frozen-lockfile
npm i json --global
env:
CYPRESS_CACHE_FOLDER: .cache/Cypress
- name: Prepare release
run: |
VERSION=${GITHUB_REF:10}
echo "Preparing release $VERSION"
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 checkout -t origin/master
git merge -m "Release $VERSION" --no-ff release/$VERSION
git push --no-verify
- name: Publish
run: |
npm set //registry.npmjs.org/:_authToken $NPM_TOKEN
npm publish
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

View File

@@ -7,26 +7,18 @@ on:
concurrency: ${{ github.workflow }}-${{ github.ref }} concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions: # added using https://github.com/step-security/secure-repo
contents: read
jobs: jobs:
release: release:
if: github.repository == 'mermaid-js/mermaid'
permissions:
contents: write # to create release (changesets/action)
id-token: write # OpenID Connect token needed for provenance
pull-requests: write # to create pull request (changesets/action)
name: Release name: Release
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout Repo - name: Checkout Repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@v3
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - uses: pnpm/action-setup@v4
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 uses: actions/setup-node@v4
with: with:
cache: pnpm cache: pnpm
node-version-file: '.node-version' node-version-file: '.node-version'
@@ -36,11 +28,10 @@ jobs:
- name: Create Release Pull Request or Publish to npm - name: Create Release Pull Request or Publish to npm
id: changesets id: changesets
uses: changesets/action@c8bada60c408975afd1a20b3db81d6eee6789308 # v1.4.9 uses: changesets/action@v1
with: with:
version: pnpm changeset:version version: pnpm changeset:version
publish: pnpm changeset:publish publish: pnpm changeset:publish
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_CONFIG_PROVENANCE: true

View File

@@ -1,37 +0,0 @@
name: Scorecard supply-chain security
on:
branch_protection_rule:
push:
branches:
- develop
schedule:
- cron: 29 15 * * 0
permissions: read-all
jobs:
analysis:
name: Scorecard analysis
permissions:
id-token: write
security-events: write
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: Run analysis
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@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@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
with:
sarif_file: results.sarif

View File

@@ -9,13 +9,13 @@ jobs:
unit-test: unit-test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@v4
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - uses: pnpm/action-setup@v4
# uses version from "packageManager" field in package.json # uses version from "packageManager" field in package.json
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 uses: actions/setup-node@v4
with: with:
cache: pnpm cache: pnpm
node-version-file: '.node-version' node-version-file: '.node-version'
@@ -38,12 +38,8 @@ jobs:
run: | run: |
pnpm exec vitest run ./packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts --coverage pnpm exec vitest run ./packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts --coverage
- name: Verify out-of-tree build with TypeScript
run: |
pnpm test:check:tsc
- name: Upload Coverage to Codecov - name: Upload Coverage to Codecov
uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 uses: codecov/codecov-action@v4
# Run step only pushes to develop and pull_requests # Run step only pushes to develop and pull_requests
if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/develop' }} if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/develop' }}
with: with:

View File

@@ -8,6 +8,6 @@ jobs:
triage: triage:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: Dunning-Kruger/unlock-issues@b06b7f7e5c3f2eaa1c6d5d89f40930e4d6d9699e # v1 - uses: Dunning-Kruger/unlock-issues@v1
with: with:
repo-token: '${{ secrets.GITHUB_TOKEN }}' repo-token: '${{ secrets.GITHUB_TOKEN }}'

View File

@@ -8,18 +8,18 @@ jobs:
update-browser-list: update-browser-list:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@v4
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - uses: pnpm/action-setup@v4
- run: npx update-browserslist-db@latest - run: npx update-browserslist-db@latest
- name: Commit changes - name: Commit changes
uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4 uses: EndBug/add-and-commit@v9
with: with:
author_name: ${{ github.actor }} author_name: ${{ github.actor }}
author_email: ${{ github.actor }}@users.noreply.github.com author_email: ${{ github.actor }}@users.noreply.github.com
message: 'chore: update browsers list' message: 'chore: update browsers list'
push: false push: false
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6 uses: peter-evans/create-pull-request@v6
with: with:
branch: update-browserslist branch: update-browserslist
title: Update Browserslist title: Update Browserslist

View File

@@ -1,2 +0,0 @@
ignored:
- DL3002 # TODO: Last USER should not be root

View File

@@ -1,2 +1,4 @@
#!/usr/bin/env sh #!/bin/sh
. "$(dirname "$0")/_/husky.sh"
NODE_OPTIONS="--max_old_space_size=8192" pnpm run pre-commit NODE_OPTIONS="--max_old_space_size=8192" pnpm run pre-commit

View File

@@ -1 +1 @@
22.14.0 20.12.2

View File

@@ -1,13 +1,2 @@
FROM node:22.12.0-alpine3.19@sha256:40dc4b415c17b85bea9be05314b4a753f45a4e1716bb31c01182e6c53d51a654 FROM node:20.12.2-alpine3.19 AS base
RUN wget -qO- https://get.pnpm.io/install.sh | ENV="$HOME/.shrc" SHELL="$(which sh)" sh -
USER 0:0
RUN corepack enable \
&& corepack enable pnpm
RUN apk add --no-cache git~=2.43.4 \
&& git config --add --system safe.directory /mermaid
ENV NODE_OPTIONS="--max_old_space_size=8192"
EXPOSE 9000 3333

View File

@@ -15,7 +15,7 @@ Generate diagrams from markdown-like text.
<a href="https://mermaid.live/"><b>Live Editor!</b></a> <a href="https://mermaid.live/"><b>Live Editor!</b></a>
</p> </p>
<p align="center"> <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://discord.gg/sKeNQX4Wtj" title="Discord invite">🙌 Join Us</a> <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://discord.gg/AgrbSrBer3" title="Discord invite">🙌 Join Us</a>
</p> </p>
<p align="center"> <p align="center">
<a href="./README.zh-CN.md">简体中文</a> <a href="./README.zh-CN.md">简体中文</a>
@@ -33,10 +33,9 @@ Try Live Editor previews of future releases: <a href="https://develop.git.mermai
[![Coverage Status](https://codecov.io/github/mermaid-js/mermaid/branch/develop/graph/badge.svg)](https://app.codecov.io/github/mermaid-js/mermaid/tree/develop) [![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) [![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid)
[![NPM Downloads](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid) [![NPM Downloads](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid)
[![Join our Discord!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=discord&label=discord)](https://discord.gg/sKeNQX4Wtj) [![Join our Discord!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=discord&label=discord)](https://discord.gg/AgrbSrBer3)
[![Twitter Follow](https://img.shields.io/badge/Social-mermaidjs__-blue?style=social&logo=X)](https://twitter.com/mermaidjs_) [![Twitter Follow](https://img.shields.io/badge/Social-mermaidjs__-blue?style=social&logo=X)](https://twitter.com/mermaidjs_)
[![Covered by Argos Visual Testing](https://argos-ci.com/badge.svg)](https://argos-ci.com?utm_source=mermaid&utm_campaign=oss) [![Covered by Argos Visual Testing](https://argos-ci.com/badge.svg)](https://argos-ci.com)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/mermaid-js/mermaid/badge)](https://securityscorecards.dev/viewer/?uri=github.com/mermaid-js/mermaid)
<img src="./img/header.png" alt="" /> <img src="./img/header.png" alt="" />
@@ -83,10 +82,6 @@ You can also use Mermaid within [GitHub](https://github.blog/2022-02-14-include-
For a more detailed introduction to Mermaid and some of its more basic uses, look to the [Beginner's Guide](https://mermaid.js.org/intro/getting-started.html), [Usage](https://mermaid.js.org/config/usage.html) and [Tutorials](https://mermaid.js.org/ecosystem/tutorials.html). For a more detailed introduction to Mermaid and some of its more basic uses, look to the [Beginner's Guide](https://mermaid.js.org/intro/getting-started.html), [Usage](https://mermaid.js.org/config/usage.html) and [Tutorials](https://mermaid.js.org/ecosystem/tutorials.html).
Our PR Visual Regression Testing is powered by [Argos](https://argos-ci.com/?utm_source=mermaid&utm_campaign=oss) with their generous Open Source plan. It makes the process of reviewing PRs with visual changes a breeze.
[![Covered by Argos Visual Testing](https://argos-ci.com/badge-large.svg)](https://argos-ci.com?utm_source=mermaid&utm_campaign=oss)
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. 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.
<a href="https://applitools.com/"> <a href="https://applitools.com/">
@@ -95,10 +90,6 @@ In our release process we rely heavily on visual regression tests using [applito
<!-- </Main description> --> <!-- </Main description> -->
## Mermaid AI Bot
[Mermaid](https://codeparrot.ai/oracle?owner=mermaid-js&repo=mermaid) Bot will help you understand this repository better. You can ask for code examples, installation guide, debugging help and much more.
## Examples ## Examples
**The following are some examples of the diagrams, charts and graphs that can be made using Mermaid. Click here to jump into the [text syntax](https://mermaid.js.org/intro/syntax-reference.html).** **The following are some examples of the diagrams, charts and graphs that can be made using Mermaid. Click here to jump into the [text syntax](https://mermaid.js.org/intro/syntax-reference.html).**
@@ -257,34 +248,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>] ### 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>]
```
gitGraph
commit
commit
branch develop
checkout develop
commit
commit
checkout main
merge develop
commit
commit
```
```mermaid
gitGraph
commit
commit
branch develop
checkout develop
commit
commit
checkout main
merge develop
commit
commit
```
### Bar chart (using gantt chart) [<a href="https://mermaid.js.org/syntax/gantt.html">docs</a> - <a href="https://mermaid.live/edit#pako:eNptkU1vhCAQhv8KIenNugiI4rkf6bmXpvEyFVxJFDYyNt1u9r8X63Z7WQ9m5pknLzieaBeMpQ3dg0dsPUkPOhwteXZIXmJcbCT3xMAxkuh8Z8kIEclyMIB209fqKcwTICFvG4IvFy_oLrZ-g9F26ILfQgvNFN94VaRXQ1iWqpumZBcu1J8p1E1TXDx59eQNr5LyEqjJn6hv5QnGNlxevZJmdLLpy5xJSzut45biYCfb0iaVxvawjNjS1p-TCguG16PvaIPzYjO67e3BwX6GiTY9jPFKH43DMF_hGMDY1J4oHg-_f8hFTJFd8L3br3yZx4QHxENsdrt1nO8dDstH3oVpF50ZYMbhU6ud4qoGLqyqBJRCmO6j0HXPZdGbihUc6Pmc0QP49xD-b5X69ZQv2gjO81IwzWqhC1lKrjJ6pA3nVS7SMiVjrKirWlYp5fs3osgrWeo00lorLWvOzz8JVbXm">live editor</a>] ### Bar chart (using gantt chart) [<a href="https://mermaid.js.org/syntax/gantt.html">docs</a> - <a href="https://mermaid.live/edit#pako:eNptkU1vhCAQhv8KIenNugiI4rkf6bmXpvEyFVxJFDYyNt1u9r8X63Z7WQ9m5pknLzieaBeMpQ3dg0dsPUkPOhwteXZIXmJcbCT3xMAxkuh8Z8kIEclyMIB209fqKcwTICFvG4IvFy_oLrZ-g9F26ILfQgvNFN94VaRXQ1iWqpumZBcu1J8p1E1TXDx59eQNr5LyEqjJn6hv5QnGNlxevZJmdLLpy5xJSzut45biYCfb0iaVxvawjNjS1p-TCguG16PvaIPzYjO67e3BwX6GiTY9jPFKH43DMF_hGMDY1J4oHg-_f8hFTJFd8L3br3yZx4QHxENsdrt1nO8dDstH3oVpF50ZYMbhU6ud4qoGLqyqBJRCmO6j0HXPZdGbihUc6Pmc0QP49xD-b5X69ZQv2gjO81IwzWqhC1lKrjJ6pA3nVS7SMiVjrKirWlYp5fs3osgrWeo00lorLWvOzz8JVbXm">live editor</a>]
``` ```
@@ -467,7 +430,7 @@ A quick note from Knut Sveidqvist:
> >
> _Thank you to [Tyler Long](https://github.com/tylerlong) who has been a collaborator since April 2017._ > _Thank you to [Tyler Long](https://github.com/tylerlong) who has been a collaborator since April 2017._
> >
> _Thank you to the ever-growing list of [contributors](https://github.com/mermaid-js/mermaid/graphs/contributors) that brought the project this far!_ > _Thank you to the ever-growing list of [contributors](https://github.com/knsv/mermaid/graphs/contributors) that brought the project this far!_
--- ---

View File

@@ -15,7 +15,7 @@ Mermaid
<a href="https://mermaid.live/"><b>实时编辑器!</b></a> <a href="https://mermaid.live/"><b>实时编辑器!</b></a>
</p> </p>
<p align="center"> <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://discord.gg/sKeNQX4Wtj" title="Discord invite">🙌 加入我们</a> <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://discord.gg/AgrbSrBer3" title="Discord invite">🙌 加入我们</a>
</p> </p>
<p align="center"> <p align="center">
<a href="./README.md">English</a> <a href="./README.md">English</a>
@@ -34,7 +34,7 @@ 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) [![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) [![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid)
[![NPM Downloads](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid) [![NPM Downloads](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid)
[![Join our Discord!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=discord&label=discord)](https://discord.gg/sKeNQX4Wtj) [![Join our Discord!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=discord&label=discord)](https://discord.gg/AgrbSrBer3)
[![Twitter Follow](https://img.shields.io/badge/Social-mermaidjs__-blue?style=social&logo=X)](https://twitter.com/mermaidjs_) [![Twitter Follow](https://img.shields.io/badge/Social-mermaidjs__-blue?style=social&logo=X)](https://twitter.com/mermaidjs_)
<img src="./img/header.png" alt="" /> <img src="./img/header.png" alt="" />
@@ -358,7 +358,7 @@ _很不幸的是鱼与熊掌不可兼得在这个场景下它意味着在
> _特别感谢 [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/mermaid-js/mermaid/graphs/contributors)没有你们就没有这个项目的今天_ > _感谢越来越多的 [贡献者们](https://github.com/knsv/mermaid/graphs/contributors)没有你们就没有这个项目的今天_
--- ---

View File

@@ -1,9 +1,8 @@
import { defineConfig } from 'cypress';
import { addMatchImageSnapshotPlugin } from 'cypress-image-snapshot/plugin';
import coverage from '@cypress/code-coverage/task';
import eyesPlugin from '@applitools/eyes-cypress'; import eyesPlugin from '@applitools/eyes-cypress';
import { registerArgosTask } from '@argos-ci/cypress/task'; import { registerArgosTask } from '@argos-ci/cypress/task';
import coverage from '@cypress/code-coverage/task.js';
import { defineConfig } from 'cypress';
import { addMatchImageSnapshotPlugin } from 'cypress-image-snapshot/plugin.js';
import cypressSplit from 'cypress-split';
export default eyesPlugin( export default eyesPlugin(
defineConfig({ defineConfig({
@@ -14,7 +13,6 @@ export default eyesPlugin(
specPattern: 'cypress/integration/**/*.{js,ts}', specPattern: 'cypress/integration/**/*.{js,ts}',
setupNodeEvents(on, config) { setupNodeEvents(on, config) {
coverage(on, config); coverage(on, config);
cypressSplit(on, config);
on('before:browser:launch', (browser, launchOptions) => { on('before:browser:launch', (browser, launchOptions) => {
if (browser.name === 'chrome' && browser.isHeadless) { if (browser.name === 'chrome' && browser.isHeadless) {
launchOptions.args.push('--window-size=1440,1024', '--force-device-scale-factor=1'); launchOptions.args.push('--window-size=1440,1024', '--force-device-scale-factor=1');
@@ -23,10 +21,12 @@ export default eyesPlugin(
}); });
// copy any needed variables from process.env to config.env // copy any needed variables from process.env to config.env
config.env.useAppli = process.env.USE_APPLI ? true : false; config.env.useAppli = process.env.USE_APPLI ? true : false;
config.env.useArgos = process.env.RUN_VISUAL_TEST === 'true'; config.env.useArgos = !!process.env.CI;
if (config.env.useArgos) { if (config.env.useArgos) {
registerArgosTask(on, config); registerArgosTask(on, config, {
token: 'fc3a35cf5200db928d65b2047861582d9444032b',
});
} else { } else {
addMatchImageSnapshotPlugin(on, config); addMatchImageSnapshotPlugin(on, config);
} }

View File

@@ -29,7 +29,6 @@ export const mermaidUrl = (
options: CypressMermaidConfig, options: CypressMermaidConfig,
api: boolean api: boolean
): string => { ): string => {
options.handDrawnSeed = 1;
const codeObject: CodeObject = { const codeObject: CodeObject = {
code: graphStr, code: graphStr,
mermaid: options, mermaid: options,
@@ -74,7 +73,7 @@ export const imgSnapshotTest = (
export const urlSnapshotTest = ( export const urlSnapshotTest = (
url: string, url: string,
options: CypressMermaidConfig = {}, options: CypressMermaidConfig,
_api = false, _api = false,
validation?: any validation?: any
): void => { ): void => {
@@ -132,10 +131,3 @@ export const verifyScreenshot = (name: string): void => {
cy.matchImageSnapshot(name); cy.matchImageSnapshot(name);
} }
}; };
export const verifyNumber = (value: number, expected: number, deltaPercent = 10): void => {
expect(value).to.be.within(
expected * (1 - deltaPercent / 100),
expected * (1 + deltaPercent / 100)
);
};

View File

@@ -1,233 +0,0 @@
import { imgSnapshotTest, urlSnapshotTest } from '../../helpers/util.ts';
describe.skip('architecture diagram', () => {
it('should render a simple architecture diagram with groups', () => {
imgSnapshotTest(
`architecture-beta
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
service gateway(internet)[Gateway]
db L--R server
disk1 T--B server
disk2 T--B db
server T--B gateway
`
);
});
it('should render an architecture diagram with groups within groups', () => {
imgSnapshotTest(
`architecture-beta
group api[API]
group public[Public API] in api
group private[Private API] in api
service serv1(server)[Server] in public
service serv2(server)[Server] in private
service db(database)[Database] in private
service gateway(internet)[Gateway] in api
serv1 B--T serv2
serv2 L--R db
serv1 L--R gateway
`
);
});
it('should render an architecture diagram with the fallback icon', () => {
imgSnapshotTest(
`architecture-beta
service unknown(iconnamedoesntexist)[Unknown Icon]
`
);
});
it('should render an architecture diagram with split directioning', () => {
imgSnapshotTest(
`architecture-beta
service db(database)[Database]
service s3(disk)[Storage]
service serv1(server)[Server 1]
service serv2(server)[Server 2]
service disk(disk)[Disk]
db L--R s3
serv1 L--T s3
serv2 L--B s3
serv1 T--B disk
`
);
});
it('should render an architecture diagram with directional arrows', () => {
imgSnapshotTest(
`architecture-beta
service servC(server)[Server 1]
service servL(server)[Server 2]
service servR(server)[Server 3]
service servT(server)[Server 4]
service servB(server)[Server 5]
servC (L--R) servL
servC (R--L) servR
servC (T--B) servT
servC (B--T) servB
servL (T--L) servT
servL (B--L) servB
servR (T--R) servT
servR (B--R) servB
`
);
});
it('should render an architecture diagram with group edges', () => {
imgSnapshotTest(
`architecture-beta
group left_group(cloud)[Left]
group right_group(cloud)[Right]
group top_group(cloud)[Top]
group bottom_group(cloud)[Bottom]
group center_group(cloud)[Center]
service left_disk(disk)[Disk] in left_group
service right_disk(disk)[Disk] in right_group
service top_disk(disk)[Disk] in top_group
service bottom_disk(disk)[Disk] in bottom_group
service center_disk(disk)[Disk] in center_group
left_disk{group} (R--L) center_disk{group}
right_disk{group} (L--R) center_disk{group}
top_disk{group} (B--T) center_disk{group}
bottom_disk{group} (T--B) center_disk{group}
`
);
});
it('should render an architecture diagram with edge labels', () => {
imgSnapshotTest(
`architecture-beta
service servC(server)[Server 1]
service servL(server)[Server 2]
service servR(server)[Server 3]
service servT(server)[Server 4]
service servB(server)[Server 5]
servC L-[Label]-R servL
servC R-[Label]-L servR
servC T-[Label]-B servT
servC B-[Label]-T servB
servL T-[Label]-L servT
servL B-[Label]-L servB
servR T-[Label]-R servT
servR B-[Label]-R servB
`
);
});
it('should render an architecture diagram with simple junction edges', () => {
imgSnapshotTest(
`architecture-beta
service left_disk(disk)[Disk]
service top_disk(disk)[Disk]
service bottom_disk(disk)[Disk]
service top_gateway(internet)[Gateway]
service bottom_gateway(internet)[Gateway]
junction juncC
junction juncR
left_disk R--L juncC
top_disk B--T juncC
bottom_disk T--B juncC
juncC R--L juncR
top_gateway B--T juncR
bottom_gateway T--B juncR
`
);
});
it('should render an architecture diagram with complex junction edges', () => {
imgSnapshotTest(
`architecture-beta
group left
group right
service left_disk(disk)[Disk] in left
service top_disk(disk)[Disk] in left
service bottom_disk(disk)[Disk] in left
service top_gateway(internet)[Gateway] in right
service bottom_gateway(internet)[Gateway] in right
junction juncC in left
junction juncR in right
left_disk R--L juncC
top_disk B--T juncC
bottom_disk T--B juncC
top_gateway (B--T juncR
bottom_gateway (T--B juncR
juncC{group} R--L) juncR{group}
`
);
});
it('should render an architecture diagram with a resonable height', () => {
imgSnapshotTest(
`architecture-beta
group federated(cloud)[Federated Environment]
service server1(server)[System] in federated
service edge(server)[Edge Device] in federated
server1:R -- L:edge
group on_prem(cloud)[Hub]
service firewall(server)[Firewall Device] in on_prem
service server(server)[Server] in on_prem
firewall:R -- L:server
service db1(database)[db1] in on_prem
service db2(database)[db2] in on_prem
service db3(database)[db3] in on_prem
service db4(database)[db4] in on_prem
service db5(database)[db5] in on_prem
service db6(database)[db6] in on_prem
junction mid in on_prem
server:B -- T:mid
junction 1Leftofmid in on_prem
1Leftofmid:R -- L:mid
1Leftofmid:B -- T:db1
junction 2Leftofmid in on_prem
2Leftofmid:R -- L:1Leftofmid
2Leftofmid:B -- T:db2
junction 3Leftofmid in on_prem
3Leftofmid:R -- L:2Leftofmid
3Leftofmid:B -- T:db3
junction 1RightOfMid in on_prem
mid:R -- L:1RightOfMid
1RightOfMid:B -- T:db4
junction 2RightOfMid in on_prem
1RightOfMid:R -- L:2RightOfMid
2RightOfMid:B -- T:db5
junction 3RightOfMid in on_prem
2RightOfMid:R -- L:3RightOfMid
3RightOfMid:B -- T:db6
edge:R -- L:firewall
`
);
});
});
// Skipped as the layout is not deterministic, and causes issues in E2E tests.
describe.skip('architecture - external', () => {
it('should allow adding external icons', () => {
urlSnapshotTest('http://localhost:9000/architecture-external.html');
});
});

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -581,63 +581,4 @@ class C13["With Città foreign language"]
{ logLevel: 1, flowchart: { htmlLabels: false } } { logLevel: 1, flowchart: { htmlLabels: false } }
); );
}); });
it('renders a class diagram with a generic class in a namespace', () => {
const diagramDefinition = `
classDiagram-v2
namespace Company.Project.Module {
class GenericClass~T~ {
+addItem(item: T)
+getItem() T
}
}
`;
imgSnapshotTest(diagramDefinition);
});
it('renders a class diagram with nested namespaces and relationships', () => {
const diagramDefinition = `
classDiagram-v2
namespace Company.Project.Module.SubModule {
class Report {
+generatePDF(data: List)
+generateCSV(data: List)
}
}
namespace Company.Project.Module {
class Admin {
+generateReport()
}
}
Admin --> Report : generates
`;
imgSnapshotTest(diagramDefinition);
});
it('renders a class diagram with multiple classes and relationships in a namespace', () => {
const diagramDefinition = `
classDiagram-v2
namespace Company.Project.Module {
class User {
+login(username: String, password: String)
+logout()
}
class Admin {
+addUser(user: User)
+removeUser(user: User)
+generateReport()
}
class Report {
+generatePDF(reportData: List)
+generateCSV(reportData: List)
}
}
Admin --> User : manages
Admin --> Report : generates
`;
imgSnapshotTest(diagramDefinition);
});
}); });

File diff suppressed because it is too large Load Diff

View File

@@ -1,652 +0,0 @@
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<br />one"
p ||--o| b : "has<br />one<br />two"
p ||--o| c : "has<br />one<br/>two<br />three"
p ||--o| d : "has<br />one<br />two<br/>three<br />...<br/>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__ <br>characters are a<br>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__ <br>characters are a<br>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 }
);
});
});
});

View File

@@ -109,8 +109,8 @@ describe('Entity Relationship Diagram', () => {
const style = svg.attr('style'); const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/); expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
// use within because the absolute value can be slightly different depending on the environment ±6% // use within because the absolute value can be slightly different depending on the environment ±5%
expect(maxWidthValue).to.be.within(140 * 0.96, 140 * 1.06); expect(maxWidthValue).to.be.within(140 * 0.95, 140 * 1.05);
}); });
}); });
@@ -125,8 +125,8 @@ describe('Entity Relationship Diagram', () => {
); );
cy.get('svg').should((svg) => { cy.get('svg').should((svg) => {
const width = parseFloat(svg.attr('width')); const width = parseFloat(svg.attr('width'));
// use within because the absolute value can be slightly different depending on the environment ±6% // use within because the absolute value can be slightly different depending on the environment ±5%
expect(width).to.be.within(140 * 0.96, 140 * 1.06); expect(width).to.be.within(140 * 0.95, 140 * 1.05);
// expect(svg).to.have.attr('height', '465'); // expect(svg).to.have.attr('height', '465');
expect(svg).to.not.have.attr('style'); expect(svg).to.not.have.attr('style');
}); });
@@ -321,37 +321,4 @@ ORDER ||--|{ LINE-ITEM : contains
{ logLevel: 1 } { logLevel: 1 }
); );
}); });
it('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<br />one"
p ||--o| b : "has<br />one<br />two"
p ||--o| c : "has<br />one<br/>two<br />three"
p ||--o| d : "has<br />one<br />two<br/>three<br />...<br/>Nth"
`,
{ logLevel: 1 }
);
});
}); });

View File

@@ -1,6 +1,6 @@
import { imgSnapshotTest, renderGraph, verifyNumber } from '../../helpers/util.ts'; import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
describe('Flowchart ELK', () => { describe.skip('Flowchart ELK', () => {
it('1-elk: should render a simple flowchart', () => { it('1-elk: should render a simple flowchart', () => {
imgSnapshotTest( imgSnapshotTest(
`flowchart-elk TD `flowchart-elk TD
@@ -109,7 +109,7 @@ describe('Flowchart ELK', () => {
const style = svg.attr('style'); const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/); expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
verifyNumber(maxWidthValue, 380); expect(maxWidthValue).to.be.within(230 * 0.95, 230 * 1.05);
}); });
}); });
it('8-elk: should render a flowchart when useMaxWidth is false', () => { it('8-elk: should render a flowchart when useMaxWidth is false', () => {
@@ -128,7 +128,7 @@ describe('Flowchart ELK', () => {
const width = parseFloat(svg.attr('width')); const width = parseFloat(svg.attr('width'));
// use within because the absolute value can be slightly different depending on the environment ±5% // 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(height).to.be.within(446 * 0.95, 446 * 1.05);
verifyNumber(width, 380); expect(width).to.be.within(230 * 0.95, 230 * 1.05);
expect(svg).to.not.have.attr('style'); expect(svg).to.not.have.attr('style');
}); });
}); });
@@ -692,7 +692,7 @@ A --> B
{} {}
); );
cy.get('svg').should((svg) => { cy.get('svg').should((svg) => {
const edges = svg[0].querySelectorAll('.edges > path'); const edges = svg.querySelectorAll('.edges > path');
edges.forEach((edge) => { edges.forEach((edge) => {
expect(edge).to.have.class('flowchart-link'); expect(edge).to.have.class('flowchart-link');
}); });
@@ -739,7 +739,7 @@ NL\`") --"\`1o **bold**\`"--> c
{ flowchart: { titleTopMargin: 0 } } { flowchart: { titleTopMargin: 0 } }
); );
}); });
it.skip('Wrapping long text with a new line', () => { it('Wrapping long text with a new line', () => {
imgSnapshotTest( imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": true}} }%% `%%{init: {"flowchart": {"htmlLabels": true}} }%%
flowchart-elk LR flowchart-elk LR
@@ -841,7 +841,7 @@ end
{ flowchart: { titleTopMargin: 0 } } { flowchart: { titleTopMargin: 0 } }
); );
}); });
it('Sub graphs', () => { it('Sub graphs and markdown strings', () => {
imgSnapshotTest( imgSnapshotTest(
`--- `---
config: config:
@@ -857,196 +857,6 @@ flowchart LR
D --> E D --> E
A["A"] A["A"]
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('6080: should handle diamond shape intersections', () => {
imgSnapshotTest(
`---
config:
layout: elk
---
flowchart LR
subgraph s1["Untitled subgraph"]
n1["Evaluate"]
n2["Option 1"]
n3["Option 2"]
n4["fa:fa-car Option 3"]
end
subgraph s2["Untitled subgraph"]
n5["Evaluate"]
n6["Option 1"]
n7["Option 2"]
n8["fa:fa-car Option 3"]
end
A["Start"] -- Some text --> B("Continue")
B --> C{"Evaluate"}
C -- One --> D["Option 1"]
C -- Two --> E["Option 2"]
C -- Three --> F["fa:fa-car Option 3"]
n1 -- One --> n2
n1 -- Two --> n3
n1 -- Three --> n4
n5 -- One --> n6
n5 -- Two --> n7
n5 -- Three --> n8
n1@{ shape: diam}
n2@{ shape: rect}
n3@{ shape: rect}
n4@{ shape: rect}
n5@{ shape: diam}
n6@{ shape: rect}
n7@{ shape: rect}
n8@{ shape: rect}
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('6088-1: should handle diamond shape intersections', () => {
imgSnapshotTest(
`---
config:
layout: elk
---
flowchart LR
subgraph S2
subgraph s1["APA"]
D{"Use the editor"}
end
D -- Mermaid js --> I{"fa:fa-code Text"}
D --> I
D --> I
end
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('6088-2: should handle diamond shape intersections', () => {
imgSnapshotTest(
`---
config:
layout: elk
---
flowchart LR
a
subgraph s0["APA"]
subgraph s8["APA"]
subgraph s1["APA"]
D{"X"}
E[Q]
end
subgraph s3["BAPA"]
F[Q]
I
end
D --> I
D --> I
D --> I
I{"X"}
end
end
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('6088-3: should handle diamond shape intersections', () => {
imgSnapshotTest(
`---
config:
layout: elk
---
flowchart LR
a
D{"Use the editor"}
D -- Mermaid js --> I{"fa:fa-code Text"}
D-->I
D-->I
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('6088-4: should handle diamond shape intersections', () => {
imgSnapshotTest(
`---
config:
layout: elk
---
flowchart LR
subgraph s1["Untitled subgraph"]
n1["Evaluate"]
n2["Option 1"]
n3["Option 2"]
n4["fa:fa-car Option 3"]
end
subgraph s2["Untitled subgraph"]
n5["Evaluate"]
n6["Option 1"]
n7["Option 2"]
n8["fa:fa-car Option 3"]
end
A["Start"] -- Some text --> B("Continue")
B --> C{"Evaluate"}
C -- One --> D["Option 1"]
C -- Two --> E["Option 2"]
C -- Three --> F["fa:fa-car Option 3"]
n1 -- One --> n2
n1 -- Two --> n3
n1 -- Three --> n4
n5 -- One --> n6
n5 -- Two --> n7
n5 -- Three --> n8
n1@{ shape: diam}
n2@{ shape: rect}
n3@{ shape: rect}
n4@{ shape: rect}
n5@{ shape: diam}
n6@{ shape: rect}
n7@{ shape: rect}
n8@{ shape: rect}
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('6088-5: should handle diamond shape intersections', () => {
imgSnapshotTest(
`---
config:
layout: elk
---
flowchart LR
A{A} --> B & C
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('6088-6: should handle diamond shape intersections', () => {
imgSnapshotTest(
`---
config:
layout: elk
---
flowchart LR
A{A} --> B & C
subgraph "subbe"
A
end
`, `,
{ flowchart: { titleTopMargin: 0 } } { flowchart: { titleTopMargin: 0 } }
); );

View File

@@ -12,6 +12,7 @@ describe('Flowchart HandDrawn', () => {
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
flowchart: { htmlLabels: false }, flowchart: { htmlLabels: false },
fontFamily: 'courier', fontFamily: 'courier',
} }
@@ -29,6 +30,7 @@ describe('Flowchart HandDrawn', () => {
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
flowchart: { htmlLabels: true }, flowchart: { htmlLabels: true },
fontFamily: 'courier', fontFamily: 'courier',
} }
@@ -45,7 +47,7 @@ describe('Flowchart HandDrawn', () => {
C -->|Two| E[iPhone] C -->|Two| E[iPhone]
C -->|Three| F[Car] C -->|Three| F[Car]
`, `,
{ look: 'handDrawn', fontFamily: 'courier' } { look: 'handDrawn', handDrawnSeed: 1, fontFamily: 'courier' }
); );
}); });
@@ -60,7 +62,7 @@ describe('Flowchart HandDrawn', () => {
C -->|Two| E[\\iPhone\\] C -->|Two| E[\\iPhone\\]
C -->|Three| F[Car] C -->|Three| F[Car]
`, `,
{ look: 'handDrawn', fontFamily: 'courier' } { look: 'handDrawn', handDrawnSeed: 1, fontFamily: 'courier' }
); );
}); });
@@ -76,7 +78,7 @@ describe('Flowchart HandDrawn', () => {
classDef processHead fill:#888888,color:white,font-weight:bold,stroke-width:3px,stroke:#001f3f classDef processHead fill:#888888,color:white,font-weight:bold,stroke-width:3px,stroke:#001f3f
class 1A,1B,D,E processHead class 1A,1B,D,E processHead
`, `,
{ look: 'handDrawn', fontFamily: 'courier' } { look: 'handDrawn', handDrawnSeed: 1, fontFamily: 'courier' }
); );
}); });
@@ -105,7 +107,7 @@ describe('Flowchart HandDrawn', () => {
35(SAM.CommonFA.PopulationFME)-->39(SAM.CommonFA.ChargeDetails) 35(SAM.CommonFA.PopulationFME)-->39(SAM.CommonFA.ChargeDetails)
36(SAM.CommonFA.PremetricCost)-->39(SAM.CommonFA.ChargeDetails) 36(SAM.CommonFA.PremetricCost)-->39(SAM.CommonFA.ChargeDetails)
`, `,
{ look: 'handDrawn', fontFamily: 'courier' } { look: 'handDrawn', handDrawnSeed: 1, fontFamily: 'courier' }
); );
}); });
@@ -176,7 +178,7 @@ describe('Flowchart HandDrawn', () => {
9a072290_1ec3_e711_8c5a_005056ad0002-->d6072290_1ec3_e711_8c5a_005056ad0002 9a072290_1ec3_e711_8c5a_005056ad0002-->d6072290_1ec3_e711_8c5a_005056ad0002
9a072290_1ec3_e711_8c5a_005056ad0002-->71082290_1ec3_e711_8c5a_005056ad0002 9a072290_1ec3_e711_8c5a_005056ad0002-->71082290_1ec3_e711_8c5a_005056ad0002
`, `,
{ look: 'handDrawn', fontFamily: 'courier' } { look: 'handDrawn', handDrawnSeed: 1, fontFamily: 'courier' }
); );
}); });
@@ -185,7 +187,7 @@ describe('Flowchart HandDrawn', () => {
` `
graph TB;subgraph "number as labels";1;end; graph TB;subgraph "number as labels";1;end;
`, `,
{ look: 'handDrawn', fontFamily: 'courier' } { look: 'handDrawn', handDrawnSeed: 1, fontFamily: 'courier' }
); );
}); });
@@ -197,7 +199,7 @@ describe('Flowchart HandDrawn', () => {
a1-->a2 a1-->a2
end end
`, `,
{ look: 'handDrawn', fontFamily: 'courier' } { look: 'handDrawn', handDrawnSeed: 1, fontFamily: 'courier' }
); );
}); });
@@ -209,7 +211,7 @@ describe('Flowchart HandDrawn', () => {
a1-->a2 a1-->a2
end end
`, `,
{ look: 'handDrawn', fontFamily: 'courier' } { look: 'handDrawn', handDrawnSeed: 1, fontFamily: 'courier' }
); );
}); });
@@ -244,7 +246,7 @@ describe('Flowchart HandDrawn', () => {
style foo fill:#F99,stroke-width:2px,stroke:#F0F,color:darkred style foo fill:#F99,stroke-width:2px,stroke:#F0F,color:darkred
style bar fill:#999,stroke-width:10px,stroke:#0F0,color:blue style bar fill:#999,stroke-width:10px,stroke:#0F0,color:blue
`, `,
{ look: 'handDrawn', fontFamily: 'courier' } { look: 'handDrawn', handDrawnSeed: 1, fontFamily: 'courier' }
); );
}); });
@@ -346,7 +348,7 @@ describe('Flowchart HandDrawn', () => {
sid-7CE72B24-E0C1-46D3-8132-8BA66BE05AA7-->sid-4DA958A0-26D9-4D47-93A7-70F39FD7D51A; sid-7CE72B24-E0C1-46D3-8132-8BA66BE05AA7-->sid-4DA958A0-26D9-4D47-93A7-70F39FD7D51A;
sid-7CE72B24-E0C1-46D3-8132-8BA66BE05AA7-->sid-4FC27B48-A6F9-460A-A675-021F5854FE22; sid-7CE72B24-E0C1-46D3-8132-8BA66BE05AA7-->sid-4FC27B48-A6F9-460A-A675-021F5854FE22;
`, `,
{ look: 'handDrawn', fontFamily: 'courier' } { look: 'handDrawn', handDrawnSeed: 1, fontFamily: 'courier' }
); );
}); });
@@ -362,6 +364,7 @@ describe('Flowchart HandDrawn', () => {
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
listUrl: false, listUrl: false,
listId: 'color styling', listId: 'color styling',
fontFamily: 'courier', fontFamily: 'courier',
@@ -387,6 +390,7 @@ describe('Flowchart HandDrawn', () => {
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
listUrl: false, listUrl: false,
listId: 'color styling', listId: 'color styling',
fontFamily: 'courier', fontFamily: 'courier',
@@ -407,6 +411,7 @@ describe('Flowchart HandDrawn', () => {
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
flowchart: { htmlLabels: false }, flowchart: { htmlLabels: false },
fontFamily: 'courier', fontFamily: 'courier',
} }
@@ -430,6 +435,7 @@ describe('Flowchart HandDrawn', () => {
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
flowchart: { htmlLabels: false }, flowchart: { htmlLabels: false },
fontFamily: 'courier', fontFamily: 'courier',
} }
@@ -451,6 +457,7 @@ describe('Flowchart HandDrawn', () => {
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
flowchart: { htmlLabels: false }, flowchart: { htmlLabels: false },
fontFamily: 'courier', fontFamily: 'courier',
} }
@@ -464,6 +471,7 @@ describe('Flowchart HandDrawn', () => {
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
flowchart: { htmlLabels: false }, flowchart: { htmlLabels: false },
fontFamily: 'courier', fontFamily: 'courier',
} }
@@ -477,6 +485,7 @@ describe('Flowchart HandDrawn', () => {
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
flowchart: { htmlLabels: false }, flowchart: { htmlLabels: false },
fontFamily: 'courier', fontFamily: 'courier',
} }
@@ -491,6 +500,7 @@ describe('Flowchart HandDrawn', () => {
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
flowchart: { htmlLabels: false }, flowchart: { htmlLabels: false },
fontFamily: 'courier', fontFamily: 'courier',
} }
@@ -517,6 +527,7 @@ describe('Flowchart HandDrawn', () => {
class A someclass;`, class A someclass;`,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
flowchart: { htmlLabels: false }, flowchart: { htmlLabels: false },
fontFamily: 'courier', fontFamily: 'courier',
} }
@@ -533,7 +544,7 @@ describe('Flowchart HandDrawn', () => {
C -->|Two| E[iPhone] C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car] C -->|Three| F[fa:fa-car Car]
`, `,
{ look: 'handDrawn', flowchart: { nodeSpacing: 50 }, fontFamily: 'courier' } { look: 'handDrawn', handDrawnSeed: 1, flowchart: { nodeSpacing: 50 }, fontFamily: 'courier' }
); );
}); });
@@ -549,6 +560,7 @@ describe('Flowchart HandDrawn', () => {
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
flowchart: { rankSpacing: '100' }, flowchart: { rankSpacing: '100' },
fontFamily: 'courier', fontFamily: 'courier',
} }
@@ -566,6 +578,7 @@ describe('Flowchart HandDrawn', () => {
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
flowchart: { htmlLabels: false }, flowchart: { htmlLabels: false },
fontFamily: 'courier', fontFamily: 'courier',
} }
@@ -590,7 +603,7 @@ describe('Flowchart HandDrawn', () => {
click E "notes://do-your-thing/id" "other protocol test" click E "notes://do-your-thing/id" "other protocol test"
click F "javascript:alert('test')" "script test" click F "javascript:alert('test')" "script test"
`, `,
{ look: 'handDrawn', securityLevel: 'loose', fontFamily: 'courier' } { look: 'handDrawn', handDrawnSeed: 1, securityLevel: 'loose', fontFamily: 'courier' }
); );
}); });
@@ -610,7 +623,7 @@ describe('Flowchart HandDrawn', () => {
click B "index.html#link-clicked" "link test" click B "index.html#link-clicked" "link test"
click D testClick "click test" click D testClick "click test"
`, `,
{ look: 'handDrawn', flowchart: { htmlLabels: true } } { look: 'handDrawn', handDrawnSeed: 1, flowchart: { htmlLabels: true } }
); );
}); });
@@ -632,6 +645,7 @@ describe('Flowchart HandDrawn', () => {
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
flowchart: { htmlLabels: false }, flowchart: { htmlLabels: false },
fontFamily: 'courier', fontFamily: 'courier',
} }
@@ -650,7 +664,7 @@ describe('Flowchart HandDrawn', () => {
class A myClass1 class A myClass1
class D myClass2 class D myClass2
`, `,
{ look: 'handDrawn', flowchart: { htmlLabels: true } } { look: 'handDrawn', handDrawnSeed: 1, flowchart: { htmlLabels: true } }
); );
}); });
@@ -668,6 +682,7 @@ describe('Flowchart HandDrawn', () => {
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
flowchart: { htmlLabels: false }, flowchart: { htmlLabels: false },
fontFamily: 'courier', fontFamily: 'courier',
} }
@@ -696,6 +711,7 @@ describe('Flowchart HandDrawn', () => {
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
flowchart: { htmlLabels: false }, flowchart: { htmlLabels: false },
fontFamily: 'courier', fontFamily: 'courier',
} }
@@ -712,6 +728,7 @@ describe('Flowchart HandDrawn', () => {
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
flowchart: { htmlLabels: false }, flowchart: { htmlLabels: false },
fontFamily: 'courier', fontFamily: 'courier',
} }
@@ -735,6 +752,7 @@ describe('Flowchart HandDrawn', () => {
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
flowchart: { htmlLabels: false }, flowchart: { htmlLabels: false },
fontFamily: 'courier', fontFamily: 'courier',
} }
@@ -751,7 +769,7 @@ describe('Flowchart HandDrawn', () => {
C -->|Two| E[iPhone] C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car] C -->|Three| F[fa:fa-car Car]
`, `,
{ look: 'handDrawn', flowchart: { diagramPadding: 0 } } { look: 'handDrawn', handDrawnSeed: 1, flowchart: { diagramPadding: 0 } }
); );
}); });
@@ -786,7 +804,7 @@ describe('Flowchart HandDrawn', () => {
`graph TD `graph TD
a["<strong>Haiya</strong>"]-->b a["<strong>Haiya</strong>"]-->b
`, `,
{ look: 'handDrawn', htmlLabels: false, flowchart: { htmlLabels: false } } { look: 'handDrawn', handDrawnSeed: 1, htmlLabels: false, flowchart: { htmlLabels: false } }
); );
}); });
it('FDH37: should render non-escaped with html labels', () => { it('FDH37: should render non-escaped with html labels', () => {
@@ -796,6 +814,7 @@ describe('Flowchart HandDrawn', () => {
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
htmlLabels: true, htmlLabels: true,
flowchart: { htmlLabels: true }, flowchart: { htmlLabels: true },
securityLevel: 'loose', securityLevel: 'loose',
@@ -811,7 +830,7 @@ describe('Flowchart HandDrawn', () => {
C -->|Two| E[iPhone] C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car] C -->|Three| F[fa:fa-car Car]
`, `,
{ look: 'handDrawn', flowchart: { useMaxWidth: true } } { look: 'handDrawn', handDrawnSeed: 1, flowchart: { useMaxWidth: true } }
); );
cy.get('svg').should((svg) => { cy.get('svg').should((svg) => {
expect(svg).to.have.attr('width', '100%'); expect(svg).to.have.attr('width', '100%');
@@ -834,7 +853,7 @@ describe('Flowchart HandDrawn', () => {
C -->|Two| E[iPhone] C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car] C -->|Three| F[fa:fa-car Car]
`, `,
{ look: 'handDrawn', flowchart: { useMaxWidth: false } } { look: 'handDrawn', handDrawnSeed: 1, flowchart: { useMaxWidth: false } }
); );
cy.get('svg').should((svg) => { cy.get('svg').should((svg) => {
// const height = parseFloat(svg.attr('height')); // const height = parseFloat(svg.attr('height'));
@@ -855,6 +874,7 @@ describe('Flowchart HandDrawn', () => {
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
htmlLabels: true, htmlLabels: true,
flowchart: { htmlLabels: true }, flowchart: { htmlLabels: true },
securityLevel: 'loose', securityLevel: 'loose',
@@ -884,6 +904,7 @@ describe('Flowchart HandDrawn', () => {
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
htmlLabels: true, htmlLabels: true,
flowchart: { htmlLabels: true }, flowchart: { htmlLabels: true },
securityLevel: 'loose', securityLevel: 'loose',
@@ -898,6 +919,7 @@ graph TD
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
htmlLabels: true, htmlLabels: true,
flowchart: { htmlLabels: true }, flowchart: { htmlLabels: true },
securityLevel: 'loose', securityLevel: 'loose',
@@ -915,6 +937,7 @@ graph TD
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
htmlLabels: true, htmlLabels: true,
flowchart: { htmlLabels: true }, flowchart: { htmlLabels: true },
securityLevel: 'loose', securityLevel: 'loose',
@@ -954,6 +977,7 @@ graph TD
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
htmlLabels: true, htmlLabels: true,
flowchart: { htmlLabels: true }, flowchart: { htmlLabels: true },
securityLevel: 'loose', securityLevel: 'loose',
@@ -975,6 +999,7 @@ graph TD
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
htmlLabels: true, htmlLabels: true,
flowchart: { htmlLabels: true }, flowchart: { htmlLabels: true },
securityLevel: 'loose', securityLevel: 'loose',
@@ -991,6 +1016,7 @@ graph TD
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
htmlLabels: true, htmlLabels: true,
flowchart: { htmlLabels: true }, flowchart: { htmlLabels: true },
securityLevel: 'loose', securityLevel: 'loose',
@@ -1006,6 +1032,7 @@ graph TD
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
htmlLabels: true, htmlLabels: true,
flowchart: { htmlLabels: true }, flowchart: { htmlLabels: true },
securityLevel: 'loose', securityLevel: 'loose',
@@ -1024,6 +1051,7 @@ graph TD
`, `,
{ {
look: 'handDrawn', look: 'handDrawn',
handDrawnSeed: 1,
flowchart: { htmlLabels: true }, flowchart: { htmlLabels: true },
securityLevel: 'loose', securityLevel: 'loose',
} }

View File

@@ -1,142 +0,0 @@
import { imgSnapshotTest } from '../../helpers/util.ts';
const aliasSet1 = ['process', 'rect', 'proc', 'rectangle'] as const;
const aliasSet2 = ['event', 'rounded'] as const;
const aliasSet3 = ['stadium', 'pill', 'terminal'] as const;
const aliasSet4 = ['fr-rect', 'subproc', 'subprocess', 'framed-rectangle', 'subroutine'] as const;
const aliasSet5 = ['db', 'database', 'cylinder', 'cyl'] as const;
const aliasSet6 = ['diam', 'decision', 'diamond'] as const;
const aliasSet7 = ['hex', 'hexagon', 'prepare'] as const;
const aliasSet8 = ['lean-r', 'lean-right', 'in-out'] as const;
const aliasSet9 = ['lean-l', 'lean-left', 'out-in'] as const;
const aliasSet10 = ['trap-b', 'trapezoid-bottom', 'priority'] as const;
const aliasSet11 = ['trap-t', 'trapezoid-top', 'manual'] as const;
const aliasSet12 = ['dbl-circ', 'double-circle'] as const;
const aliasSet13 = ['notched-rectangle', 'card', 'notch-rect'] as const;
const aliasSet14 = [
'lin-rect',
'lined-rectangle',
'lin-proc',
'lined-process',
'shaded-process',
] as const;
const aliasSet15 = ['sm-circ', 'small-circle', 'start'] as const;
const aliasSet16 = ['fr-circ', 'framed-circle', 'stop'] as const;
const aliasSet17 = ['fork', 'join'] as const;
// brace-r', 'braces'
const aliasSet18 = ['comment', 'brace-l'] as const;
const aliasSet19 = ['bolt', 'com-link', 'lightning-bolt'] as const;
const aliasSet20 = ['doc', 'document'] as const;
const aliasSet21 = ['delay', 'half-rounded-rectangle'] as const;
const aliasSet22 = ['h-cyl', 'das', 'horizontal-cylinder'] as const;
const aliasSet23 = ['lin-cyl', 'disk', 'lined-cylinder'] as const;
const aliasSet24 = ['curv-trap', 'display', 'curved-trapezoid'] as const;
const aliasSet25 = ['div-rect', 'div-proc', 'divided-rectangle', 'divided-process'] as const;
const aliasSet26 = ['extract', 'tri', 'triangle'] as const;
const aliasSet27 = ['win-pane', 'internal-storage', 'window-pane'] as const;
const aliasSet28 = ['f-circ', 'junction', 'filled-circle'] as const;
const aliasSet29 = ['lin-doc', 'lined-document'] as const;
const aliasSet30 = ['notch-pent', 'loop-limit', 'notched-pentagon'] as const;
const aliasSet31 = ['flip-tri', 'manual-file', 'flipped-triangle'] as const;
const aliasSet32 = ['sl-rect', 'manual-input', 'sloped-rectangle'] as const;
const aliasSet33 = ['docs', 'documents', 'st-doc', 'stacked-document'] as const;
const aliasSet34 = ['procs', 'processes', 'st-rect', 'stacked-rectangle'] as const;
const aliasSet35 = ['flag', 'paper-tape'] as const;
const aliasSet36 = ['bow-rect', 'stored-data', 'bow-tie-rectangle'] as const;
const aliasSet37 = ['cross-circ', 'summary', 'crossed-circle'] as const;
const aliasSet38 = ['tag-doc', 'tagged-document'] as const;
const aliasSet39 = ['tag-rect', 'tag-proc', 'tagged-rectangle', 'tagged-process'] as const;
const aliasSet40 = ['collate', 'hourglass'] as const;
// Aggregate all alias sets into a single array
const aliasSets = [
aliasSet1,
aliasSet2,
aliasSet3,
aliasSet4,
aliasSet5,
aliasSet6,
aliasSet7,
aliasSet8,
aliasSet9,
aliasSet10,
aliasSet11,
aliasSet12,
aliasSet13,
aliasSet14,
aliasSet15,
aliasSet16,
aliasSet17,
aliasSet18,
aliasSet19,
aliasSet20,
aliasSet21,
aliasSet22,
aliasSet23,
aliasSet24,
aliasSet25,
aliasSet26,
aliasSet27,
aliasSet28,
aliasSet29,
aliasSet30,
aliasSet31,
aliasSet32,
aliasSet33,
aliasSet34,
aliasSet35,
aliasSet36,
aliasSet37,
aliasSet38,
aliasSet39,
] as const;
aliasSets.forEach((aliasSet) => {
describe(`Test ${aliasSet.join(',')} `, () => {
it(`All ${aliasSet.join(',')} should render same shape`, () => {
let flowchartCode = `flowchart \n`;
aliasSet.forEach((alias, index) => {
flowchartCode += ` n${index}@{ shape: ${alias}, label: "${alias}" }\n`;
});
imgSnapshotTest(flowchartCode);
});
});
});

View File

@@ -99,7 +99,7 @@ describe('Flowchart v2', () => {
const style = svg.attr('style'); const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/); expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
expect(maxWidthValue).to.be.within(417 * 0.95, 417 * 1.05); expect(maxWidthValue).to.be.within(446 * 0.95 - 1, 446 * 1.05);
}); });
}); });
it('8: should render a flowchart when useMaxWidth is false', () => { it('8: should render a flowchart when useMaxWidth is false', () => {
@@ -118,7 +118,7 @@ describe('Flowchart v2', () => {
const width = parseFloat(svg.attr('width')); const width = parseFloat(svg.attr('width'));
// use within because the absolute value can be slightly different depending on the environment ±5% // 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(height).to.be.within(446 * 0.95, 446 * 1.05);
expect(width).to.be.within(417 * 0.95, 417 * 1.05); expect(width).to.be.within(446 * 0.95 - 1, 446 * 1.05);
expect(svg).to.not.have.attr('style'); expect(svg).to.not.have.attr('style');
}); });
}); });
@@ -786,7 +786,7 @@ A ~~~ B
`--- `---
title: Subgraph nodeSpacing and rankSpacing example title: Subgraph nodeSpacing and rankSpacing example
config: config:
flowchart: flowchart:
nodeSpacing: 250 nodeSpacing: 250
rankSpacing: 250 rankSpacing: 250
--- ---
@@ -1052,65 +1052,5 @@ end
} }
); );
}); });
it('Should render self-loops', () => {
imgSnapshotTest(
`flowchart
A --> A
subgraph B
B1 --> B1
end
subgraph C
subgraph C1
C2 --> C2
subgraph D
D1 --> D1
end
D --> D
end
C1 --> C1
end
`,
{
flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } },
}
);
});
});
describe('New @ sytax for node metadata edge cases', () => {
it('should be possible to use @ syntax to add labels on multi nodes', () => {
imgSnapshotTest(
`flowchart TB
n2["label for n2"] & n4@{ label: "labe for n4"} & n5@{ label: "labe for n5"}
`,
{}
);
});
it('should be possible to use @ syntax to add labels with trail spaces and &', () => {
imgSnapshotTest(
`flowchart TB
n2["label for n2"] & n4@{ label: "labe for n4"} & n5@{ label: "labe for n5"}
`,
{}
);
});
it('should be possible to use @ syntax to add labels with trail spaces', () => {
imgSnapshotTest(
`flowchart TB
n2["label for n2"]
n4@{ label: "labe for n4"}
n5@{ label: "labe for n5"}
`,
{}
);
});
it('should be possible to use @ syntax to add labels with trail spaces and edge/link', () => {
imgSnapshotTest(
`flowchart TD
A["A"] --> B["for B"] & C@{ label: "for c"} & E@{label : "for E"}
D@{label: "for D"}
`,
{}
);
});
}); });
}); });

View File

@@ -895,7 +895,7 @@ graph TD
imgSnapshotTest( imgSnapshotTest(
` `
graph TD 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 hello --> default
`, `,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
@@ -917,21 +917,4 @@ 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',
}
);
});
}); });

View File

@@ -1,143 +0,0 @@
import { imgSnapshotTest } from '../../helpers/util';
const looks = ['classic', 'handDrawn'] as const;
const directions = [
'TB',
//'BT',
'LR',
// 'RL'
] as const;
const forms = [undefined, 'square', 'circle', 'rounded'] as const;
const labelPos = [undefined, 't', 'b'] as const;
looks.forEach((look) => {
directions.forEach((direction) => {
forms.forEach((form) => {
labelPos.forEach((pos) => {
describe(`Test iconShape in ${form ? `${form} form,` : ''} ${look} look and dir ${direction} with label position ${pos ? pos : 'not defined'}`, () => {
it(`without label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> nAA@{ icon: 'fa:bell'`;
if (form) {
flowchartCode += `, form: '${form}'`;
}
flowchartCode += ` }\n`;
imgSnapshotTest(flowchartCode, { look });
});
it(`with label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is a label for icon shape'`;
if (form) {
flowchartCode += `, form: '${form}'`;
}
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
imgSnapshotTest(flowchartCode, { look });
});
it(`with very long label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is a very very very very very long long long label for icon shape'`;
if (form) {
flowchartCode += `, form: '${form}'`;
}
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
imgSnapshotTest(flowchartCode, { look });
});
it(`with markdown htmlLabels:true`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is **bold** </br>and <strong>strong</strong> for icon shape'`;
if (form) {
flowchartCode += `, form: '${form}'`;
}
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
imgSnapshotTest(flowchartCode, { look });
});
it(`with markdown htmlLabels:false`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is **bold** </br>and <strong>strong</strong> for icon shape'`;
if (form) {
flowchartCode += `, form: '${form}'`;
}
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
imgSnapshotTest(flowchartCode, {
look,
htmlLabels: false,
flowchart: { htmlLabels: false },
});
});
it(`with styles`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'new icon shape'`;
if (form) {
flowchartCode += `, form: '${form}'`;
}
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
flowchartCode += ` style nAA fill:#f9f,stroke:#333,stroke-width:4px \n`;
imgSnapshotTest(flowchartCode, { look });
});
it(`with classDef`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5\n`;
flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'new icon shape'`;
if (form) {
flowchartCode += `, form: '${form}'`;
}
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
flowchartCode += ` nAA:::customClazz\n`;
imgSnapshotTest(flowchartCode, { look });
});
});
});
});
});
});
describe('Test iconShape with different h', () => {
it('with different h', () => {
let flowchartCode = `flowchart TB\n`;
const icon = 'fa:bell';
const iconHeight = 64;
flowchartCode += ` nA --> nAA@{ icon: '${icon}', label: 'icon with different h', h: ${iconHeight} }\n`;
imgSnapshotTest(flowchartCode);
});
});
describe('Test colored iconShape', () => {
it('with no styles', () => {
let flowchartCode = `flowchart TB\n`;
const icon = 'fluent-emoji:tropical-fish';
flowchartCode += ` nA --> nAA@{ icon: '${icon}', form: 'square', label: 'icon with color' }\n`;
imgSnapshotTest(flowchartCode);
});
it('with styles', () => {
let flowchartCode = `flowchart TB\n`;
const icon = 'fluent-emoji:tropical-fish';
flowchartCode += ` nA --> nAA@{ icon: '${icon}', form: 'square', label: 'icon with color' }\n`;
flowchartCode += ` style nAA fill:#f9f,stroke:#333,stroke-width:4px \n`;
imgSnapshotTest(flowchartCode);
});
});

View File

@@ -1,103 +0,0 @@
import { imgSnapshotTest } from '../../helpers/util';
const looks = ['classic', 'handDrawn'] as const;
const directions = [
'TB',
//'BT',
'LR',
// 'RL'
] as const;
const labelPos = [undefined, 't', 'b'] as const;
looks.forEach((look) => {
directions.forEach((direction) => {
labelPos.forEach((pos) => {
describe(`Test imageShape in ${look} look and dir ${direction} with label position ${pos ? pos : 'not defined'}`, () => {
it(`without label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', w: '100', h: '100' }\n`;
imgSnapshotTest(flowchartCode, { look });
});
it(`with label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is a label for image shape'`;
flowchartCode += `, w: '100', h: '200'`;
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
imgSnapshotTest(flowchartCode, { look });
});
it(`with very long label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is a very very very very very long long long label for image shape'`;
flowchartCode += `, w: '100', h: '250'`;
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
imgSnapshotTest(flowchartCode, { look });
});
it(`with markdown htmlLabels:true`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is **bold** </br>and <strong>strong</strong> for image shape'`;
flowchartCode += `, w: '550', h: '200'`;
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
imgSnapshotTest(flowchartCode, { look, htmlLabels: true });
});
it(`with markdown htmlLabels:false`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is **bold** </br>and <strong>strong</strong> for image shape'`;
flowchartCode += `, w: '250', h: '200'`;
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
imgSnapshotTest(flowchartCode, {
look,
htmlLabels: false,
flowchart: { htmlLabels: false },
});
});
it(`with styles`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'new image shape'`;
flowchartCode += `, w: '550', h: '200'`;
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
flowchartCode += ` style A fill:#f9f,stroke:#333,stroke-width:4px \n`;
imgSnapshotTest(flowchartCode, { look });
});
it(`with classDef`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#000000,stroke-dasharray: 5 5\n`;
flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'new image shape'`;
flowchartCode += `, w: '500', h: '550'`;
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
flowchartCode += ` A:::customClazz\n`;
imgSnapshotTest(flowchartCode, { look });
});
});
});
});
});

View File

@@ -1,136 +0,0 @@
import { imgSnapshotTest } from '../../helpers/util.ts';
describe('Kanban diagram', () => {
it('1: should render a kanban with a single section', () => {
imgSnapshotTest(
`kanban
id1[Todo]
docs[Create Documentation]
docs[Create Blog about the new diagram]
`,
{}
);
});
it('2: should render a kanban with multiple sections', () => {
imgSnapshotTest(
`kanban
id1[Todo]
docs[Create Documentation]
id2
docs[Create Blog about the new diagram]
`,
{}
);
});
it('3: should render a kanban with a single wrapping node', () => {
imgSnapshotTest(
`kanban
id1[Todo]
id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping]
`,
{}
);
});
it('4: should handle the height of a section with a wrapping node at the end', () => {
imgSnapshotTest(
`kanban
id1[Todo]
id2[One line]
id3[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping]
`,
{}
);
});
it('5: should handle the height of a section with a wrapping node at the top', () => {
imgSnapshotTest(
`kanban
id1[Todo]
id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping]
id3[One line]
`,
{}
);
});
it('6: should handle the height of a section with a wrapping node in the middle', () => {
imgSnapshotTest(
`kanban
id1[Todo]
id2[One line]
id3[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping]
id4[One line]
`,
{}
);
});
it('6: should handle assigments', () => {
imgSnapshotTest(
`kanban
id1[Todo]
docs[Create Documentation]
id2[In progress]
docs[Create Blog about the new diagram]@{ assigned: 'knsv' }
`,
{}
);
});
it('7: should handle prioritization', () => {
imgSnapshotTest(
`kanban
id2[In progress]
vh[Very High]@{ priority: 'Very High' }
h[High]@{ priority: 'High' }
m[Default priority]
l[Low]@{ priority: 'Low' }
vl[Very Low]@{ priority: 'Very Low' }
`,
{}
);
});
it('7: should handle external tickets', () => {
imgSnapshotTest(
`kanban
id1[Todo]
docs[Create Documentation]
id2[In progress]
docs[Create Blog about the new diagram]@{ ticket: MC-2037 }
`,
{}
);
});
it('8: should handle assignments, prioritization and tickets ids in the same item', () => {
imgSnapshotTest(
`kanban
id2[In progress]
docs[Create Blog about the new diagram]@{ priority: 'Very Low', ticket: MC-2037, assigned: 'knsv' }
`,
{}
);
});
it('10: Full example', () => {
imgSnapshotTest(
`---
config:
kanban:
ticketBaseUrl: 'https://abc123.atlassian.net/browse/#TICKET#'
---
kanban
id1[Todo]
docs[Create Documentation]
docs[Create Blog about the new diagram]
id7[In progress]
id6[Create renderer so that it works in all cases. We also add som extra text here for testing purposes. And some more just for the extra flare.]
id8[Design grammar]@{ assigned: 'knsv' }
id9[Ready for deploy]
id10[Ready for test]
id11[Done]
id5[define getData]
id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char]@{ ticket: MC-2036, priority: 'Very High'}
id3[Update DB function]@{ ticket: MC-2037, assigned: knsv, priority: 'High' }
id4[Create parsing tests]@{ ticket: MC-2038, assigned: 'K.Sveidqvist', priority: 'High' }
id66[last item]@{ priority: 'Very Low', assigned: 'knsv' }
id12[Can't reproduce]
`,
{}
);
});
});

View File

@@ -1,146 +0,0 @@
import { imgSnapshotTest } from '../../helpers/util.ts';
const looks = ['classic', 'handDrawn'] as const;
const directions = [
'TB',
//'BT',
'LR',
//'RL'
] as const;
const newShapesSet1 = [
'triangle',
'sloped-rectangle',
'horizontal-cylinder',
'flipped-triangle',
'hourglass',
] as const;
const newShapesSet2 = [
'tagged-rectangle',
'documents',
'lightning-bolt',
'filled-circle',
'window-pane',
] as const;
const newShapesSet3 = [
'curved-trapezoid',
'bow-rect',
'tagged-document',
'divided-rectangle',
'crossed-circle',
] as const;
const newShapesSet4 = [
'document',
'notched-pentagon',
'lined-cylinder',
'stacked-document',
'half-rounded-rectangle',
] as const;
const newShapesSet5 = [
'lined-document',
'tagged-document',
'brace-l',
'comment',
'braces',
'brace-r',
] as const;
const newShapesSet6 = ['brace-r', 'braces'] as const;
// Aggregate all shape sets into a single array
const newShapesSets = [
newShapesSet1,
newShapesSet2,
newShapesSet3,
newShapesSet4,
newShapesSet5,
newShapesSet6,
];
looks.forEach((look) => {
directions.forEach((direction) => {
newShapesSets.forEach((newShapesSet) => {
describe(`Test ${newShapesSet.join(', ')} in ${look} look and dir ${direction}`, () => {
it(`without label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape} }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`with label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is a label for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`connect all shapes with each other`, () => {
let flowchartCode = `flowchart ${direction}\n`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index}${index}@{ shape: ${newShape}, label: 'This is a label for ${newShape} shape' }\n`;
});
for (let i = 0; i < newShapesSet.length; i++) {
for (let j = i + 1; j < newShapesSet.length; j++) {
flowchartCode += ` n${i}${i} --> n${j}${j}\n`;
}
}
if (!(direction === 'TB' && look === 'handDrawn' && newShapesSet === newShapesSet1)) {
//skip this test, works in real. Need to look
imgSnapshotTest(flowchartCode, { look });
}
});
it(`with very long label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is a very very very very very long long long label for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`with markdown htmlLabels:true`, () => {
let flowchartCode = `flowchart ${direction}\n`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is **bold** </br>and <strong>strong</strong> for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`with markdown htmlLabels:false`, () => {
let flowchartCode = `flowchart ${direction}\n`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is **bold** </br>and <strong>strong</strong> for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, {
look,
htmlLabels: false,
flowchart: { htmlLabels: false },
});
});
it(`with styles`, () => {
let flowchartCode = `flowchart ${direction}\n`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'new ${newShape} shape' }\n`;
flowchartCode += ` style n${index}${index} fill:#f9f,stroke:#333,stroke-width:4px \n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`with classDef`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5\n`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'new ${newShape} shape' }\n`;
flowchartCode += ` n${index}${index}:::customClazz\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
});
});
});
});

View File

@@ -1,107 +0,0 @@
import { imgSnapshotTest } from '../../helpers/util';
const looks = ['classic', 'handDrawn'] as const;
const directions = [
'TB',
//'BT',
'LR',
//'RL'
] as const;
const shapesSet1 = ['text', 'card', 'lin-rect', 'diamond', 'hexagon'] as const;
// removing labelRect, need have alias for it
const shapesSet2 = ['rounded', 'rect', 'start', 'stop'] as const;
const shapesSet3 = ['fork', 'choice', 'note', 'stadium', 'odd'] as const;
const shapesSet4 = ['subroutine', 'cylinder', 'circle', 'doublecircle', 'odd'] as const;
const shapesSet5 = ['anchor', 'lean-r', 'lean-l', 'trap-t', 'trap-b'] as const;
// Aggregate all shape sets into a single array
const shapesSets = [shapesSet1, shapesSet2, shapesSet3, shapesSet4, shapesSet5] as const;
looks.forEach((look) => {
directions.forEach((direction) => {
shapesSets.forEach((shapesSet) => {
describe(`Test ${shapesSet.join(', ')} in ${look} look and dir ${direction}`, () => {
it(`without label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape} }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`with label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is a label for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`connect all shapes with each other`, () => {
let flowchartCode = `flowchart ${direction}\n`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index}${index}@{ shape: ${newShape}, label: 'This is a label for ${newShape} shape' }\n`;
});
for (let i = 0; i < shapesSet.length; i++) {
for (let j = i + 1; j < shapesSet.length; j++) {
flowchartCode += ` n${i}${i} --> n${j}${j}\n`;
}
}
imgSnapshotTest(flowchartCode, { look });
});
it(`with very long label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is a very very very very very long long long label for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`with markdown htmlLabels:true`, () => {
let flowchartCode = `flowchart ${direction}\n`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is **bold** </br>and <strong>strong</strong> for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`with markdown htmlLabels:false`, () => {
let flowchartCode = `flowchart ${direction}\n`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is **bold** </br>and <strong>strong</strong> for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, {
look,
htmlLabels: false,
flowchart: { htmlLabels: false },
});
});
it(`with styles`, () => {
let flowchartCode = `flowchart ${direction}\n`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'new ${newShape} shape' }\n`;
flowchartCode += ` style n${index}${index} fill:#f9f,stroke:#333,stroke-width:4px \n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`with classDef`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5\n`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'new ${newShape} shape' }\n`;
flowchartCode += ` n${index}${index}:::customClazz\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
});
});
});
});

View File

@@ -1,79 +0,0 @@
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' } } }
);
});
});

View File

@@ -1,703 +0,0 @@
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
);
});
});
});

View File

@@ -1,52 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Architecture Mermaid Test Page</title>
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=" />
<style>
div.mermaid {
/* font-family: 'trebuchet ms', verdana, arial; */
font-family: 'Courier New', Courier, monospace !important;
}
</style>
</head>
<body>
<h2>External Icons Demo</h2>
<pre class="mermaid">
architecture-beta
service s3(logos:aws-s3)[Cloud Store]
service ec2(logos:aws-ec2)[Server]
service api(logos:aws-api-gateway)[Api Gateway]
service fa(fa:image)[Font Awesome Icon]
</pre>
<script type="module">
import mermaid from './mermaid.esm.mjs';
mermaid.initialize({
startOnLoad: false,
logLevel: 0,
});
mermaid.registerIconPacks([
{
name: 'logos',
loader: () =>
fetch('https://unpkg.com/@iconify-json/logos/icons.json').then((res) => res.json()),
},
{
name: 'fa',
loader: () =>
fetch('https://unpkg.com/@iconify-json/fa6-regular/icons.json').then((res) =>
res.json()
),
},
]);
await mermaid.run();
if (window.Cypress) {
window.rendered = true;
}
</script>
</body>
</html>

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css" href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
@@ -30,8 +30,8 @@
.mermaid svg { .mermaid svg {
/* font-size: 18px !important; */ /* font-size: 18px !important; */
background-color: #eee; background-color: #eee;
background-image: background-image: radial-gradient(#fff 1%, transparent 11%),
radial-gradient(#fff 1%, transparent 11%), radial-gradient(#fff 1%, transparent 11%); radial-gradient(#fff 1%, transparent 11%);
background-size: 20px 20px; background-size: 20px 20px;
background-position: background-position:
0 0, 0 0,

View File

@@ -3,7 +3,7 @@
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" /> <link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/> />
<link <link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css" href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/> />
<link <link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css" href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -3,7 +3,7 @@
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" /> <link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -3,7 +3,7 @@
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" /> <link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -3,7 +3,7 @@
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" /> <link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/> />
<link <link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css" href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
@@ -30,8 +30,8 @@
.mermaid svg { .mermaid svg {
/* font-size: 18px !important; */ /* font-size: 18px !important; */
background-color: #efefef; background-color: #efefef;
background-image: background-image: radial-gradient(#fff 51%, transparent 91%),
radial-gradient(#fff 51%, transparent 91%), radial-gradient(#fff 51%, transparent 91%); radial-gradient(#fff 51%, transparent 91%);
background-size: 20px 20px; background-size: 20px 20px;
background-position: background-position:
0 0, 0 0,

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css" href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"

View File

@@ -4,16 +4,12 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/> />
<link <link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css" href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
rel="stylesheet" rel="stylesheet"
/> />
<link
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css"
rel="stylesheet"
/>
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
rel="stylesheet" rel="stylesheet"
@@ -38,7 +34,6 @@
/* background: rgb(221, 208, 208); */ /* background: rgb(221, 208, 208); */
/* background: #333; */ /* background: #333; */
font-family: 'Arial'; font-family: 'Arial';
/* color: white; */
/* font-size: 18px !important; */ /* font-size: 18px !important; */
} }
@@ -79,354 +74,101 @@
font-size: 72px; font-size: 72px;
} }
pre {
width: 100%;
}
/* tspan { /* tspan {
font-size: 6px !important; font-size: 6px !important;
} */ } */
/* .flowchart-link {
stroke-dasharray: 4, 4 !important;
animation: flow 1s linear infinite;
animation: dashdraw 4.93282s linear infinite;
stroke-width: 2px !important;
} */
@keyframes dashdraw {
from {
stroke-dashoffset: 0;
}
}
/*stroke-width:2;stroke-dasharray:10.000000,9.865639;stroke-dashoffset:-198.656393;animation: 4.932820s linear infinite;*/
/* stroke-width:2;stroke-dasharray:10.000000,9.865639;stroke-dashoffset:-198.656393;animation: dashdraw 4.932820s linear infinite;*/
</style> </style>
</head> </head>
<body> <body>
<pre id="diagram4" class="mermaid"> <div class="flex">
flowchart LR <pre id="diagram" class="mermaid">
AB["apa@apa@"] --> B(("`apa@apa`"))
</pre>
<pre id="diagram4" class="mermaid">
flowchart
D(("for D"))
</pre>
<pre id="diagram4" class="mermaid">
flowchart LR
A e1@==> B
e1@{ animate: true}
</pre>
<pre id="diagram4" class="mermaid">
flowchart LR
A e1@--> B
classDef animate stroke-width:2,stroke-dasharray:10\,8,stroke-dashoffset:-180,animation: edge-animation-frame 6s linear infinite, stroke-linecap: round
class e1 animate
</pre>
<h2>infinite</h2>
<pre id="diagram4" class="mermaid2">
flowchart LR
A e1@--> B
classDef animate stroke-dasharray: 9\,5,stroke-dashoffset: 900,animation: dash 25s linear infinite;
class e1 animate
</pre>
<h2>Mermaid - edge-animation-slow</h2>
<pre id="diagram4" class="mermaid2">
flowchart LR
A e1@--> B
e1@{ animation: fast}
</pre>
<h2>Mermaid - edge-animation-fast</h2>
<pre id="diagram4" class="mermaid2">
flowchart LR
A e1@--> B
classDef animate stroke-dasharray: 1000,stroke-dashoffset: 1000,animation: dash 10s linear;
class e1 edge-animation-fast
</pre>
<pre id="diagram4" class="mermaid2">
info </pre
>
<pre id="diagram4" class="mermaid2">
--- ---
config: title: hello2
layout: elk config:
--- look: handDrawn
flowchart LR layout: elk
a elk:
subgraph s0["APA"] nodePlacementStrategy: BRANDES_KOEPF
subgraph s8["APA"]
subgraph s1["APA"]
D{"X"}
E[Q]
end
subgraph s3["BAPA"]
F[Q]
I
end
D --> I
D --> I
D --> I
I{"X"}
end
end
</pre>
<pre id="diagram4" class="mermaid2">
---
config:
layout: elk
---
flowchart LR
a
D{"Use the editor"}
D -- Mermaid js --> I{"fa:fa-code Text"}
D-->I
D-->I
</pre>
<pre id="diagram4" class="mermaid2">
---
config:
layout: elk
--- ---
flowchart LR flowchart LR
subgraph s1["Untitled subgraph"] A[Start] --Some text--> B(Continue)
n1["Evaluate"] B --> C{Evaluate}
n2["Option 1"] C -- One --> D[Option 1]
n3["Option 2"] C -- Two --> E[Option 2]
n4["fa:fa-car Option 3"] C -- Three --> F[fa:fa-car Option 3]
end
subgraph s2["Untitled subgraph"]
n5["Evaluate"]
n6["Option 1"]
n7["Option 2"]
n8["fa:fa-car Option 3"]
end
A["Start"] -- Some text --> B("Continue")
B --> C{"Evaluate"}
C -- One --> D["Option 1"]
C -- Two --> E["Option 2"]
C -- Three --> F["fa:fa-car Option 3"]
n1 -- One --> n2
n1 -- Two --> n3
n1 -- Three --> n4
n5 -- One --> n6
n5 -- Two --> n7
n5 -- Three --> n8
n1@{ shape: diam}
n2@{ shape: rect}
n3@{ shape: rect}
n4@{ shape: rect}
n5@{ shape: diam}
n6@{ shape: rect}
n7@{ shape: rect}
n8@{ shape: rect}
</pre>
<pre id="diagram4" class="mermaid2">
---
config:
layout: elk
---
flowchart LR
subgraph s1["Untitled subgraph"]
n1["Evaluate"]
n2["Option 1"]
end
n1 -- One --> n2
</pre>
<pre id="diagram4" class="mermaid2">
---
config:
layout: elk
---
flowchart LR
A{A} --> B & C
</pre </pre
> >
<pre id="diagram4" class="mermaid2"> <pre id="diagram" class="mermaid2">
--- ---
config: config:
layout: elk look: handdrawn
flowchart:
htmlLabels: true
--- ---
flowchart LR flowchart
A{A} --> B & C A[I am a long text, where do I go??? handdrawn - true]
subgraph "subbe"
A
end
</pre </pre
> >
<pre id="diagram4" class="mermaid2"> </div>
<div class="flex">
<pre id="diagram" class="mermaid2">
--- ---
config: config:
layout: elk flowchart:
htmlLabels: false
--- ---
flowchart LR flowchart
n2@{ shape: rect} A[I am a long text, where do I go??? classic - false]
n3@{ shape: rect} </pre
n4@{ shape: rect} >
A["Start"] -- Some text --> B("Continue") <pre id="diagram" class="mermaid2">
B --> C{"Evaluate"}
C -- One --> D["Option 1"]
C -- Two --> E["Option 2"]
C -- Three --> F["fa:fa-car Option 3"]
%% C@{ shape: hexagon}
</pre>
<pre id="diagram4" class="mermaid2">
--- ---
config: config:
kanban: flowchart:
ticketBaseUrl: 'https://github.com/your-repo/issues/#TICKET#' htmlLabels: true
--- ---
kanban flowchart
Backlog A[I am a long text, where do I go??? classic - true]
task1[📝 Define project requirements]@{ ticket: a101 } </pre
To Do >
task2[🔍 Research technologies]@{ ticket: a102 } </div>
Review <pre id="diagram2" class="mermaid2">
task4[🔍 Code review for login feature]@{ ticket: a104 } flowchart LR
Done id1(Start)-->id2(Stop)
task5[✅ Deploy initial version]@{ ticket: a105 } style id1 fill:#f9f,stroke:#333,stroke-width:4px
In Progress style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
task3[💻 Develop login feature]@{ ticket: 103 }
</pre> </pre>
<pre id="diagram4" class="mermaid2">
flowchart LR <pre id="diagram3" class="mermaid2">
nA[Default] --> A@{ icon: 'fa:bell', form: 'rounded' } flowchart LR
A:::foo & B:::bar --> C:::foobar
classDef foo stroke:#f00
classDef bar stroke:#0f0
classDef ash color:red
class C ash
style C stroke:#00f, fill:black
</pre> </pre>
<pre id="diagram4" class="mermaid2"> <pre id="diagram4" class="mermaid2">
flowchart LR stateDiagram
nA[Style] --> A@{ icon: 'fa:bell', form: 'rounded' } A:::foo
style A fill:#f9f,stroke:#333,stroke-width:4px B:::bar --> C:::foobar
</pre> classDef foo stroke:#f00
<pre id="diagram4" class="mermaid2"> classDef bar stroke:#0f0
flowchart LR style C stroke:#00f, fill:black, color:white
nA[Class] --> A@{ icon: 'fa:bell', form: 'rounded' }
A:::AClass
classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
</pre>
<pre id="diagram4" class="mermaid2">
flowchart LR
nA[Class] --> A@{ icon: 'logos:aws', form: 'rounded' }
</pre> </pre>
<pre id="diagram4" class="mermaid2">
flowchart LR
nA[Default] --> A@{ icon: 'fa:bell', form: 'square' }
</pre>
<pre id="diagram4" class="mermaid2">
flowchart LR
nA[Style] --> A@{ icon: 'fa:bell', form: 'square' }
style A fill:#f9f,stroke:#333,stroke-width:4px
</pre>
<pre id="diagram4" class="mermaid2">
flowchart LR
nA[Class] --> A@{ icon: 'fa:bell', form: 'square' }
A:::AClass
classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
</pre>
<pre id="diagram4" class="mermaid2">
flowchart LR
nA[Class] --> A@{ icon: 'logos:aws', form: 'square' }
</pre>
<pre id="diagram4" class="mermaid2">
flowchart LR
nA[Default] --> A@{ icon: 'fa:bell', form: 'circle' }
</pre>
<pre id="diagram4" class="mermaid2">
flowchart LR
nA[Style] --> A@{ icon: 'fa:bell', form: 'circle' }
style A fill:#f9f,stroke:#333,stroke-width:4px
</pre>
<pre id="diagram4" class="mermaid2">
flowchart LR
nA[Class] --> A@{ icon: 'fa:bell', form: 'circle' }
A:::AClass
classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
</pre>
<pre id="diagram4" class="mermaid2">
flowchart LR
nA[Class] --> A@{ icon: 'logos:aws', form: 'circle' }
A:::AClass
classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
</pre>
<pre id="diagram4" class="mermaid2">
flowchart LR
nA[Style] --> A@{ icon: 'logos:aws', form: 'circle' }
style A fill:#f9f,stroke:#333,stroke-width:4px
</pre>
<pre id="diagram4" class="mermaid2">
kanban
id2[In progress]
docs[Create Blog about the new diagram]@{ priority: 'Very Low', ticket: MC-2037, assigned: 'knsv' }
</pre>
<pre id="diagram4" class="mermaid2">
---
config:
kanban:
ticketBaseUrl: 'https://mermaidchart.atlassian.net/browse/#TICKET#'
# sectionWidth: 300
---
kanban
Todo
[Create Documentation]
docs[Create Blog about the new diagram]
id7[In progress]
id6[Create renderer so that it works in all cases. We also add som extra text here for testing purposes. And some more just for the extra flare.]
id9[Ready for deploy]
id8[Design grammar]@{ assigned: 'knsv' }
id10[Ready for test]
id4[Create parsing tests]@{ ticket: MC-2038, assigned: 'K.Sveidqvist', priority: 'High' }
id66[last item]@{ priority: 'Very Low', assigned: 'knsv' }
id11[Done]
id5[define getData]
id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char]@{ ticket: MC-2036, priority: 'Very High'}
id3[Update DB function]@{ ticket: MC-2037, assigned: knsv, priority: 'High' }
id12[Can't reproduce]
id3[Weird flickering in Firefox]
</pre>
<script type="module"> <script type="module">
import mermaid from './mermaid.esm.mjs'; import mermaid from './mermaid.esm.mjs';
import layouts from './mermaid-layout-elk.esm.mjs'; import layouts from './mermaid-layout-elk.esm.mjs';
const staticBellIconPack = {
prefix: 'fa6-regular',
icons: {
bell: {
body: '<path fill="currentColor" d="M224 0c-17.7 0-32 14.3-32 32v19.2C119 66 64 130.6 64 208v25.4c0 45.4-15.5 89.5-43.8 124.9L5.3 377c-5.8 7.2-6.9 17.1-2.9 25.4S14.8 416 24 416h400c9.2 0 17.6-5.3 21.6-13.6s2.9-18.2-2.9-25.4l-14.9-18.6c-28.3-35.5-43.8-79.6-43.8-125V208c0-77.4-55-142-128-156.8V32c0-17.7-14.3-32-32-32m0 96c61.9 0 112 50.1 112 112v25.4c0 47.9 13.9 94.6 39.7 134.6H72.3c25.8-40 39.7-86.7 39.7-134.6V208c0-61.9 50.1-112 112-112m64 352H160c0 17 6.7 33.3 18.7 45.3S207 512 224 512s33.3-6.7 45.3-18.7S288 465 288 448"/>',
width: 448,
},
},
width: 512,
height: 512,
};
mermaid.registerIconPacks([
{
name: 'logos',
loader: () =>
fetch('https://unpkg.com/@iconify-json/logos@1/icons.json').then((res) => res.json()),
},
{
name: 'fa',
loader: () => staticBellIconPack,
},
]);
mermaid.registerLayoutLoaders(layouts); mermaid.registerLayoutLoaders(layouts);
mermaid.parseError = function (err, hash) { mermaid.parseError = function (err, hash) {
console.error('Mermaid error: ', err); console.error('Mermaid error: ', err);
@@ -434,13 +176,8 @@ kanban
window.callback = function () { window.callback = function () {
alert('A callback was triggered'); alert('A callback was triggered');
}; };
function callback() { mermaid.initialize({
alert('It worked');
}
await mermaid.initialize({
// theme: 'base', // theme: 'base',
// theme: 'default',
// theme: 'forest',
// handDrawnSeed: 12, // handDrawnSeed: 12,
// look: 'handDrawn', // look: 'handDrawn',
// 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX', // 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX',
@@ -449,25 +186,21 @@ kanban
// layout: 'fixed', // layout: 'fixed',
// htmlLabels: false, // htmlLabels: false,
flowchart: { titleTopMargin: 10 }, flowchart: { titleTopMargin: 10 },
// fontFamily: 'Caveat', // fontFamily: 'Caveat',
// fontFamily: 'Kalam', // fontFamily: 'Kalam',
// fontFamily: 'courier', // fontFamily: 'courier',
fontFamily: 'arial',
sequence: { sequence: {
actorFontFamily: 'courier', actorFontFamily: 'courier',
noteFontFamily: 'courier', noteFontFamily: 'courier',
messageFontFamily: 'courier', messageFontFamily: 'courier',
}, },
kanban: {
htmlLabels: false,
},
fontSize: 12, fontSize: 12,
logLevel: 0, logLevel: 0,
securityLevel: 'loose', securityLevel: 'loose',
callback,
}); });
function callback() {
alert('It worked');
}
mermaid.parseError = function (err, hash) { mermaid.parseError = function (err, hash) {
console.error('In parse error:'); console.error('In parse error:');
console.error(err); console.error(err);

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -1,141 +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/6.7.2/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"
/>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Caveat:wght@400..700&family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&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: #efefef;
background-image: radial-gradient(#fff 51%, transparent 91%),
radial-gradient(#fff 51%, transparent 91%);
background-size: 20px 20px;
background-position:
0 0,
10px 10px;
background-repeat: repeat; */
}
</style>
</head>
<body style="display: flex; gap: 2rem; flex-direction: row">
<pre id="diagram4" class="mermaid">
flowchart
A --> A
subgraph B
B1 --> B1
end
subgraph C
subgraph C1
C2 --> C2
subgraph D
D1 --> D1
end
D --> D
end
C1 --> C1
end
</pre>
<script type="module">
import mermaid from './mermaid.esm.mjs';
import layouts from './mermaid-layout-elk.esm.mjs';
mermaid.registerLayoutLoaders(layouts);
mermaid.registerIconPacks([
{
name: 'logos',
loader: () =>
fetch('https://unpkg.com/@iconify-json/logos/icons.json').then((res) => res.json()),
},
{
name: 'fa',
loader: () =>
fetch('https://unpkg.com/@iconify-json/fa6-solid/icons.json').then((res) => res.json()),
},
]);
mermaid.parseError = function (err, hash) {
console.error('Mermaid error: ', err);
};
window.callback = function () {
alert('A callback was triggered');
};
mermaid.initialize({
// theme: 'base',
// handdrawnSeed: 12,
look: 'classic',
// 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX',
// 'elk.nodePlacement.strategy': 'SIMPLE',
// 'elk.nodePlacement.strategy': 'LAYERED',
// 'elk.mergeEdges': true,
// layout: 'dagre',
// layout: 'elk',
// layout: 'fixed',
// htmlLabels: false,
flowchart: { titleTopMargin: 10, padding: 0, htmlLabels: true },
// fontFamily: 'Caveat',
// fontFamily: 'Kalam',
fontFamily: 'courier',
sequence: {
actorFontFamily: 'courier',
noteFontFamily: 'courier',
messageFontFamily: 'courier',
},
themeVariables: {
fontSize: 50,
fontFamily: 'courier',
},
logLevel: 0,
securityLevel: 'loose',
});
function callback() {
alert('It worked');
}
mermaid.parseError = function (err, hash) {
console.error('In parse error:');
console.error(err);
};
</script>
</body>
</html>

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -3,7 +3,7 @@
<head> <head>
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" /> <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 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/6.7.2/css/font-awesome.min.css" /> <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://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" /> <link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet" />
<link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.googleapis.com" />

File diff suppressed because one or more lines are too long

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

View File

@@ -4,7 +4,7 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"

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