Merge from upstream mermaid os develop

This commit is contained in:
Ashish Jain
2024-10-09 11:19:40 +02:00
124 changed files with 3398 additions and 1119 deletions

View File

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

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
fix: Jagged edge fix for icon shape

View File

@@ -1,5 +0,0 @@
---
'mermaid': patch
---
Fix for issue with calculation of label width when using in firefox

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
Add missing TypeScript dependencies

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
fix: Icon color fix for colored icons.

View File

@@ -1,5 +0,0 @@
---
'@mermaid-js/layout-elk': patch
---
chore: Update render options

View File

@@ -1,5 +0,0 @@
---
'mermaid': minor
---
New Flowchart Shapes (with new syntax)

View File

@@ -1,5 +0,0 @@
---
'mermaid': patch
---
Ban DOMPurify v3.1.7 as a dependency

View File

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

View File

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

5
.github/lychee.toml vendored
View File

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

View File

@@ -19,7 +19,7 @@ jobs:
# uses version from "packageManager" field in package.json
- name: Setup Node.js
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
cache: pnpm
node-version-file: '.node-version'

View File

@@ -23,7 +23,7 @@ jobs:
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- name: Setup Node.js
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
cache: pnpm
node-version-file: '.node-version'

View File

@@ -36,7 +36,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@2c779ab0d087cd7fe7b826087247c2c81f27bfa6 # v3.26.5
uses: github/codeql-action/init@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
with:
config-file: ./.github/codeql/codeql-config.yml
languages: ${{ matrix.language }}
@@ -48,7 +48,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@2c779ab0d087cd7fe7b826087247c2c81f27bfa6 # v3.26.5
uses: github/codeql-action/autobuild@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@@ -62,4 +62,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@2c779ab0d087cd7fe7b826087247c2c81f27bfa6 # v3.26.5
uses: github/codeql-action/analyze@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12

View File

@@ -38,7 +38,7 @@ jobs:
# uses version from "packageManager" field in package.json
- name: Setup Node.js
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version-file: '.node-version'

53
.github/workflows/e2e-timings.yml vendored Normal file
View File

@@ -0,0 +1,53 @@
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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version-file: '.node-version'
- name: Install dependencies
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
with:
runTests: false
- name: Cypress run
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
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'

View File

@@ -28,7 +28,6 @@ env:
) ||
github.event.before
}}
shouldRunParallel: ${{ secrets.CYPRESS_RECORD_KEY != '' && !(github.event_name == 'push' && github.ref == 'refs/heads/develop') }}
jobs:
cache:
runs-on: ubuntu-latest
@@ -39,7 +38,7 @@ jobs:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- name: Setup Node.js
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version-file: '.node-version'
- name: Cache snapshots
@@ -59,7 +58,7 @@ jobs:
- name: Install dependencies
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
uses: cypress-io/github-action@df7484c5ba85def7eef30db301afa688187bc378 # v6.7.2
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
with:
# just perform install
runTests: false
@@ -80,7 +79,7 @@ jobs:
strategy:
fail-fast: false
matrix:
containers: [1, 2, 3, 4]
containers: [1, 2, 3, 4, 5]
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
@@ -88,7 +87,7 @@ jobs:
# uses version from "packageManager" field in package.json
- name: Setup Node.js
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version-file: '.node-version'
@@ -101,7 +100,7 @@ jobs:
key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
- name: Install dependencies
uses: cypress-io/github-action@df7484c5ba85def7eef30db301afa688187bc378 # v6.7.2
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
with:
runTests: false
@@ -117,11 +116,8 @@ jobs:
# Install NPM dependencies, cache them correctly
# and run all Cypress tests
- name: Cypress run
uses: cypress-io/github-action@df7484c5ba85def7eef30db301afa688187bc378 # v6.7.2
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
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:
install: false
start: pnpm run dev:coverage
@@ -129,16 +125,18 @@ jobs:
browser: chrome
# Disable recording if we don't have an API key
# e.g. if this action was run from a fork
record: ${{ env.shouldRunParallel == 'true' }}
parallel: ${{ env.shouldRunParallel == 'true' }}
record: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
env:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
VITEST_COVERAGE: true
CYPRESS_COMMIT: ${{ github.sha }}
ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}
ARGOS_PARALLEL: ${{ env.shouldRunParallel == 'true' }}
ARGOS_PARALLEL_TOTAL: 4
ARGOS_PARALLEL: true
ARGOS_PARALLEL_TOTAL: ${{ strategy.job-total }}
ARGOS_PARALLEL_INDEX: ${{ matrix.containers }}
SPLIT: ${{ strategy.job-total }}
SPLIT_INDEX: ${{ strategy.job-index }}
SPLIT_FILE: 'cypress/timings.json'
- name: Upload Coverage to Codecov
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0

View File

@@ -29,7 +29,7 @@ jobs:
# uses version from "packageManager" field in package.json
- name: Setup Node.js
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
cache: pnpm
node-version-file: '.node-version'

View File

@@ -28,7 +28,7 @@ jobs:
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- name: Setup Node.js
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
cache: pnpm
node-version-file: '.node-version'

View File

@@ -16,7 +16,7 @@ jobs:
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- name: Setup Node.js
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
cache: pnpm
node-version-file: '.node-version'

View File

@@ -31,7 +31,7 @@ jobs:
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- name: Setup Node.js
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
cache: pnpm
node-version-file: '.node-version'

View File

@@ -26,7 +26,7 @@ jobs:
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- name: Setup Node.js
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
cache: pnpm
node-version-file: '.node-version'
@@ -36,7 +36,7 @@ jobs:
- name: Create Release Pull Request or Publish to npm
id: changesets
uses: changesets/action@aba318e9165b45b7948c60273e0b72fce0a64eb9 # v1.4.7
uses: changesets/action@3de3850952bec538fde60aac71731376e57b9b57 # v1.4.8
with:
version: pnpm changeset:version
publish: pnpm changeset:publish

View File

@@ -16,11 +16,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
persist-credentials: false
- name: Run analysis
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3
with:
results_file: results.sarif
results_format: sarif
@@ -32,6 +32,6 @@ jobs:
path: results.sarif
retention-days: 5
- name: Upload to code-scanning
uses: github/codeql-action/upload-sarif@f0f3afee809481da311ca3a6ff1ff51d81dbeb24 # v3.26.4
uses: github/codeql-action/upload-sarif@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
with:
sarif_file: results.sarif

View File

@@ -15,7 +15,7 @@ jobs:
# uses version from "packageManager" field in package.json
- name: Setup Node.js
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
cache: pnpm
node-version-file: '.node-version'

View File

@@ -1,8 +1,9 @@
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 { registerArgosTask } from '@argos-ci/cypress/task';
import coverage from '@cypress/code-coverage/task';
import { defineConfig } from 'cypress';
import { addMatchImageSnapshotPlugin } from 'cypress-image-snapshot/plugin';
import cypressSplit from 'cypress-split';
export default eyesPlugin(
defineConfig({
@@ -13,6 +14,7 @@ export default eyesPlugin(
specPattern: 'cypress/integration/**/*.{js,ts}',
setupNodeEvents(on, config) {
coverage(on, config);
cypressSplit(on, config);
on('before:browser:launch', (browser, launchOptions) => {
if (browser.name === 'chrome' && browser.isHeadless) {
launchOptions.args.push('--window-size=1440,1024', '--force-device-scale-factor=1');

View File

@@ -29,6 +29,7 @@ export const mermaidUrl = (
options: CypressMermaidConfig,
api: boolean
): string => {
options.handDrawnSeed = 1;
const codeObject: CodeObject = {
code: graphStr,
mermaid: options,

View File

@@ -173,7 +173,8 @@ describe.skip('architecture diagram', () => {
});
});
describe('architecture - external', () => {
// 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');
});

View File

@@ -581,4 +581,63 @@ class C13["With Città foreign language"]
{ 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);
});
});

View File

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

View File

@@ -124,3 +124,20 @@ describe('Test iconShape with different h', () => {
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);
});
});

File diff suppressed because one or more lines are too long

152
cypress/timings.json Normal file
View File

@@ -0,0 +1,152 @@
{
"durations": [
{
"spec": "cypress/integration/other/configuration.spec.js",
"duration": 4989
},
{
"spec": "cypress/integration/other/external-diagrams.spec.js",
"duration": 1382
},
{
"spec": "cypress/integration/other/ghsa.spec.js",
"duration": 3178
},
{
"spec": "cypress/integration/other/iife.spec.js",
"duration": 1372
},
{
"spec": "cypress/integration/other/interaction.spec.js",
"duration": 8998
},
{
"spec": "cypress/integration/other/rerender.spec.js",
"duration": 1249
},
{
"spec": "cypress/integration/other/xss.spec.js",
"duration": 25664
},
{
"spec": "cypress/integration/rendering/appli.spec.js",
"duration": 1928
},
{
"spec": "cypress/integration/rendering/architecture.spec.ts",
"duration": 2330
},
{
"spec": "cypress/integration/rendering/block.spec.js",
"duration": 11156
},
{
"spec": "cypress/integration/rendering/c4.spec.js",
"duration": 3418
},
{
"spec": "cypress/integration/rendering/classDiagram-v2.spec.js",
"duration": 14866
},
{
"spec": "cypress/integration/rendering/classDiagram.spec.js",
"duration": 9894
},
{
"spec": "cypress/integration/rendering/conf-and-directives.spec.js",
"duration": 5778
},
{
"spec": "cypress/integration/rendering/current.spec.js",
"duration": 1690
},
{
"spec": "cypress/integration/rendering/erDiagram.spec.js",
"duration": 9144
},
{
"spec": "cypress/integration/rendering/errorDiagram.spec.js",
"duration": 1951
},
{
"spec": "cypress/integration/rendering/flowchart-elk.spec.js",
"duration": 2196
},
{
"spec": "cypress/integration/rendering/flowchart-handDrawn.spec.js",
"duration": 21029
},
{
"spec": "cypress/integration/rendering/flowchart-shape-alias.spec.ts",
"duration": 16087
},
{
"spec": "cypress/integration/rendering/flowchart-v2.spec.js",
"duration": 27465
},
{
"spec": "cypress/integration/rendering/flowchart.spec.js",
"duration": 20035
},
{
"spec": "cypress/integration/rendering/gantt.spec.js",
"duration": 11366
},
{
"spec": "cypress/integration/rendering/gitGraph.spec.js",
"duration": 34025
},
{
"spec": "cypress/integration/rendering/iconShape.spec.ts",
"duration": 185902
},
{
"spec": "cypress/integration/rendering/imageShape.spec.ts",
"duration": 41631
},
{
"spec": "cypress/integration/rendering/info.spec.ts",
"duration": 1736
},
{
"spec": "cypress/integration/rendering/journey.spec.js",
"duration": 2247
},
{
"spec": "cypress/integration/rendering/katex.spec.js",
"duration": 2144
},
{
"spec": "cypress/integration/rendering/marker_unique_id.spec.js",
"duration": 1646
},
{
"spec": "cypress/integration/rendering/mindmap.spec.ts",
"duration": 6406
},
{
"spec": "cypress/integration/rendering/newShapes.spec.ts",
"duration": 107219
},
{
"spec": "cypress/integration/rendering/stateDiagram.spec.js",
"duration": 15834
},
{
"spec": "cypress/integration/rendering/theme.spec.js",
"duration": 33240
},
{
"spec": "cypress/integration/rendering/timeline.spec.ts",
"duration": 7122
},
{
"spec": "cypress/integration/rendering/xyChart.spec.js",
"duration": 11127
},
{
"spec": "cypress/integration/rendering/zenuml.spec.js",
"duration": 2391
}
]
}

View File

@@ -159,30 +159,87 @@
class People List~List~Person~~
</pre>
<hr />
<pre class="mermaid">
classDiagram
A1 --> B1
namespace A {
class A1 {
+foo : string
}
class A2 {
+bar : int
namespace Company.Project.Module {
class GenericClass~T~ {
+addItem(item: T)
+getItem() T
}
}
namespace B {
class B1 {
+foo : bool
}
class B2 {
+bar : float
}
}
A2 --> B2
</pre>
<hr />
<pre class="mermaid">
classDiagram
namespace Company.Project.Module.SubModule {
class Report {
+generatePDF(data: List)
+generateCSV(data: List)
}
}
namespace Company.Project.Module {
class Admin {
+generateReport()
}
}
Admin --> Report : generates
</pre>
<pre class="mermaid">
classDiagram
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
</pre>
<hr />
<pre class="mermaid">
classDiagram
namespace Shapes {
class Shape {
+calculateArea() double
}
class Circle {
+double radius
}
class Square {
+double side
}
}
Shape <|-- Circle
Shape <|-- Square
namespace Vehicles {
class Vehicle {
+String brand
}
class Car {
+int horsepower
}
class Bike {
+boolean hasGears
}
}
Vehicle <|-- Car
Vehicle <|-- Bike
Car --> Circle : "Logo Shape"
Bike --> Square : "Logo Shape"
</pre>
<script type="module">
import mermaid from './mermaid.esm.mjs';
mermaid.initialize({

View File

@@ -101,7 +101,7 @@ To add a new shape:
- **Example**:
```typescript
import { Node, RenderOptions } from '../../types.d.ts';
import { Node, RenderOptions } from '../../types.ts';
export const myNewShape = async (
parent: SVGAElement,
@@ -117,7 +117,7 @@ To add a new shape:
### 2. Register the Shape
- **Register the shape**: Add your shape to the `shapes` object in the main shapes module. This allows your shape to be recognized and used within the system.
- **Register the shape**: Add your shape to the `shapes` object in the [main shapes module](../rendering-util/rendering-elements/shapes.ts). This allows your shape to be recognized and used within the system.
- **Example**:
@@ -126,9 +126,14 @@ To add a new shape:
const shapes = {
...,
'my-new-shape': myNewShape,
// Shortened alias (if any).
'm-nsh': myNewShape
{
semanticName: 'My Shape',
name: 'Shape Name',
shortName: '<short-name>',
description: '<Description for the shape>',
aliases: ['<alias-one>', '<al-on>', '<alias-two>', '<al-two>'],
handler: myNewShape,
},
};
```

View File

@@ -127,7 +127,7 @@ Error.prepareStackTrace
#### Defined in
node_modules/.pnpm/@types+node\@20.16.2/node_modules/@types/node/globals.d.ts:28
node_modules/.pnpm/@types+node\@20.16.5/node_modules/@types/node/globals.d.ts:98
---
@@ -141,7 +141,7 @@ Error.stackTraceLimit
#### Defined in
node_modules/.pnpm/@types+node\@20.16.2/node_modules/@types/node/globals.d.ts:30
node_modules/.pnpm/@types+node\@20.16.5/node_modules/@types/node/globals.d.ts:100
## Methods
@@ -168,4 +168,4 @@ Error.captureStackTrace
#### Defined in
node_modules/.pnpm/@types+node\@20.16.2/node_modules/@types/node/globals.d.ts:21
node_modules/.pnpm/@types+node\@20.16.5/node_modules/@types/node/globals.d.ts:91

View File

@@ -20,7 +20,7 @@
#### Defined in
[packages/mermaid/src/rendering-util/types.ts:125](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L125)
[packages/mermaid/src/rendering-util/types.ts:126](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L126)
---
@@ -30,7 +30,7 @@
#### Defined in
[packages/mermaid/src/rendering-util/types.ts:124](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L124)
[packages/mermaid/src/rendering-util/types.ts:125](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L125)
---
@@ -40,4 +40,4 @@
#### Defined in
[packages/mermaid/src/rendering-util/types.ts:123](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L123)
[packages/mermaid/src/rendering-util/types.ts:124](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L124)

View File

@@ -28,7 +28,7 @@ page.
#### Defined in
[packages/mermaid/src/mermaid.ts:451](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L451)
[packages/mermaid/src/mermaid.ts:436](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L436)
---
@@ -59,7 +59,7 @@ A graph definition key
#### Defined in
[packages/mermaid/src/mermaid.ts:453](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L453)
[packages/mermaid/src/mermaid.ts:438](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L438)
---
@@ -89,7 +89,7 @@ Use [initialize](mermaid.Mermaid.md#initialize) and [run](mermaid.Mermaid.md#run
#### Defined in
[packages/mermaid/src/mermaid.ts:446](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L446)
[packages/mermaid/src/mermaid.ts:431](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L431)
---
@@ -116,13 +116,13 @@ This function should be called before the run function.
#### Defined in
[packages/mermaid/src/mermaid.ts:450](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L450)
[packages/mermaid/src/mermaid.ts:435](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L435)
---
### mermaidAPI
**mermaidAPI**: `Readonly`<{ `defaultConfig`: [`MermaidConfig`](mermaid.MermaidConfig.md) = configApi.defaultConfig; `getConfig`: () => [`MermaidConfig`](mermaid.MermaidConfig.md) = configApi.getConfig; `getDiagramFromText`: (`text`: `string`, `metadata`: `Pick`<`DiagramMetadata`, `"title"`>) => `Promise`<`Diagram`> ; `getSiteConfig`: () => [`MermaidConfig`](mermaid.MermaidConfig.md) = configApi.getSiteConfig; `globalReset`: () => `void` ; `initialize`: (`userOptions`: [`MermaidConfig`](mermaid.MermaidConfig.md)) => `void` ; `parse`: (`text`: `string`, `parseOptions`: [`ParseOptions`](mermaid.ParseOptions.md) & { `suppressErrors`: `true` }) => `Promise`<`ParseResult` | `false`>(`text`: `string`, `parseOptions?`: [`ParseOptions`](mermaid.ParseOptions.md)) => `Promise`<`ParseResult`> ; `render`: (`id`: `string`, `text`: `string`, `svgContainingElement?`: `Element`, `positions?`: `Positions`) => `Promise`<[`RenderResult`](mermaid.RenderResult.md)> ; `reset`: () => `void` ; `setConfig`: (`conf`: [`MermaidConfig`](mermaid.MermaidConfig.md)) => [`MermaidConfig`](mermaid.MermaidConfig.md) = configApi.setConfig; `updateSiteConfig`: (`conf`: [`MermaidConfig`](mermaid.MermaidConfig.md)) => [`MermaidConfig`](mermaid.MermaidConfig.md) = configApi.updateSiteConfig }>
**mermaidAPI**: `Readonly`<{ `defaultConfig`: [`MermaidConfig`](mermaid.MermaidConfig.md) = configApi.defaultConfig; `getConfig`: () => [`MermaidConfig`](mermaid.MermaidConfig.md) = configApi.getConfig; `getDiagramFromText`: (`text`: `string`, `metadata`: `Pick`<`DiagramMetadata`, `"title"`>) => `Promise`<`Diagram`> ; `getSiteConfig`: () => [`MermaidConfig`](mermaid.MermaidConfig.md) = configApi.getSiteConfig; `globalReset`: () => `void` ; `initialize`: (`userOptions`: [`MermaidConfig`](mermaid.MermaidConfig.md)) => `void` ; `parse`: (`text`: `string`, `parseOptions`: [`ParseOptions`](mermaid.ParseOptions.md) & { `suppressErrors`: `true` }) => `Promise`<[`ParseResult`](mermaid.ParseResult.md) & { `error?`: `unknown` }>(`text`: `string`, `parseOptions?`: [`ParseOptions`](mermaid.ParseOptions.md)) => `Promise`<[`ParseResult`](mermaid.ParseResult.md)> ; `render`: (`id`: `string`, `text`: `string`, `svgContainingElement?`: `Element`, `positions?`: `Positions`) => `Promise`<[`RenderResult`](mermaid.RenderResult.md)> ; `reset`: () => `void` ; `setConfig`: (`conf`: [`MermaidConfig`](mermaid.MermaidConfig.md)) => [`MermaidConfig`](mermaid.MermaidConfig.md) = configApi.setConfig; `updateSiteConfig`: (`conf`: [`MermaidConfig`](mermaid.MermaidConfig.md)) => [`MermaidConfig`](mermaid.MermaidConfig.md) = configApi.updateSiteConfig }>
**`Deprecated`**
@@ -130,32 +130,32 @@ Use [parse](mermaid.Mermaid.md#parse) and [render](mermaid.Mermaid.md#render) in
#### Defined in
[packages/mermaid/src/mermaid.ts:440](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L440)
[packages/mermaid/src/mermaid.ts:425](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L425)
---
### parse
**parse**: (`text`: `string`, `parseOptions?`: [`ParseOptions`](mermaid.ParseOptions.md)) => `Promise`<`boolean` | `void` | [`ParseResult`](mermaid.ParseResult.md)>
**parse**: (`text`: `string`, `parseOptions`: [`ParseOptions`](mermaid.ParseOptions.md) & { `suppressErrors`: `true` }) => `Promise`<[`ParseResult`](mermaid.ParseResult.md) & { `error?`: `unknown` }>(`text`: `string`, `parseOptions?`: [`ParseOptions`](mermaid.ParseOptions.md)) => `Promise`<[`ParseResult`](mermaid.ParseResult.md)>
#### Type declaration
▸ (`text`, `parseOptions?`): `Promise`<`boolean` | `void` | [`ParseResult`](mermaid.ParseResult.md)>
▸ (`text`, `parseOptions`): `Promise`<[`ParseResult`](mermaid.ParseResult.md) & { `error?`: `unknown` }>
Parse the text and validate the syntax.
##### Parameters
| Name | Type | Description |
| :-------------- | :---------------------------------------- | :------------------------------ |
| :------------- | :----------------------------------------------------------------------- | :------------------------------ |
| `text` | `string` | The mermaid diagram definition. |
| `parseOptions?` | [`ParseOptions`](mermaid.ParseOptions.md) | Options for parsing. |
| `parseOptions` | [`ParseOptions`](mermaid.ParseOptions.md) & { `suppressErrors`: `true` } | Options for parsing. |
##### Returns
`Promise`<`boolean` | `void` | [`ParseResult`](mermaid.ParseResult.md)>
`Promise`<[`ParseResult`](mermaid.ParseResult.md) & { `error?`: `unknown` }>
If valid, Diagram otherwise `false` if parseOptions.suppressErrors is `true`.
An object with the `diagramType` set to type of the diagram if valid. Otherwise `false` if parseOptions.suppressErrors is `true`.
**`See`**
@@ -165,22 +165,22 @@ If valid, Diagram otherwise `false` if parseOptions.suppressErrors is `true`.
Error if the diagram is invalid and parseOptions.suppressErrors is false or not set.
**`Example`**
▸ (`text`, `parseOptions?`): `Promise`<[`ParseResult`](mermaid.ParseResult.md)>
```js
console.log(await mermaid.parse('flowchart \n a --> b'));
// { diagramType: 'flowchart-v2' }
console.log(await mermaid.parse('wrong \n a --> b', { suppressErrors: true }));
// false
console.log(await mermaid.parse('wrong \n a --> b', { suppressErrors: false }));
// throws Error
console.log(await mermaid.parse('wrong \n a --> b'));
// throws Error
```
##### Parameters
| Name | Type |
| :-------------- | :---------------------------------------- |
| `text` | `string` |
| `parseOptions?` | [`ParseOptions`](mermaid.ParseOptions.md) |
##### Returns
`Promise`<[`ParseResult`](mermaid.ParseResult.md)>
#### Defined in
[packages/mermaid/src/mermaid.ts:441](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L441)
[packages/mermaid/src/mermaid.ts:426](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L426)
---
@@ -190,7 +190,7 @@ console.log(await mermaid.parse('wrong \n a --> b'));
#### Defined in
[packages/mermaid/src/mermaid.ts:435](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L435)
[packages/mermaid/src/mermaid.ts:420](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L420)
---
@@ -218,7 +218,7 @@ Used to register external diagram types.
#### Defined in
[packages/mermaid/src/mermaid.ts:449](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L449)
[packages/mermaid/src/mermaid.ts:434](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L434)
---
@@ -242,7 +242,7 @@ Used to register external diagram types.
#### Defined in
[packages/mermaid/src/mermaid.ts:454](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L454)
[packages/mermaid/src/mermaid.ts:439](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L439)
---
@@ -266,7 +266,7 @@ Used to register external diagram types.
#### Defined in
[packages/mermaid/src/mermaid.ts:448](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L448)
[packages/mermaid/src/mermaid.ts:433](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L433)
---
@@ -293,7 +293,7 @@ Used to register external diagram types.
#### Defined in
[packages/mermaid/src/mermaid.ts:442](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L442)
[packages/mermaid/src/mermaid.ts:427](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L427)
---
@@ -341,7 +341,7 @@ Renders the mermaid diagrams
#### Defined in
[packages/mermaid/src/mermaid.ts:447](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L447)
[packages/mermaid/src/mermaid.ts:432](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L432)
---
@@ -376,7 +376,7 @@ to it (eg. dart interop wrapper). (Initially there is no parseError member of me
#### Defined in
[packages/mermaid/src/mermaid.ts:452](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L452)
[packages/mermaid/src/mermaid.ts:437](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L437)
---
@@ -386,4 +386,4 @@ to it (eg. dart interop wrapper). (Initially there is no parseError member of me
#### Defined in
[packages/mermaid/src/mermaid.ts:434](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L434)
[packages/mermaid/src/mermaid.ts:419](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L419)

View File

@@ -19,4 +19,4 @@ The `parseError` function will not be called.
#### Defined in
[packages/mermaid/src/types.ts:56](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L56)
[packages/mermaid/src/types.ts:58](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L58)

View File

@@ -8,60 +8,68 @@
[mermaid](../modules/mermaid.md).ParseResult
## Hierarchy
- `Omit`<`ParseResult`, `"config"`>
**`ParseResult`**
## Properties
### code
**code**: `string`
The mermaid code after extracting the config.
#### Defined in
[packages/mermaid/src/types.ts:66](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L66)
---
### config
**config**: [`MermaidConfig`](mermaid.MermaidConfig.md)
#### Defined in
[packages/mermaid/src/mermaid.ts:328](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L328)
---
### defaultConfig
**defaultConfig**: [`MermaidConfig`](mermaid.MermaidConfig.md)
#### Overrides
Omit.defaultConfig
The config passed as YAML frontmatter or directives
#### Defined in
[packages/mermaid/src/types.ts:67](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L67)
[packages/mermaid/src/types.ts:70](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L70)
---
### diagram
**diagram**: `Diagram`
The diagram AST
#### Inherited from
Omit.diagram
`Optional` **diagram**: `Diagram`
#### Defined in
[packages/mermaid/src/types.ts:63](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L63)
[packages/mermaid/src/types.ts:72](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L72)
---
### userConfig
### error
**userConfig**: [`MermaidConfig`](mermaid.MermaidConfig.md)
`Optional` **error**: `unknown`
Config the user has defined in the text as frontmatter or directives
The error that occurred during parsing, if any.
#### Defined in
[packages/mermaid/src/mermaid.ts:326](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L326)
[packages/mermaid/src/types.ts:76](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L76)
---
### success
**success**: `boolean`
#### Defined in
[packages/mermaid/src/types.ts:62](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L62)
---
### title
`Optional` **title**: `string`
#### Defined in
[packages/mermaid/src/types.ts:71](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L71)

View File

@@ -39,7 +39,7 @@ bindFunctions?.(div); // To call bindFunctions only if it's present.
#### Defined in
[packages/mermaid/src/types.ts:90](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L90)
[packages/mermaid/src/types.ts:100](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L100)
---
@@ -51,7 +51,7 @@ The diagram type, e.g. 'flowchart', 'sequence', etc.
#### Defined in
[packages/mermaid/src/types.ts:80](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L80)
[packages/mermaid/src/types.ts:90](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L90)
---
@@ -63,4 +63,4 @@ The svg code for the rendered graph.
#### Defined in
[packages/mermaid/src/types.ts:76](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L76)
[packages/mermaid/src/types.ts:86](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L86)

View File

@@ -87,4 +87,4 @@
#### Defined in
[packages/mermaid/src/mermaid.ts:457](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L457)
[packages/mermaid/src/mermaid.ts:442](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L442)

View File

@@ -64,7 +64,7 @@ To add an integration to this list, see the [Integrations - create page](./integ
- [Mermaid Flow Visual Editor](https://www.mermaidflow.app) ✅
- [Mermerd](https://github.com/KarnerTh/mermerd)
- [Slab](https://slab.com) ✅
- [Swimm](https://docs.swimm.io/features/diagrams-and-charts/#mermaid--swimm--up-to-date-diagrams-) ✅
- [Swimm](https://docs.swimm.io/features/diagrams-and-charts) ✅
- [NotesHub](https://noteshub.app) ✅
- [Notion](https://notion.so) ✅
- [Observable](https://observablehq.com/@observablehq/mermaid) ✅

View File

@@ -12,7 +12,7 @@ Try the Ultimate AI, Mermaid, and Visual Diagramming Suite by creating an accoun
<br />
<a href="https://www.producthunt.com/products/mermaid-chart?utm_source=badge-follow&utm_medium=badge&utm_souce=badge-mermaid&#0045;chart" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/follow.svg?product_id=552855&theme=light" alt="Mermaid&#0032;Chart - A&#0032;smarter&#0032;way&#0032;to&#0032;create&#0032;diagrams | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
<a href="https://www.producthunt.com/posts/mermaid-whiteboard?embed=true&utm_source=badge-featured&utm_medium=badge&utm_souce=badge-mermaid&#0045;whiteboard" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=486720&theme=light" alt="Mermaid&#0032;Whiteboard - Drag&#0032;&#0038;&#0032;Drop&#0032;your&#0032;Nodes&#0032;with&#0032;Mermaid&#0039;s&#0032;new&#0032;Whiteboard&#0033; | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
## About
@@ -22,17 +22,20 @@ Try the Ultimate AI, Mermaid, and Visual Diagramming Suite by creating an accoun
- **Editor** - A web based editor for creating and editing Mermaid diagrams.
- **Visual Editor** - The Visual Editor enables users of all skill levels to create diagrams easily and efficiently, with both GUI and code-based editing options.
- **Mermaid AI** - Use our embedded AI Chat to generate diagrams from natural language descriptions.
- **AI Chat** - Use our embedded AI Chat to generate diagrams from natural language descriptions.
- **Whiteboard** - A virtual whiteboard for creating and editing Mermaid diagrams.
- **Plugins** - A plugin system for extending the functionality of Mermaid.
Official Mermaid Chart plugins:
- [Mermaid Chart GPT](https://chat.openai.com/g/g-1IRFKwq4G-mermaid-chart)
- [Confluence](https://marketplace.atlassian.com/apps/1234056/mermaid-chart-for-confluence?hosting=cloud&tab=overview)
- [Jira](https://marketplace.atlassian.com/apps/1234810/mermaid-chart-for-jira?tab=overview&hosting=cloud)
- [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=MermaidChart.vscode-mermaid-chart)
- [JetBrains IDE](https://plugins.jetbrains.com/plugin/23043-mermaid-chart)
- [Google Docs](https://gsuite.google.com/marketplace/app/mermaidchart/947683068472)
- [Microsoft PowerPoint and Word](https://appsource.microsoft.com/en-us/product/office/WA200006214?tab=Overview)
Visit our [Plugins](https://www.mermaidchart.com/plugins) page for more information.

View File

@@ -6,6 +6,12 @@
# Blog
## [Expanding the Horizons of Mermaid Flowcharts: Introducing 30 New Shapes!](https://www.mermaidchart.com/blog/posts/new-mermaid-flowchart-shapes/)
24 September 2024 · 5 mins
Discover 30 new shapes in Mermaid flowcharts, offering enhanced clarity, customization, and versatility for more dynamic and expressive visualizations.
## [Introducing Architecture Diagrams in Mermaid](https://www.mermaidchart.com/blog/posts/mermaid-supports-architecture-diagrams/)
2 September 2024 · 2 mins

View File

@@ -211,6 +211,27 @@ block-beta
This example demonstrates how Mermaid dynamically adjusts the width of the columns to accommodate the widest block, in this case, 'a' and the composite block 'e'. This dynamic adjustment is essential for creating visually balanced and easy-to-understand diagrams.
**Merging Blocks Horizontally:**
In scenarios where you need to stack blocks horizontally, you can use column width to accomplish the task. Blocks can be arranged vertically by putting them in a single column. Here is how you can create a block diagram in which 4 blocks are stacked on top of each other:
```mermaid-example
block-beta
block
columns 1
a["A label"] b c d
end
```
```mermaid
block-beta
block
columns 1
a["A label"] b c d
end
```
In this example, the width of the merged block dynamically adjusts to the width of the largest child block.
With these advanced configuration options, Mermaid's block diagrams can be tailored to represent a wide array of complex systems and structures. The flexibility offered by these features enables users to create diagrams that are both informative and visually appealing. In the following sections, we will explore further capabilities, including different block shapes and linking options.
## 4. Block Varieties and Shapes

View File

@@ -298,7 +298,7 @@ flowchart TD
id1(((This is the text in the circle)))
```
## Expanded Node Shapes in Mermaid Flowcharts
## Expanded Node Shapes in Mermaid Flowcharts (v11.3.0+)
Mermaid introduces 30 new shapes to enhance the flexibility and precision of flowchart creation. These new shapes provide more options to represent processes, decisions, events, data storage visually, and other elements within your flowcharts, improving clarity and semantic meaning.
@@ -317,52 +317,52 @@ This syntax creates a node A as a rectangle. It renders in the same way as `A["A
Below is a comprehensive list of the newly introduced shapes and their corresponding semantic meanings, short names, and aliases:
| **Semantic Name** | **Shape Name** | **Short Name** | **Description** | **Alias Supported** |
| ------------------------------------- | ---------------------- | -------------- | ------------------------------ | ----------------------------------------------------------- |
| **Process** | Rectangle | `rect` | Standard process shape | `proc`, `process`, `rectangle` |
| **Event** | Rounded Rectangle | `rounded` | Represents an event | `event` |
| **Terminal Point** | Stadium | `stadium` | Terminal point | `terminal`, `pill` |
| **Subprocess** | Framed Rectangle | `fr-rect` | Subprocess | `subprocess`,`subproc`, `framed-rectangle`, `subroutine` |
| **Database** | Cylinder | `cyl` | Database storage | `db`, `database`, `cylinder` |
| **Start** | Circle | `circle` | Starting point | `circ` |
| **Odd** | Odd | `odd` | Odd shape | |
| **Decision** | Diamond | `diam` | Decision-making step | `decision`, `diamond` |
| **Prepare Conditional** | Hexagon | `hex` | Preparation or condition step | `hexagon`, `prepare` |
| **Data Input/Output** | Lean Right | `lean-r` | Represents input or output | `lean-right`, `in-out` |
| **Data Input/Output** | Lean Left | `lean-l` | Represents output or input | `lean-left`, `out-in` |
| **Priority Action** | Trapezoid Base Bottom | `trap-b` | Priority action | `priority`, `trapezoid-bottom` |
| **Manual Operation** | Trapezoid Base Top | `trap-t` | Represents a manual task | `manual`, `trapezoid-top` |
| **Stop** | Double Circle | `dbl-circ` | Represents a stop point | `double-circle` |
| **Text Block** | Text Block | `text` | Text block | - |
| **Card** | Notched Rectangle | `notch-rect` | Represents a card | `card`, `notched-rectangle` |
| **Lined/Shaded Process** | Lined Rectangle | `lin-rect` | Lined process shape | `lined-rectangle`,`lined-proc`, `lin-proc`,`shaded-process` |
| **Start** | Small Circle | `sm-circ` | Small starting point | `start`, `small-circle` |
| **Stop** | Framed Circle | `fr-circ` | Stop point | `stop`, `framed-circle` |
| **Fork/Join** | Filled Rectangle | `fork` | Fork or join in process flow | `join` |
| **Collate** | Hourglass | `hourglass` | Represents a collate operation | `hourglass` |
| **Comment** | Curly Brace | `brace` | Adds a comment | `comment`, `brace-l` |
| **Comment Right** | Curly Brace | `brace-r` | Adds a comment | - |
| **Comment with braces on both sides** | Curly Braces | `braces` | Adds a comment | - |
| **Com Link** | Lightning Bolt | `bolt` | Communication link | `com-link`, `lightning-bolt` |
| **Document** | Document | `doc` | Represents a document | `doc`, `document` |
| **Delay** | Half-Rounded Rectangle | `delay` | Represents a delay | `half-rounded-rectangle` |
| **Direct Access Storage** | Horizontal Cylinder | `h-cyl` | Direct access storage | `das`, `horizontal-cylinder` |
| **Disk Storage** | Lined Cylinder | `lin-cyl` | Disk storage | `disk`, `lined-cylinder` |
| **Display** | Curved Trapezoid | `curv-trap` | Represents a display | `curved-trapezoid`, `display` |
| **Divided Process** | Divided Rectangle | `div-rect` | Divided process shape | `div-proc`, `divided-rectangle`, `divided-process` |
| **Extract** | Triangle | `tri` | Extraction process | `extract`, `triangle` |
| **Internal Storage** | Window Pane | `win-pane` | Internal storage | `internal-storage`, `window-pane` |
| **Junction** | Filled Circle | `f-circ` | Junction point | `junction`, `filled-circle` |
| **Lined Document** | Lined Document | `lin-doc` | Lined document | `lined-document` |
| **Loop Limit** | Trapezoidal Pentagon | `notch-pent` | Loop limit step | `loop-limit`, `notched-pentagon` |
| **Manual File** | Flipped Triangle | `flip-tri` | Manual file operation | `manual-file`, `flipped-triangle` |
| **Manual Input** | Sloped Rectangle | `sl-rect` | Manual input step | `manual-input`, `sloped-rectangle` |
| **Multi-Document** | Stacked Document | `docs` | Multiple documents | `documents`, `st-doc`, `stacked-document` |
| **Multi-Process** | Stacked Rectangle | `st-rect` | Multiple processes | `procs`, `processes`, `stacked-rect` |
| **Paper Tape** | Flag | `flag` | Paper tape | `paper-tape` |
| **Stored Data** | Bow Tie Rectangle | `bow-rect` | Stored data | `stored-data`, `bow-tie-rectangle` |
| **Summary** | Crossed Circle | `cross-circ` | Summary | `summary`, `crossed-circle` |
| **Tagged Document** | Tagged Document | `tag-doc` | Tagged document | `tag-doc`, `tagged-document` |
| **Tagged Process** | Tagged Rectangle | `tag-rect` | Tagged process | `tagged-rectangle`,`tag-proc`, `tagged-process` |
| --------------------------------- | ---------------------- | -------------- | ------------------------------ | ---------------------------------------------------------------- |
| Card | Notched Rectangle | `notch-rect` | Represents a card | `card`, `notched-rectangle` |
| Collate | Hourglass | `hourglass` | Represents a collate operation | `collate`, `hourglass` |
| Com Link | Lightning Bolt | `bolt` | Communication link | `com-link`, `lightning-bolt` |
| Comment | Curly Brace | `brace` | Adds a comment | `brace-l`, `comment` |
| Comment Right | Curly Brace | `brace-r` | Adds a comment | |
| Comment with braces on both sides | Curly Braces | `braces` | Adds a comment | |
| Data Input/Output | Lean Right | `lean-r` | Represents input or output | `in-out`, `lean-right` |
| Data Input/Output | Lean Left | `lean-l` | Represents output or input | `lean-left`, `out-in` |
| Database | Cylinder | `cyl` | Database storage | `cylinder`, `database`, `db` |
| Decision | Diamond | `diam` | Decision-making step | `decision`, `diamond`, `question` |
| Delay | Half-Rounded Rectangle | `delay` | Represents a delay | `half-rounded-rectangle` |
| Direct Access Storage | Horizontal Cylinder | `h-cyl` | Direct access storage | `das`, `horizontal-cylinder` |
| Disk Storage | Lined Cylinder | `lin-cyl` | Disk storage | `disk`, `lined-cylinder` |
| Display | Curved Trapezoid | `curv-trap` | Represents a display | `curved-trapezoid`, `display` |
| Divided Process | Divided Rectangle | `div-rect` | Divided process shape | `div-proc`, `divided-process`, `divided-rectangle` |
| Document | Document | `doc` | Represents a document | `doc`, `document` |
| Event | Rounded Rectangle | `rounded` | Represents an event | `event` |
| Extract | Triangle | `tri` | Extraction process | `extract`, `triangle` |
| Fork/Join | Filled Rectangle | `fork` | Fork or join in process flow | `join` |
| Internal Storage | Window Pane | `win-pane` | Internal storage | `internal-storage`, `window-pane` |
| Junction | Filled Circle | `f-circ` | Junction point | `filled-circle`, `junction` |
| Lined Document | Lined Document | `lin-doc` | Lined document | `lined-document` |
| Lined/Shaded Process | Lined Rectangle | `lin-rect` | Lined process shape | `lin-proc`, `lined-process`, `lined-rectangle`, `shaded-process` |
| Loop Limit | Trapezoidal Pentagon | `notch-pent` | Loop limit step | `loop-limit`, `notched-pentagon` |
| Manual File | Flipped Triangle | `flip-tri` | Manual file operation | `flipped-triangle`, `manual-file` |
| Manual Input | Sloped Rectangle | `sl-rect` | Manual input step | `manual-input`, `sloped-rectangle` |
| Manual Operation | Trapezoid Base Top | `trap-t` | Represents a manual task | `inv-trapezoid`, `manual`, `trapezoid-top` |
| Multi-Document | Stacked Document | `docs` | Multiple documents | `documents`, `st-doc`, `stacked-document` |
| Multi-Process | Stacked Rectangle | `st-rect` | Multiple processes | `processes`, `procs`, `stacked-rectangle` |
| Odd | Odd | `odd` | Odd shape | |
| Paper Tape | Flag | `flag` | Paper tape | `paper-tape` |
| Prepare Conditional | Hexagon | `hex` | Preparation or condition step | `hexagon`, `prepare` |
| Priority Action | Trapezoid Base Bottom | `trap-b` | Priority action | `priority`, `trapezoid`, `trapezoid-bottom` |
| Process | Rectangle | `rect` | Standard process shape | `proc`, `process`, `rectangle` |
| Start | Circle | `circle` | Starting point | `circ` |
| Start | Small Circle | `sm-circ` | Small starting point | `small-circle`, `start` |
| Stop | Double Circle | `dbl-circ` | Represents a stop point | `double-circle` |
| Stop | Framed Circle | `fr-circ` | Stop point | `framed-circle`, `stop` |
| Stored Data | Bow Tie Rectangle | `bow-rect` | Stored data | `bow-tie-rectangle`, `stored-data` |
| Subprocess | Framed Rectangle | `fr-rect` | Subprocess | `framed-rectangle`, `subproc`, `subprocess`, `subroutine` |
| Summary | Crossed Circle | `cross-circ` | Summary | `crossed-circle`, `summary` |
| Tagged Document | Tagged Document | `tag-doc` | Tagged document | `tag-doc`, `tagged-document` |
| Tagged Process | Tagged Rectangle | `tag-rect` | Tagged process | `tag-proc`, `tagged-process`, `tagged-rectangle` |
| Terminal Point | Stadium | `stadium` | Terminal point | `pill`, `terminal` |
| Text Block | Text Block | `text` | Text block | |
### Example Flowchart with New Shapes
@@ -426,12 +426,12 @@ flowchart TD
```mermaid-example
flowchart TD
A@{ shape: fr, label: "This is a subprocess" }
A@{ shape: subproc, label: "This is a subprocess" }
```
```mermaid
flowchart TD
A@{ shape: fr, label: "This is a subprocess" }
A@{ shape: subproc, label: "This is a subprocess" }
```
### Database (Cylinder)

View File

@@ -155,6 +155,9 @@ end
box rgb(33,66,99)
... actors ...
end
box rgba(33,66,99,0.5)
... actors ...
end
```
> **Note**
@@ -580,6 +583,12 @@ sequenceDiagram
It is possible to highlight flows by providing colored background rects. This is done by the notation
```
rect COLOR
... content ...
end
```
The colors are defined using rgb and rgba syntax.
```

View File

@@ -64,7 +64,7 @@
},
"devDependencies": {
"@applitools/eyes-cypress": "^3.44.4",
"@argos-ci/cypress": "^2.1.0",
"@argos-ci/cypress": "^2.2.2",
"@changesets/changelog-github": "^0.5.0",
"@changesets/cli": "^2.27.7",
"@cspell/eslint-plugin": "^8.8.4",
@@ -91,6 +91,7 @@
"cspell": "^8.6.0",
"cypress": "^13.14.1",
"cypress-image-snapshot": "^4.0.1",
"cypress-split": "^1.24.0",
"esbuild": "^0.21.5",
"eslint": "^9.4.0",
"eslint-config-prettier": "^9.1.0",
@@ -103,7 +104,7 @@
"eslint-plugin-markdown": "^5.0.0",
"eslint-plugin-no-only-tests": "^3.1.0",
"eslint-plugin-tsdoc": "^0.3.0",
"eslint-plugin-unicorn": "^55.0.0",
"eslint-plugin-unicorn": "^56.0.0",
"express": "^4.19.1",
"globals": "^15.4.0",
"globby": "^14.0.1",
@@ -131,5 +132,10 @@
},
"nyc": {
"report-dir": "coverage/cypress"
},
"pnpm": {
"patchedDependencies": {
"roughjs": "patches/roughjs.patch"
}
}
}

View File

@@ -1,5 +1,14 @@
# @mermaid-js/layout-elk
## 0.1.5
### Patch Changes
- [#5825](https://github.com/mermaid-js/mermaid/pull/5825) [`233e36c`](https://github.com/mermaid-js/mermaid/commit/233e36c9884fcce141a72ce7c845179781e18632) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - chore: Update render options
- Updated dependencies [[`6c5b7ce`](https://github.com/mermaid-js/mermaid/commit/6c5b7ce9f41c0fbd59fe03dbefc8418d97697f0a), [`9e3aa70`](https://github.com/mermaid-js/mermaid/commit/9e3aa705ae21fd4898504ab22d775a9e437b898e), [`de2c05c`](https://github.com/mermaid-js/mermaid/commit/de2c05cd5463af68d19dd7b6b3f1303d69ddb2dd)]:
- mermaid@11.3.0
## 0.1.4
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@mermaid-chart/layout-elk",
"version": "0.1.4-b.2",
"version": "0.1.5-b.1",
"description": "ELK layout engine for mermaid",
"module": "dist/mermaid-layout-elk.core.mjs",
"types": "dist/layouts.d.ts",

View File

@@ -1,5 +1,35 @@
# mermaid
## 11.3.0
### Minor Changes
- [#5825](https://github.com/mermaid-js/mermaid/pull/5825) [`9e3aa70`](https://github.com/mermaid-js/mermaid/commit/9e3aa705ae21fd4898504ab22d775a9e437b898e) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - New Flowchart Shapes (with new syntax)
### Patch Changes
- [#5849](https://github.com/mermaid-js/mermaid/pull/5849) [`6c5b7ce`](https://github.com/mermaid-js/mermaid/commit/6c5b7ce9f41c0fbd59fe03dbefc8418d97697f0a) Thanks [@ReneLombard](https://github.com/ReneLombard)! - Fixed an issue when the mermaid classdiagram crashes when adding a . to the namespace.
Forexample
```mermaid
classDiagram
namespace Company.Project.Module {
class GenericClass~T~ {
+addItem(item: T)
+getItem() T
}
}
```
- [#5914](https://github.com/mermaid-js/mermaid/pull/5914) [`de2c05c`](https://github.com/mermaid-js/mermaid/commit/de2c05cd5463af68d19dd7b6b3f1303d69ddb2dd) Thanks [@aloisklink](https://github.com/aloisklink)! - Ban DOMPurify v3.1.7 as a dependency
## 11.2.1
### Patch Changes
- [#5856](https://github.com/mermaid-js/mermaid/pull/5856) [`bfd8c63`](https://github.com/mermaid-js/mermaid/commit/bfd8c63daaa8420e57da9953922b9f0c94123064) Thanks [@knsv](https://github.com/knsv)! - Fix for issue with calculation of label width when using in firefox
## 11.2.0
### Minor Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@mermaid-chart/mermaid",
"version": "11.2.0-b.16",
"version": "11.3.0-b.1",
"description": "Markdown-ish syntax for generating flowcharts, mindmaps, sequence diagrams, class diagrams, gantt charts, git graphs and more.",
"type": "module",
"module": "./dist/mermaid.core.mjs",
@@ -35,8 +35,8 @@
"clean": "rimraf dist",
"dev": "pnpm -w dev",
"docs:code": "typedoc src/defaultConfig.ts src/config.ts src/mermaid.ts && prettier --write ./src/docs/config/setup",
"docs:build": "rimraf ../../docs && pnpm docs:spellcheck && pnpm docs:code && tsx scripts/docs.cli.mts",
"docs:verify": "pnpm docs:spellcheck && pnpm docs:code && tsx scripts/docs.cli.mts --verify",
"docs:build": "rimraf ../../docs && pnpm docs:code && pnpm docs:spellcheck && tsx scripts/docs.cli.mts",
"docs:verify": "pnpm docs:code && pnpm docs:spellcheck && tsx scripts/docs.cli.mts --verify",
"docs:pre:vitepress": "pnpm --filter ./src/docs prefetch && rimraf src/vitepress && pnpm docs:code && tsx scripts/docs.cli.mts --vitepress && pnpm --filter ./src/vitepress install --no-frozen-lockfile --ignore-scripts",
"docs:build:vitepress": "pnpm docs:pre:vitepress && (cd src/vitepress && pnpm run build) && cpy --flat src/docs/landing/ ./src/vitepress/.vitepress/dist/landing",
"docs:dev": "pnpm docs:pre:vitepress && concurrently \"pnpm --filter ./src/vitepress dev\" \"tsx scripts/docs.cli.mts --watch --vitepress\"",
@@ -70,12 +70,14 @@
"@braintree/sanitize-url": "^7.0.1",
"@iconify/utils": "^2.1.32",
"@mermaid-js/parser": "^0.3.1-rc.1",
"@types/d3": "^7.4.3",
"@types/dompurify": "^3.0.5",
"cytoscape": "^3.29.2",
"cytoscape-cose-bilkent": "^4.1.0",
"cytoscape-fcose": "^2.2.0",
"d3": "^7.9.0",
"d3-sankey": "^0.12.3",
"dagre-d3-es": "7.0.10",
"dagre-d3-es": "7.0.11",
"dayjs": "^1.11.10",
"dompurify": "^3.0.11 <3.1.7",
"katex": "^0.16.9",
@@ -92,13 +94,11 @@
"@iconify/types": "^2.0.0",
"@types/cytoscape": "^3.21.4",
"@types/cytoscape-fcose": "^2.2.4",
"@types/d3": "^7.4.3",
"@types/d3-sankey": "^0.12.4",
"@types/d3-scale": "^4.0.8",
"@types/d3-scale-chromatic": "^3.0.3",
"@types/d3-selection": "^3.0.10",
"@types/d3-shape": "^3.1.6",
"@types/dompurify": "^3.0.5",
"@types/jsdom": "^21.1.6",
"@types/katex": "^0.16.7",
"@types/lodash-es": "^4.17.12",

View File

@@ -41,7 +41,8 @@ import { exec } from 'child_process';
import { globby } from 'globby';
import { JSDOM } from 'jsdom';
import { dump, load, JSON_SCHEMA } from 'js-yaml';
import type { Code, ListItem, Root, Text, YAML } from 'mdast';
import type { Code, ListItem, PhrasingContent, Root, Text, YAML } from 'mdast';
import { register } from 'node:module';
import { posix, dirname, relative, join } from 'path';
import prettier from 'prettier';
import { remark } from 'remark';
@@ -53,6 +54,10 @@ import mm from 'micromatch';
import flatmap from 'unist-util-flatmap';
import { visit } from 'unist-util-visit';
// short-circuit `.schema.yaml` imports, so that we can safely import `shapes.js`
register('./loadHook.mjs', import.meta.url);
const { shapesDefs } = await import('../src/rendering-util/rendering-elements/shapes.js');
export const MERMAID_RELEASE_VERSION = JSON.parse(readFileSync('../mermaid/package.json', 'utf8'))
.version as string;
const MERMAID_MAJOR_VERSION = MERMAID_RELEASE_VERSION.split('.')[0];
@@ -103,6 +108,60 @@ const generateHeader = (file: string): string => {
> ## Please edit the corresponding file in [${filePathFromRoot}](${sourcePathRelativeToGenerated}).`;
};
/**
* Builds a markdown list of shapes supported in flowcharts.
*/
export function buildShapeDoc() {
const data = shapesDefs
.sort((a, b) => a.semanticName.localeCompare(b.semanticName))
.map((shape): PhrasingContent[][] => {
const { name, semanticName, description, shortName, aliases = [] } = shape;
return [
[{ type: 'text', value: semanticName }],
[{ type: 'text', value: name }],
[{ type: 'inlineCode', value: shortName }],
[{ type: 'text', value: description }],
aliases.sort().flatMap((alias, index) => [
...(index !== 0 ? ([{ type: 'text', value: ', ' }] as const) : []),
{
type: 'inlineCode',
value: alias,
},
]),
];
});
// don't prettify this table, since we'd do it later
return remark()
.use(remarkGfm)
.stringify({
type: 'root',
children: [
{
type: 'table',
children: [
['Semantic Name', 'Shape Name', 'Short Name', 'Description', 'Alias Supported'].map(
(s): PhrasingContent[] => [
{
type: 'strong',
children: [{ type: 'text', value: s }],
},
]
),
...data,
].map((row) => ({
type: 'tableRow',
children: row.map((cell) => ({
type: 'tableCell',
children: cell,
})),
})),
},
],
})
.toString();
}
/**
* Given a source file name and path, return the documentation destination full path and file name
* Create the destination path if it does not already exist.
@@ -192,10 +251,22 @@ export const transformToBlockQuote = (
const injectPlaceholders = (text: string): string =>
text.replace(/<MERMAID_VERSION>/g, MERMAID_MAJOR_VERSION).replace(/<CDN_URL>/g, CDN_URL);
const virtualGenerators: Record<string, () => string> = {
shapesTable: buildShapeDoc,
};
const transformIncludeStatements = (file: string, text: string): string => {
// resolve includes - src https://github.com/vuejs/vitepress/blob/428eec3750d6b5648a77ac52d88128df0554d4d1/src/node/markdownToVue.ts#L65-L76
return text.replace(includesRE, (m, m1) => {
return text.replace(includesRE, (m, m1: string) => {
try {
if (m1.startsWith('virtual:')) {
const key = m1.replace('virtual:', '');
const generator = virtualGenerators[key];
if (!generator) {
throw new Error(`Unknown virtual generator: ${key} in "${file}"`);
}
return generator();
}
const includePath = join(dirname(file), m1).replaceAll('\\', '/');
const content = readSyncedUTF8file(includePath);
includedFiles.add(changeToFinalDocDir(includePath));

View File

@@ -1,4 +1,4 @@
import { transformMarkdownAst, transformToBlockQuote } from './docs.mjs';
import { buildShapeDoc, transformMarkdownAst, transformToBlockQuote } from './docs.mjs';
import { remark } from 'remark'; // import it this way so we can mock it
import remarkFrontmatter from 'remark-frontmatter';
@@ -165,4 +165,59 @@ This Markdown should be kept.
});
});
});
describe('buildShapeDoc', () => {
it('should build shapesTable based on the shapeDefs', () => {
expect(buildShapeDoc()).toMatchInlineSnapshot(`
"| **Semantic Name** | **Shape Name** | **Short Name** | **Description** | **Alias Supported** |
| --------------------------------- | ---------------------- | -------------- | ------------------------------ | ---------------------------------------------------------------- |
| Card | Notched Rectangle | \`notch-rect\` | Represents a card | \`card\`, \`notched-rectangle\` |
| Collate | Hourglass | \`hourglass\` | Represents a collate operation | \`collate\`, \`hourglass\` |
| Com Link | Lightning Bolt | \`bolt\` | Communication link | \`com-link\`, \`lightning-bolt\` |
| Comment | Curly Brace | \`brace\` | Adds a comment | \`brace-l\`, \`comment\` |
| Comment Right | Curly Brace | \`brace-r\` | Adds a comment | |
| Comment with braces on both sides | Curly Braces | \`braces\` | Adds a comment | |
| Data Input/Output | Lean Right | \`lean-r\` | Represents input or output | \`in-out\`, \`lean-right\` |
| Data Input/Output | Lean Left | \`lean-l\` | Represents output or input | \`lean-left\`, \`out-in\` |
| Database | Cylinder | \`cyl\` | Database storage | \`cylinder\`, \`database\`, \`db\` |
| Decision | Diamond | \`diam\` | Decision-making step | \`decision\`, \`diamond\`, \`question\` |
| Delay | Half-Rounded Rectangle | \`delay\` | Represents a delay | \`half-rounded-rectangle\` |
| Direct Access Storage | Horizontal Cylinder | \`h-cyl\` | Direct access storage | \`das\`, \`horizontal-cylinder\` |
| Disk Storage | Lined Cylinder | \`lin-cyl\` | Disk storage | \`disk\`, \`lined-cylinder\` |
| Display | Curved Trapezoid | \`curv-trap\` | Represents a display | \`curved-trapezoid\`, \`display\` |
| Divided Process | Divided Rectangle | \`div-rect\` | Divided process shape | \`div-proc\`, \`divided-process\`, \`divided-rectangle\` |
| Document | Document | \`doc\` | Represents a document | \`doc\`, \`document\` |
| Event | Rounded Rectangle | \`rounded\` | Represents an event | \`event\` |
| Extract | Triangle | \`tri\` | Extraction process | \`extract\`, \`triangle\` |
| Fork/Join | Filled Rectangle | \`fork\` | Fork or join in process flow | \`join\` |
| Internal Storage | Window Pane | \`win-pane\` | Internal storage | \`internal-storage\`, \`window-pane\` |
| Junction | Filled Circle | \`f-circ\` | Junction point | \`filled-circle\`, \`junction\` |
| Lined Document | Lined Document | \`lin-doc\` | Lined document | \`lined-document\` |
| Lined/Shaded Process | Lined Rectangle | \`lin-rect\` | Lined process shape | \`lin-proc\`, \`lined-process\`, \`lined-rectangle\`, \`shaded-process\` |
| Loop Limit | Trapezoidal Pentagon | \`notch-pent\` | Loop limit step | \`loop-limit\`, \`notched-pentagon\` |
| Manual File | Flipped Triangle | \`flip-tri\` | Manual file operation | \`flipped-triangle\`, \`manual-file\` |
| Manual Input | Sloped Rectangle | \`sl-rect\` | Manual input step | \`manual-input\`, \`sloped-rectangle\` |
| Manual Operation | Trapezoid Base Top | \`trap-t\` | Represents a manual task | \`inv-trapezoid\`, \`manual\`, \`trapezoid-top\` |
| Multi-Document | Stacked Document | \`docs\` | Multiple documents | \`documents\`, \`st-doc\`, \`stacked-document\` |
| Multi-Process | Stacked Rectangle | \`st-rect\` | Multiple processes | \`processes\`, \`procs\`, \`stacked-rectangle\` |
| Odd | Odd | \`odd\` | Odd shape | |
| Paper Tape | Flag | \`flag\` | Paper tape | \`paper-tape\` |
| Prepare Conditional | Hexagon | \`hex\` | Preparation or condition step | \`hexagon\`, \`prepare\` |
| Priority Action | Trapezoid Base Bottom | \`trap-b\` | Priority action | \`priority\`, \`trapezoid\`, \`trapezoid-bottom\` |
| Process | Rectangle | \`rect\` | Standard process shape | \`proc\`, \`process\`, \`rectangle\` |
| Start | Circle | \`circle\` | Starting point | \`circ\` |
| Start | Small Circle | \`sm-circ\` | Small starting point | \`small-circle\`, \`start\` |
| Stop | Double Circle | \`dbl-circ\` | Represents a stop point | \`double-circle\` |
| Stop | Framed Circle | \`fr-circ\` | Stop point | \`framed-circle\`, \`stop\` |
| Stored Data | Bow Tie Rectangle | \`bow-rect\` | Stored data | \`bow-tie-rectangle\`, \`stored-data\` |
| Subprocess | Framed Rectangle | \`fr-rect\` | Subprocess | \`framed-rectangle\`, \`subproc\`, \`subprocess\`, \`subroutine\` |
| Summary | Crossed Circle | \`cross-circ\` | Summary | \`crossed-circle\`, \`summary\` |
| Tagged Document | Tagged Document | \`tag-doc\` | Tagged document | \`tag-doc\`, \`tagged-document\` |
| Tagged Process | Tagged Rectangle | \`tag-rect\` | Tagged process | \`tag-proc\`, \`tagged-process\`, \`tagged-rectangle\` |
| Terminal Point | Stadium | \`stadium\` | Terminal point | \`pill\`, \`terminal\` |
| Text Block | Text Block | \`text\` | Text block | |
"
`);
});
});
});

View File

@@ -0,0 +1,22 @@
import { fileURLToPath } from 'node:url';
/** @import import { LoadHook } from "node:module"; */
/**
* @type {LoadHook}
*
* Load hook that short circuits the loading of `.schema.yaml` files with `export default {}`.
* These would normally be loaded using ESBuild, but that doesn't work for these local scripts.
*
* @see https://nodejs.org/api/module.html#loadurl-context-nextload
*/
export const load = async (url, context, nextLoad) => {
const filePath = url.startsWith('file://') ? fileURLToPath(url) : url;
if (filePath.endsWith('.schema.yaml')) {
return {
format: 'module',
shortCircuit: true,
source: `export default {}`,
};
} else {
return await nextLoad(url, context);
}
};

View File

@@ -14,6 +14,78 @@ describe('given a basic class diagram, ', function () {
classDb.clear();
parser.yy = classDb;
});
it('should handle classes within namespaces', () => {
const str = `classDiagram
namespace Company.Project {
class User {
+login(username: String, password: String)
+logout()
}
}
namespace Company.Project.Module {
class Admin {
+addUser(user: User)
+removeUser(user: User)
}
}`;
parser.parse(str);
const user = classDb.getClass('User');
const admin = classDb.getClass('Admin');
// Check if the classes are correctly registered under their respective namespaces
expect(user.parent).toBe('Company.Project');
expect(admin.parent).toBe('Company.Project.Module');
expect(user.methods.length).toBe(2);
expect(admin.methods.length).toBe(2);
});
it('should handle generic classes within namespaces', () => {
const str = `classDiagram
namespace Company.Project.Module {
class GenericClass~T~ {
+addItem(item: T)
+getItem() T
}
}`;
parser.parse(str);
const genericClass = classDb.getClass('GenericClass');
expect(genericClass.type).toBe('T');
expect(genericClass.methods[0].getDisplayDetails().displayText).toBe('+addItem(item: T)');
expect(genericClass.methods[1].getDisplayDetails().displayText).toBe('+getItem() : T');
});
it('should handle nested namespaces and relationships', () => {
const str = ` classDiagram
namespace Company.Project.Module.SubModule {
class Report {
+generatePDF(data: List)
+generateCSV(data: List)
}
}
namespace Company.Project.Module {
class Admin {
+generateReport()
}
}
Admin --> Report : generates`;
parser.parse(str);
const report = classDb.getClass('Report');
const admin = classDb.getClass('Admin');
const relations = classDb.getRelations();
expect(report.parent).toBe('Company.Project.Module.SubModule');
expect(admin.parent).toBe('Company.Project.Module');
expect(relations[0].id1).toBe('Admin');
expect(relations[0].id2).toBe('Report');
expect(relations[0].title).toBe('generates');
});
it('should handle accTitle and accDescr', function () {
const str = `classDiagram
accTitle: My Title
@@ -48,6 +120,22 @@ describe('given a basic class diagram, ', function () {
}
});
it('should handle fully qualified class names in relationships', () => {
const str = `classDiagram
namespace Company.Project.Module {
class User
class Admin
}
Admin --> User : manages`;
parser.parse(str);
const relations = classDb.getRelations();
expect(relations[0].id1).toBe('Admin');
expect(relations[0].id2).toBe('User');
expect(relations[0].title).toBe('manages');
});
it('should handle backquoted class names', function () {
const str = 'classDiagram\n' + 'class `Car`';
@@ -393,27 +481,23 @@ class C13["With Città foreign language"]
Student "1" --o "1" IdCard : carries
Student "1" --o "1" Bike : rides`);
expect(classDb.getClasses().size).toBe(3);
expect(classDb.getClasses().get('Student')).toMatchInlineSnapshot(`
{
"annotations": [],
"cssClasses": [],
"domId": "classId-Student-134",
"id": "Student",
"label": "Student",
"members": [
ClassMember {
"classifier": "",
"id": "idCard : IdCard",
"memberType": "attribute",
"visibility": "-",
},
const studentClass = classDb.getClasses().get('Student');
// Check that the important properties match, but ignore the domId
expect(studentClass).toMatchObject({
id: 'Student',
label: 'Student',
members: [
expect.objectContaining({
id: 'idCard : IdCard',
visibility: '-',
}),
],
"methods": [],
"styles": [],
"type": "",
}
`);
methods: [],
annotations: [],
cssClasses: [],
});
expect(classDb.getClasses().size).toBe(3);
expect(classDb.getRelations().length).toBe(2);
expect(classDb.getRelations()).toMatchInlineSnapshot(`
[

View File

@@ -241,11 +241,13 @@ classLabel
namespaceName
: alphaNumToken { $$=$1; }
| alphaNumToken DOT namespaceName { $$=$1+'.'+$3; }
| alphaNumToken namespaceName { $$=$1+$2; }
;
className
: alphaNumToken { $$=$1; }
| alphaNumToken DOT className { $$=$1+'.'+$3; }
| classLiteralName { $$=$1; }
| alphaNumToken className { $$=$1+$2; }
| alphaNumToken GENERICTYPE { $$=$1+'~'+$2+'~'; }
@@ -270,12 +272,12 @@ statement
;
namespaceStatement
: namespaceIdentifier STRUCT_START classStatements STRUCT_STOP {yy.addClassesToNamespace($1, $3);}
| namespaceIdentifier STRUCT_START NEWLINE classStatements STRUCT_STOP {yy.addClassesToNamespace($1, $4);}
: namespaceIdentifier STRUCT_START classStatements STRUCT_STOP { yy.addClassesToNamespace($1, $3); }
| namespaceIdentifier STRUCT_START NEWLINE classStatements STRUCT_STOP { yy.addClassesToNamespace($1, $4); }
;
namespaceIdentifier
: NAMESPACE namespaceName {$$=$2; yy.addNamespace($2);}
: NAMESPACE namespaceName { $$=$2; yy.addNamespace($2); }
;
classStatements

View File

@@ -1,11 +1,11 @@
<template>
<div class="-mt-6 mb-8">
<a
href="https://www.producthunt.com/products/mermaid-chart?utm_source=badge-follow&utm_medium=badge&utm_souce=badge-mermaid&#0045;chart"
href="https://www.producthunt.com/posts/mermaid-whiteboard?embed=true&utm_source=badge-featured&utm_medium=badge&utm_souce=badge-mermaid&#0045;whiteboard"
target="_blank"
><img
src="https://api.producthunt.com/widgets/embed-image/v1/follow.svg?product_id=552855&theme=light"
alt="Mermaid&#0032;Chart - A&#0032;smarter&#0032;way&#0032;to&#0032;create&#0032;diagrams | Product Hunt"
src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=486720&theme=light"
alt="Mermaid&#0032;Whiteboard - Drag&#0032;&#0038;&#0032;Drop&#0032;your&#0032;Nodes&#0032;with&#0032;Mermaid&#0039;s&#0032;new&#0032;Whiteboard&#0033; | Product Hunt"
style="width: 250px; height: 54px"
width="250"
height="54"

View File

@@ -95,7 +95,7 @@ To add a new shape:
- **Example**:
```typescript
import { Node, RenderOptions } from '../../types.d.ts';
import { Node, RenderOptions } from '../../types.ts';
export const myNewShape = async (
parent: SVGAElement,
@@ -111,7 +111,7 @@ To add a new shape:
### 2. Register the Shape
- **Register the shape**: Add your shape to the `shapes` object in the main shapes module. This allows your shape to be recognized and used within the system.
- **Register the shape**: Add your shape to the `shapes` object in the [main shapes module](../rendering-util/rendering-elements/shapes.ts). This allows your shape to be recognized and used within the system.
- **Example**:
@@ -120,9 +120,14 @@ To add a new shape:
const shapes = {
...,
'my-new-shape': myNewShape,
// Shortened alias (if any).
'm-nsh': myNewShape
{
semanticName: 'My Shape',
name: 'Shape Name',
shortName: '<short-name>',
description: '<Description for the shape>',
aliases: ['<alias-one>', '<al-on>', '<alias-two>', '<al-two>'],
handler: myNewShape,
},
};
```

View File

@@ -59,7 +59,7 @@ To add an integration to this list, see the [Integrations - create page](./integ
- [Mermaid Flow Visual Editor](https://www.mermaidflow.app) ✅
- [Mermerd](https://github.com/KarnerTh/mermerd)
- [Slab](https://slab.com) ✅
- [Swimm](https://docs.swimm.io/features/diagrams-and-charts/#mermaid--swimm--up-to-date-diagrams-) ✅
- [Swimm](https://docs.swimm.io/features/diagrams-and-charts) ✅
- [NotesHub](https://noteshub.app) ✅
- [Notion](https://notion.so) ✅
- [Observable](https://observablehq.com/@observablehq/mermaid) ✅

View File

@@ -6,7 +6,7 @@ Try the Ultimate AI, Mermaid, and Visual Diagramming Suite by creating an accoun
<br />
<a href="https://www.producthunt.com/products/mermaid-chart?utm_source=badge-follow&utm_medium=badge&utm_souce=badge-mermaid&#0045;chart" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/follow.svg?product_id=552855&theme=light" alt="Mermaid&#0032;Chart - A&#0032;smarter&#0032;way&#0032;to&#0032;create&#0032;diagrams | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
<a href="https://www.producthunt.com/posts/mermaid-whiteboard?embed=true&utm_source=badge-featured&utm_medium=badge&utm_souce=badge-mermaid&#0045;whiteboard" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=486720&theme=light" alt="Mermaid&#0032;Whiteboard - Drag&#0032;&#0038;&#0032;Drop&#0032;your&#0032;Nodes&#0032;with&#0032;Mermaid&#0039;s&#0032;new&#0032;Whiteboard&#0033; | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
## About
@@ -16,17 +16,20 @@ Try the Ultimate AI, Mermaid, and Visual Diagramming Suite by creating an accoun
- **Editor** - A web based editor for creating and editing Mermaid diagrams.
- **Visual Editor** - The Visual Editor enables users of all skill levels to create diagrams easily and efficiently, with both GUI and code-based editing options.
- **Mermaid AI** - Use our embedded AI Chat to generate diagrams from natural language descriptions.
- **AI Chat** - Use our embedded AI Chat to generate diagrams from natural language descriptions.
- **Whiteboard** - A virtual whiteboard for creating and editing Mermaid diagrams.
- **Plugins** - A plugin system for extending the functionality of Mermaid.
Official Mermaid Chart plugins:
- [Mermaid Chart GPT](https://chat.openai.com/g/g-1IRFKwq4G-mermaid-chart)
- [Confluence](https://marketplace.atlassian.com/apps/1234056/mermaid-chart-for-confluence?hosting=cloud&tab=overview)
- [Jira](https://marketplace.atlassian.com/apps/1234810/mermaid-chart-for-jira?tab=overview&hosting=cloud)
- [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=MermaidChart.vscode-mermaid-chart)
- [JetBrains IDE](https://plugins.jetbrains.com/plugin/23043-mermaid-chart)
- [Google Docs](https://gsuite.google.com/marketplace/app/mermaidchart/947683068472)
- [Microsoft PowerPoint and Word](https://appsource.microsoft.com/en-us/product/office/WA200006214?tab=Overview)
Visit our [Plugins](https://www.mermaidchart.com/plugins) page for more information.

View File

@@ -1,5 +1,11 @@
# Blog
## [Expanding the Horizons of Mermaid Flowcharts: Introducing 30 New Shapes!](https://www.mermaidchart.com/blog/posts/new-mermaid-flowchart-shapes/)
24 September 2024 · 5 mins
Discover 30 new shapes in Mermaid flowcharts, offering enhanced clarity, customization, and versatility for more dynamic and expressive visualizations.
## [Introducing Architecture Diagrams in Mermaid](https://www.mermaidchart.com/blog/posts/mermaid-supports-architecture-diagrams/)
2 September 2024 · 2 mins

View File

@@ -153,6 +153,19 @@ block-beta
This example demonstrates how Mermaid dynamically adjusts the width of the columns to accommodate the widest block, in this case, 'a' and the composite block 'e'. This dynamic adjustment is essential for creating visually balanced and easy-to-understand diagrams.
**Merging Blocks Horizontally:**
In scenarios where you need to stack blocks horizontally, you can use column width to accomplish the task. Blocks can be arranged vertically by putting them in a single column. Here is how you can create a block diagram in which 4 blocks are stacked on top of each other:
```mermaid-example
block-beta
block
columns 1
a["A label"] b c d
end
```
In this example, the width of the merged block dynamically adjusts to the width of the largest child block.
With these advanced configuration options, Mermaid's block diagrams can be tailored to represent a wide array of complex systems and structures. The flexibility offered by these features enables users to create diagrams that are both informative and visually appealing. In the following sections, we will explore further capabilities, including different block shapes and linking options.
## 4. Block Varieties and Shapes

View File

@@ -194,7 +194,7 @@ flowchart TD
id1(((This is the text in the circle)))
```
## Expanded Node Shapes in Mermaid Flowcharts
## Expanded Node Shapes in Mermaid Flowcharts (v11.3.0+)
Mermaid introduces 30 new shapes to enhance the flexibility and precision of flowchart creation. These new shapes provide more options to represent processes, decisions, events, data storage visually, and other elements within your flowcharts, improving clarity and semantic meaning.
@@ -212,53 +212,7 @@ This syntax creates a node A as a rectangle. It renders in the same way as `A["A
Below is a comprehensive list of the newly introduced shapes and their corresponding semantic meanings, short names, and aliases:
| **Semantic Name** | **Shape Name** | **Short Name** | **Description** | **Alias Supported** |
| ------------------------------------- | ---------------------- | -------------- | ------------------------------ | ----------------------------------------------------------- |
| **Process** | Rectangle | `rect` | Standard process shape | `proc`, `process`, `rectangle` |
| **Event** | Rounded Rectangle | `rounded` | Represents an event | `event` |
| **Terminal Point** | Stadium | `stadium` | Terminal point | `terminal`, `pill` |
| **Subprocess** | Framed Rectangle | `fr-rect` | Subprocess | `subprocess`,`subproc`, `framed-rectangle`, `subroutine` |
| **Database** | Cylinder | `cyl` | Database storage | `db`, `database`, `cylinder` |
| **Start** | Circle | `circle` | Starting point | `circ` |
| **Odd** | Odd | `odd` | Odd shape | |
| **Decision** | Diamond | `diam` | Decision-making step | `decision`, `diamond` |
| **Prepare Conditional** | Hexagon | `hex` | Preparation or condition step | `hexagon`, `prepare` |
| **Data Input/Output** | Lean Right | `lean-r` | Represents input or output | `lean-right`, `in-out` |
| **Data Input/Output** | Lean Left | `lean-l` | Represents output or input | `lean-left`, `out-in` |
| **Priority Action** | Trapezoid Base Bottom | `trap-b` | Priority action | `priority`, `trapezoid-bottom` |
| **Manual Operation** | Trapezoid Base Top | `trap-t` | Represents a manual task | `manual`, `trapezoid-top` |
| **Stop** | Double Circle | `dbl-circ` | Represents a stop point | `double-circle` |
| **Text Block** | Text Block | `text` | Text block | - |
| **Card** | Notched Rectangle | `notch-rect` | Represents a card | `card`, `notched-rectangle` |
| **Lined/Shaded Process** | Lined Rectangle | `lin-rect` | Lined process shape | `lined-rectangle`,`lined-proc`, `lin-proc`,`shaded-process` |
| **Start** | Small Circle | `sm-circ` | Small starting point | `start`, `small-circle` |
| **Stop** | Framed Circle | `fr-circ` | Stop point | `stop`, `framed-circle` |
| **Fork/Join** | Filled Rectangle | `fork` | Fork or join in process flow | `join` |
| **Collate** | Hourglass | `hourglass` | Represents a collate operation | `hourglass` |
| **Comment** | Curly Brace | `brace` | Adds a comment | `comment`, `brace-l` |
| **Comment Right** | Curly Brace | `brace-r` | Adds a comment | - |
| **Comment with braces on both sides** | Curly Braces | `braces` | Adds a comment | - |
| **Com Link** | Lightning Bolt | `bolt` | Communication link | `com-link`, `lightning-bolt` |
| **Document** | Document | `doc` | Represents a document | `doc`, `document` |
| **Delay** | Half-Rounded Rectangle | `delay` | Represents a delay | `half-rounded-rectangle` |
| **Direct Access Storage** | Horizontal Cylinder | `h-cyl` | Direct access storage | `das`, `horizontal-cylinder` |
| **Disk Storage** | Lined Cylinder | `lin-cyl` | Disk storage | `disk`, `lined-cylinder` |
| **Display** | Curved Trapezoid | `curv-trap` | Represents a display | `curved-trapezoid`, `display` |
| **Divided Process** | Divided Rectangle | `div-rect` | Divided process shape | `div-proc`, `divided-rectangle`, `divided-process` |
| **Extract** | Triangle | `tri` | Extraction process | `extract`, `triangle` |
| **Internal Storage** | Window Pane | `win-pane` | Internal storage | `internal-storage`, `window-pane` |
| **Junction** | Filled Circle | `f-circ` | Junction point | `junction`, `filled-circle` |
| **Lined Document** | Lined Document | `lin-doc` | Lined document | `lined-document` |
| **Loop Limit** | Trapezoidal Pentagon | `notch-pent` | Loop limit step | `loop-limit`, `notched-pentagon` |
| **Manual File** | Flipped Triangle | `flip-tri` | Manual file operation | `manual-file`, `flipped-triangle` |
| **Manual Input** | Sloped Rectangle | `sl-rect` | Manual input step | `manual-input`, `sloped-rectangle` |
| **Multi-Document** | Stacked Document | `docs` | Multiple documents | `documents`, `st-doc`, `stacked-document` |
| **Multi-Process** | Stacked Rectangle | `st-rect` | Multiple processes | `procs`, `processes`, `stacked-rect` |
| **Paper Tape** | Flag | `flag` | Paper tape | `paper-tape` |
| **Stored Data** | Bow Tie Rectangle | `bow-rect` | Stored data | `stored-data`, `bow-tie-rectangle` |
| **Summary** | Crossed Circle | `cross-circ` | Summary | `summary`, `crossed-circle` |
| **Tagged Document** | Tagged Document | `tag-doc` | Tagged document | `tag-doc`, `tagged-document` |
| **Tagged Process** | Tagged Rectangle | `tag-rect` | Tagged process | `tagged-rectangle`,`tag-proc`, `tagged-process` |
<!--@include: virtual:shapesTable -->
### Example Flowchart with New Shapes
@@ -298,7 +252,7 @@ flowchart TD
```mermaid-example
flowchart TD
A@{ shape: fr, label: "This is a subprocess" }
A@{ shape: subproc, label: "This is a subprocess" }
```
### Database (Cylinder)

View File

@@ -105,6 +105,9 @@ end
box rgb(33,66,99)
... actors ...
end
box rgba(33,66,99,0.5)
... actors ...
end
```
```note
@@ -394,6 +397,12 @@ sequenceDiagram
It is possible to highlight flows by providing colored background rects. This is done by the notation
```
rect COLOR
... content ...
end
```
The colors are defined using rgb and rgba syntax.
```

View File

@@ -1,6 +1,4 @@
import { select } from 'd3';
import { insertNode } from '../dagre-wrapper/nodes.js';
import { getConfig } from '../diagram-api/diagramAPI.js';
export const getDiagramElement = (id, securityLevel) => {
let sandboxElement;
@@ -18,41 +16,3 @@ export const getDiagramElement = (id, securityLevel) => {
return svg;
};
export function insertElementsForSize(el, data) {
const nodesElem = el.insert('g').attr('class', 'nodes');
el.insert('g').attr('class', 'edges');
const config = getConfig();
data.nodes.forEach(async (item) => {
item.shape = 'rect';
await insertNode(
nodesElem,
{
...item,
class: 'default flowchart-label',
labelStyle: '',
x: 0,
y: 0,
width: 100,
rx: 0,
ry: 0,
height: 100,
shape: 'rect',
padding: 8,
},
{ config }
);
// Create a new DOM element
// const element = document.createElement('div');
// // Set the content of the element to the name of the item
// element.textContent = item.name;
// // Set the size of the element to the size of the item
// element.style.width = `${item.size}px`;
// element.style.height = `${item.size}px`;
// Append the element to the body of the document
// document.body.appendChild(element);
});
}

View File

@@ -1,305 +1,5 @@
import { log } from '../../logger.js';
import { state } from './shapes/state.ts';
import { roundedRect } from './shapes/roundedRect.ts';
import { squareRect } from './shapes/squareRect.ts';
import { stateStart } from './shapes/stateStart.ts';
import { stateEnd } from './shapes/stateEnd.ts';
import { forkJoin } from './shapes/forkJoin.ts';
import { choice } from './shapes/choice.ts';
import { note } from './shapes/note.ts';
import { stadium } from './shapes/stadium.js';
import { rectWithTitle } from './shapes/rectWithTitle.js';
import { subroutine } from './shapes/subroutine.js';
import { cylinder } from './shapes/cylinder.js';
import { circle } from './shapes/circle.js';
import { doublecircle } from './shapes/doubleCircle.js';
import { rect_left_inv_arrow } from './shapes/rectLeftInvArrow.js';
import { question } from './shapes/question.js';
import { hexagon } from './shapes/hexagon.js';
import { text } from './shapes/text.js';
import { card } from './shapes/card.js';
import { shadedProcess } from './shapes/shadedProcess.js';
import { anchor } from './shapes/anchor.js';
import { lean_right } from './shapes/leanRight.js';
import { lean_left } from './shapes/leanLeft.js';
import { trapezoid } from './shapes/trapezoid.js';
import { inv_trapezoid } from './shapes/invertedTrapezoid.js';
import { labelRect } from './shapes/labelRect.js';
import { triangle } from './shapes/triangle.js';
import { halfRoundedRectangle } from './shapes/halfRoundedRectangle.js';
import { curvedTrapezoid } from './shapes/curvedTrapezoid.js';
import { slopedRect } from './shapes/slopedRect.js';
import { bowTieRect } from './shapes/bowTieRect.js';
import { dividedRectangle } from './shapes/dividedRect.js';
import { crossedCircle } from './shapes/crossedCircle.js';
import { waveRectangle } from './shapes/waveRectangle.js';
import { tiltedCylinder } from './shapes/tiltedCylinder.js';
import { trapezoidalPentagon } from './shapes/trapezoidalPentagon.js';
import { flippedTriangle } from './shapes/flippedTriangle.js';
import { hourglass } from './shapes/hourglass.js';
import { taggedRect } from './shapes/taggedRect.js';
import { multiRect } from './shapes/multiRect.js';
import { linedCylinder } from './shapes/linedCylinder.js';
import { waveEdgedRectangle } from './shapes/waveEdgedRectangle.js';
import { lightningBolt } from './shapes/lightningBolt.js';
import { filledCircle } from './shapes/filledCircle.js';
import { multiWaveEdgedRectangle } from './shapes/multiWaveEdgedRectangle.js';
import { windowPane } from './shapes/windowPane.js';
import { linedWaveEdgedRect } from './shapes/linedWaveEdgedRect.js';
import { taggedWaveEdgedRectangle } from './shapes/taggedWaveEdgedRectangle.js';
import { curlyBraceLeft } from './shapes/curlyBraceLeft.js';
import { curlyBraceRight } from './shapes/curlyBraceRight.js';
import { curlyBraces } from './shapes/curlyBraces.js';
import { iconSquare } from './shapes/iconSquare.js';
import { iconCircle } from './shapes/iconCircle.js';
import { icon } from './shapes/icon.js';
import { imageSquare } from './shapes/imageSquare.js';
import { iconRounded } from './shapes/iconRounded.js';
//Use these names as the left side to render shapes.
export const shapes = {
// States
state,
stateStart,
stateEnd,
forkJoin,
choice,
note,
// Rectangles
rectWithTitle,
roundedRect,
squareRect,
// Rectangle with alias: 'process', 'rect', 'proc', 'rectangle'
rectangle: squareRect,
rect: squareRect,
process: squareRect,
proc: squareRect,
// Rounded Rectangle with alias: 'event', 'rounded'
rounded: roundedRect,
event: roundedRect,
// Stadium with alias: 'terminal','pill', 'stadium'
stadium,
pill: stadium,
terminal: stadium,
// Subprocess with alias: 'fr-rect', 'subproc', 'subprocess', 'framed-rectangle', 'subroutine'
subroutine,
'framed-rectangle': subroutine,
'fr-rect': subroutine,
subprocess: subroutine,
subproc: subroutine,
// Cylinder with alias: 'db', 'database', 'cylinder', 'cyl'
cylinder,
db: cylinder,
cyl: cylinder,
database: cylinder,
// Diamond with alias: 'diam', 'decision', 'diamond'
question,
diam: question,
diamond: question,
decision: question,
// Hexagon with alias: 'hex', 'hexagon', 'prepare'
hexagon,
hex: hexagon,
prepare: hexagon,
// Lean Right with alias: 'lean-r', 'lean-right', 'in-out'
lean_right, // used in old syntax for flowchart
'lean-r': lean_right,
'lean-right': lean_right,
'in-out': lean_right,
// Lean Left with alias: 'lean-l', 'lean-left', 'out-in'
lean_left, // used in old syntax for flowchart
'lean-l': lean_left,
'lean-left': lean_left,
'out-in': lean_left,
// Trapezoid with alias: 'trap-b', 'trapezoid-bottom', 'priority'
trapezoid, // used in old syntax for flowchart
'trap-b': trapezoid,
'trapezoid-bottom': trapezoid,
priority: trapezoid,
// Inverted Trapezoid with alias: 'inv-trapezoid', 'trapezoid-top', 'trap-t', 'manual'
inv_trapezoid, // used in old syntax for flowchart
'inv-trapezoid': inv_trapezoid,
'trapezoid-top': inv_trapezoid,
'trap-t': inv_trapezoid,
manual: inv_trapezoid,
// Double Circle with alias: 'dbl-circ', 'double-circle'
doublecircle, // used in old syntax for flowchart
'dbl-circ': doublecircle,
'double-circle': doublecircle,
// circle with alias: 'circ', 'circle'
circle,
circ: circle,
// Rect Left Inv Arrow with alias: 'odd', 'rect-left-inv-arrow'
rect_left_inv_arrow,
odd: rect_left_inv_arrow,
// Notched Rectangle with alias: 'notched-rectangle', 'notch-rect', 'card'
card,
'notched-rectangle': card,
'notch-rect': card,
// Lined rectangle with alias: 'lin-rect', 'lined-rectangle', 'lin-proc', lined-process', 'shaded-process'
'lined-rectangle': shadedProcess,
'lin-rect': shadedProcess,
'lin-proc': shadedProcess,
'lined-process': shadedProcess,
'shaded-process': shadedProcess,
// Small circle with alias: 'sm-circ', 'small-circle', 'start'
'small-circle': stateStart,
'sm-circ': stateStart,
start: stateStart,
// framed circle with alias: 'stop', 'framed-circle', 'fr-circ'
stop: stateEnd,
'framed-circle': stateEnd,
'fr-circ': stateEnd,
// fork with alias: 'join', 'fork'
join: forkJoin,
fork: forkJoin,
// comment with alias: 'comment', 'brace-l'
comment: curlyBraceLeft,
'brace-l': curlyBraceLeft,
// lightening bolt with alias: 'bolt', 'com-link', 'lightning-bolt'
bolt: lightningBolt,
'com-link': lightningBolt,
'lightning-bolt': lightningBolt,
// document with alias: 'doc', 'document'
doc: waveEdgedRectangle,
document: waveEdgedRectangle,
// delay with alias: 'delay', 'half-rounded-rectangle'
delay: halfRoundedRectangle,
'half-rounded-rectangle': halfRoundedRectangle,
// horizontal cylinder with alias: 'h-cyl', 'das', 'horizontal-cylinder'
'horizontal-cylinder': tiltedCylinder,
'h-cyl': tiltedCylinder,
das: tiltedCylinder,
// lined cylinder with alias: 'lin-cyl', 'lined-cylinder', 'disk'
'lined-cylinder': linedCylinder,
'lin-cyl': linedCylinder,
disk: linedCylinder,
// curved trapezoid with alias: 'curv-trap', 'curved-trapezoid', 'display'
'curved-trapezoid': curvedTrapezoid,
'curv-trap': curvedTrapezoid,
display: curvedTrapezoid,
// divided rectangle with alias: 'div-rect', 'divided-rectangle', 'div-proc', 'divided-process'
'divided-rectangle': dividedRectangle,
'div-rect': dividedRectangle,
'div-proc': dividedRectangle,
'divided-process': dividedRectangle,
// triangle with alias: 'tri', 'triangle', 'extract'
triangle,
tri: triangle,
extract: triangle,
// window pane with alias: 'window-pane', 'win-pane', 'internal-storage'
'window-pane': windowPane,
'win-pane': windowPane,
'internal-storage': windowPane,
// filled circle with alias: 'f-circ', 'filled-circle', 'junction'
'f-circ': filledCircle,
junction: filledCircle,
'filled-circle': filledCircle,
// lined document with alias: 'lin-doc', 'lined-document'
'lin-doc': linedWaveEdgedRect,
'lined-document': linedWaveEdgedRect,
// notched pentagon with alias: 'notch-pent', 'notched-pentagon', 'loop-limit'
'notched-pentagon': trapezoidalPentagon,
'notch-pent': trapezoidalPentagon,
'loop-limit': trapezoidalPentagon,
// flipped triangle with alias: 'flip-tri', 'flipped-triangle', 'manual-file'
'flipped-triangle': flippedTriangle,
'flip-tri': flippedTriangle,
'manual-file': flippedTriangle,
// sloped rectangle with alias: 'sl-rect', 'sloped-rectangle', 'manual-input'
'sloped-rectangle': slopedRect,
'sl-rect': slopedRect,
'manual-input': slopedRect,
// documents with alias: 'docs', 'documents', 'st-doc', 'stacked-document'
docs: multiWaveEdgedRectangle,
documents: multiWaveEdgedRectangle,
'st-doc': multiWaveEdgedRectangle,
'stacked-document': multiWaveEdgedRectangle,
// 'processes' with alias: 'procs', 'processes', 'st-rect', 'stacked-rectangle'
processes: multiRect,
procs: multiRect,
'stacked-rectangle': multiRect,
'st-rect': multiRect,
// flag with alias: 'flag', 'paper-tape'
flag: waveRectangle,
'paper-tape': waveRectangle,
// bow tie rectangle with alias: 'bow-rect', 'bow-tie-rectangle', 'stored-data'
'bow-tie-rectangle': bowTieRect,
'bow-rect': bowTieRect,
'stored-data': bowTieRect,
// crossed circle with alias: 'cross-circ', 'crossed-circle', 'summary'
'crossed-circle': crossedCircle,
'cross-circ': crossedCircle,
summary: crossedCircle,
// tagged document with alias: 'tag-doc', 'tagged-document'
'tag-doc': taggedWaveEdgedRectangle,
'tagged-document': taggedWaveEdgedRectangle,
// tagged rectangle with alias: 'tag-rect', 'tagged-rectangle', 'tag-proc', 'tagged-process'
'tag-rect': taggedRect,
'tagged-rectangle': taggedRect,
'tag-proc': taggedRect,
'tagged-process': taggedRect,
// hourglass with alias: 'hourglass', 'collate'
hourglass,
collate: hourglass,
text,
anchor,
brace: curlyBraceLeft,
labelRect,
'brace-r': curlyBraceRight,
braces: curlyBraces,
iconSquare,
iconCircle,
icon,
iconRounded,
imageSquare,
};
import { shapes } from './shapes.js';
const nodeElems = new Map();
@@ -307,8 +7,6 @@ export const insertNode = async (elem, node, renderOptions) => {
let newEl;
let el;
// console.log("node is ", node.icon, node.shape)
//special check for rect shape (with or without rounded corners)
if (node.shape === 'rect') {
if (node.rx && node.ry) {
@@ -318,7 +16,9 @@ export const insertNode = async (elem, node, renderOptions) => {
}
}
if (!shapes[node.shape]) {
const shapeHandler = shapes[node.shape];
if (!shapeHandler) {
throw new Error(`No such shape: ${node.shape}. Please check your syntax.`);
}
@@ -331,9 +31,9 @@ export const insertNode = async (elem, node, renderOptions) => {
target = node.linkTarget || '_blank';
}
newEl = elem.insert('svg:a').attr('xlink:href', node.link).attr('target', target);
el = await shapes[node.shape](newEl, node, renderOptions);
el = await shapeHandler(newEl, node, renderOptions);
} else {
el = await shapes[node.shape](elem, node, renderOptions);
el = await shapeHandler(elem, node, renderOptions);
newEl = el;
}
// MC Special
@@ -353,9 +53,11 @@ export const insertNode = async (elem, node, renderOptions) => {
}
return newEl;
};
export const setNodeElem = (elem, node) => {
nodeElems.set(node.id, elem);
};
export const clear = () => {
nodeElems.clear();
};

View File

@@ -1,5 +1,5 @@
import exp from 'constants';
import { shapes } from './nodes.js';
import { shapes } from './shapes.js';
import { describe, it, expect } from 'vitest';
describe('Test Alias for shapes', function () {
// for each shape in docs/syntax/flowchart.md, along with its semantic name, short name, and alias name, add a test case
@@ -83,10 +83,11 @@ describe('Test Alias for shapes', function () {
expect(shapes['notch-rect']).toBe(shapes['notched-rectangle']);
});
// lined-rect | lined-proc | shaded-proc
it('should support alias for shadedProcess shape ', function () {
expect(shapes['lined-proc']).toBe(shapes['lined-rect']);
expect(shapes['shaded-proc']).toBe(shapes['lined-rect']);
const aliases = ['lined-process', 'lined-rectangle', 'lin-proc', 'lin-rect'];
for (const alias of aliases) {
expect(shapes[alias]).toBe(shapes['shaded-process']);
}
});
// sm-circ | small-circle | start

View File

@@ -0,0 +1,481 @@
import type { Node, ShapeRenderOptions } from '../types.js';
import { anchor } from './shapes/anchor.js';
import { bowTieRect } from './shapes/bowTieRect.js';
import { card } from './shapes/card.js';
import { choice } from './shapes/choice.js';
import { circle } from './shapes/circle.js';
import { crossedCircle } from './shapes/crossedCircle.js';
import { curlyBraceLeft } from './shapes/curlyBraceLeft.js';
import { curlyBraceRight } from './shapes/curlyBraceRight.js';
import { curlyBraces } from './shapes/curlyBraces.js';
import { curvedTrapezoid } from './shapes/curvedTrapezoid.js';
import { cylinder } from './shapes/cylinder.js';
import { dividedRectangle } from './shapes/dividedRect.js';
import { doublecircle } from './shapes/doubleCircle.js';
import { filledCircle } from './shapes/filledCircle.js';
import { flippedTriangle } from './shapes/flippedTriangle.js';
import { forkJoin } from './shapes/forkJoin.js';
import { halfRoundedRectangle } from './shapes/halfRoundedRectangle.js';
import { hexagon } from './shapes/hexagon.js';
import { hourglass } from './shapes/hourglass.js';
import { icon } from './shapes/icon.js';
import { iconCircle } from './shapes/iconCircle.js';
import { iconRounded } from './shapes/iconRounded.js';
import { iconSquare } from './shapes/iconSquare.js';
import { imageSquare } from './shapes/imageSquare.js';
import { inv_trapezoid } from './shapes/invertedTrapezoid.js';
import { labelRect } from './shapes/labelRect.js';
import { lean_left } from './shapes/leanLeft.js';
import { lean_right } from './shapes/leanRight.js';
import { lightningBolt } from './shapes/lightningBolt.js';
import { linedCylinder } from './shapes/linedCylinder.js';
import { linedWaveEdgedRect } from './shapes/linedWaveEdgedRect.js';
import { multiRect } from './shapes/multiRect.js';
import { multiWaveEdgedRectangle } from './shapes/multiWaveEdgedRectangle.js';
import { note } from './shapes/note.js';
import { question } from './shapes/question.js';
import { rect_left_inv_arrow } from './shapes/rectLeftInvArrow.js';
import { rectWithTitle } from './shapes/rectWithTitle.js';
import { roundedRect } from './shapes/roundedRect.js';
import { shadedProcess } from './shapes/shadedProcess.js';
import { slopedRect } from './shapes/slopedRect.js';
import { squareRect } from './shapes/squareRect.js';
import { stadium } from './shapes/stadium.js';
import { state } from './shapes/state.js';
import { stateEnd } from './shapes/stateEnd.js';
import { stateStart } from './shapes/stateStart.js';
import { subroutine } from './shapes/subroutine.js';
import { taggedRect } from './shapes/taggedRect.js';
import { taggedWaveEdgedRectangle } from './shapes/taggedWaveEdgedRectangle.js';
import { text } from './shapes/text.js';
import { tiltedCylinder } from './shapes/tiltedCylinder.js';
import { trapezoid } from './shapes/trapezoid.js';
import { trapezoidalPentagon } from './shapes/trapezoidalPentagon.js';
import { triangle } from './shapes/triangle.js';
import { waveEdgedRectangle } from './shapes/waveEdgedRectangle.js';
import { waveRectangle } from './shapes/waveRectangle.js';
import { windowPane } from './shapes/windowPane.js';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type ShapeHandler = (parent: any, node: Node, options: ShapeRenderOptions) => unknown;
export interface ShapeDefinition {
semanticName: string;
name: string;
shortName: string;
description: string;
/**
* Aliases can include descriptive names, other short names, etc.
*/
aliases?: string[];
/**
* These are names used by mermaid before the introduction of new shapes. These will not be in standard formats, and shouldn't be used by the users
*/
internalAliases?: string[];
handler: ShapeHandler;
}
export const shapesDefs: ShapeDefinition[] = [
{
semanticName: 'Process',
name: 'Rectangle',
shortName: 'rect',
description: 'Standard process shape',
aliases: ['proc', 'process', 'rectangle'],
internalAliases: ['squareRect'],
handler: squareRect,
},
{
semanticName: 'Event',
name: 'Rounded Rectangle',
shortName: 'rounded',
description: 'Represents an event',
aliases: ['event'],
internalAliases: ['roundedRect'],
handler: roundedRect,
},
{
semanticName: 'Terminal Point',
name: 'Stadium',
shortName: 'stadium',
description: 'Terminal point',
aliases: ['terminal', 'pill'],
handler: stadium,
},
{
semanticName: 'Subprocess',
name: 'Framed Rectangle',
shortName: 'fr-rect',
description: 'Subprocess',
aliases: ['subprocess', 'subproc', 'framed-rectangle', 'subroutine'],
handler: subroutine,
},
{
semanticName: 'Database',
name: 'Cylinder',
shortName: 'cyl',
description: 'Database storage',
aliases: ['db', 'database', 'cylinder'],
handler: cylinder,
},
{
semanticName: 'Start',
name: 'Circle',
shortName: 'circle',
description: 'Starting point',
aliases: ['circ'],
handler: circle,
},
{
semanticName: 'Decision',
name: 'Diamond',
shortName: 'diam',
description: 'Decision-making step',
aliases: ['decision', 'diamond', 'question'],
handler: question,
},
{
semanticName: 'Prepare Conditional',
name: 'Hexagon',
shortName: 'hex',
description: 'Preparation or condition step',
aliases: ['hexagon', 'prepare'],
handler: hexagon,
},
{
semanticName: 'Data Input/Output',
name: 'Lean Right',
shortName: 'lean-r',
description: 'Represents input or output',
aliases: ['lean-right', 'in-out'],
internalAliases: ['lean_right'],
handler: lean_right,
},
{
semanticName: 'Data Input/Output',
name: 'Lean Left',
shortName: 'lean-l',
description: 'Represents output or input',
aliases: ['lean-left', 'out-in'],
internalAliases: ['lean_left'],
handler: lean_left,
},
{
semanticName: 'Priority Action',
name: 'Trapezoid Base Bottom',
shortName: 'trap-b',
description: 'Priority action',
aliases: ['priority', 'trapezoid-bottom', 'trapezoid'],
handler: trapezoid,
},
{
semanticName: 'Manual Operation',
name: 'Trapezoid Base Top',
shortName: 'trap-t',
description: 'Represents a manual task',
aliases: ['manual', 'trapezoid-top', 'inv-trapezoid'],
internalAliases: ['inv_trapezoid'],
handler: inv_trapezoid,
},
{
semanticName: 'Stop',
name: 'Double Circle',
shortName: 'dbl-circ',
description: 'Represents a stop point',
aliases: ['double-circle'],
internalAliases: ['doublecircle'],
handler: doublecircle,
},
{
semanticName: 'Text Block',
name: 'Text Block',
shortName: 'text',
description: 'Text block',
handler: text,
},
{
semanticName: 'Card',
name: 'Notched Rectangle',
shortName: 'notch-rect',
description: 'Represents a card',
aliases: ['card', 'notched-rectangle'],
handler: card,
},
{
semanticName: 'Lined/Shaded Process',
name: 'Lined Rectangle',
shortName: 'lin-rect',
description: 'Lined process shape',
aliases: ['lined-rectangle', 'lined-process', 'lin-proc', 'shaded-process'],
handler: shadedProcess,
},
{
semanticName: 'Start',
name: 'Small Circle',
shortName: 'sm-circ',
description: 'Small starting point',
aliases: ['start', 'small-circle'],
internalAliases: ['stateStart'],
handler: stateStart,
},
{
semanticName: 'Stop',
name: 'Framed Circle',
shortName: 'fr-circ',
description: 'Stop point',
aliases: ['stop', 'framed-circle'],
internalAliases: ['stateEnd'],
handler: stateEnd,
},
{
semanticName: 'Fork/Join',
name: 'Filled Rectangle',
shortName: 'fork',
description: 'Fork or join in process flow',
aliases: ['join'],
internalAliases: ['forkJoin'],
handler: forkJoin,
},
{
semanticName: 'Collate',
name: 'Hourglass',
shortName: 'hourglass',
description: 'Represents a collate operation',
aliases: ['hourglass', 'collate'],
handler: hourglass,
},
{
semanticName: 'Comment',
name: 'Curly Brace',
shortName: 'brace',
description: 'Adds a comment',
aliases: ['comment', 'brace-l'],
handler: curlyBraceLeft,
},
{
semanticName: 'Comment Right',
name: 'Curly Brace',
shortName: 'brace-r',
description: 'Adds a comment',
handler: curlyBraceRight,
},
{
semanticName: 'Comment with braces on both sides',
name: 'Curly Braces',
shortName: 'braces',
description: 'Adds a comment',
handler: curlyBraces,
},
{
semanticName: 'Com Link',
name: 'Lightning Bolt',
shortName: 'bolt',
description: 'Communication link',
aliases: ['com-link', 'lightning-bolt'],
handler: lightningBolt,
},
{
semanticName: 'Document',
name: 'Document',
shortName: 'doc',
description: 'Represents a document',
aliases: ['doc', 'document'],
handler: waveEdgedRectangle,
},
{
semanticName: 'Delay',
name: 'Half-Rounded Rectangle',
shortName: 'delay',
description: 'Represents a delay',
aliases: ['half-rounded-rectangle'],
handler: halfRoundedRectangle,
},
{
semanticName: 'Direct Access Storage',
name: 'Horizontal Cylinder',
shortName: 'h-cyl',
description: 'Direct access storage',
aliases: ['das', 'horizontal-cylinder'],
handler: tiltedCylinder,
},
{
semanticName: 'Disk Storage',
name: 'Lined Cylinder',
shortName: 'lin-cyl',
description: 'Disk storage',
aliases: ['disk', 'lined-cylinder'],
handler: linedCylinder,
},
{
semanticName: 'Display',
name: 'Curved Trapezoid',
shortName: 'curv-trap',
description: 'Represents a display',
aliases: ['curved-trapezoid', 'display'],
handler: curvedTrapezoid,
},
{
semanticName: 'Divided Process',
name: 'Divided Rectangle',
shortName: 'div-rect',
description: 'Divided process shape',
aliases: ['div-proc', 'divided-rectangle', 'divided-process'],
handler: dividedRectangle,
},
{
semanticName: 'Extract',
name: 'Triangle',
shortName: 'tri',
description: 'Extraction process',
aliases: ['extract', 'triangle'],
handler: triangle,
},
{
semanticName: 'Internal Storage',
name: 'Window Pane',
shortName: 'win-pane',
description: 'Internal storage',
aliases: ['internal-storage', 'window-pane'],
handler: windowPane,
},
{
semanticName: 'Junction',
name: 'Filled Circle',
shortName: 'f-circ',
description: 'Junction point',
aliases: ['junction', 'filled-circle'],
handler: filledCircle,
},
{
semanticName: 'Loop Limit',
name: 'Trapezoidal Pentagon',
shortName: 'notch-pent',
description: 'Loop limit step',
aliases: ['loop-limit', 'notched-pentagon'],
handler: trapezoidalPentagon,
},
{
semanticName: 'Manual File',
name: 'Flipped Triangle',
shortName: 'flip-tri',
description: 'Manual file operation',
aliases: ['manual-file', 'flipped-triangle'],
handler: flippedTriangle,
},
{
semanticName: 'Manual Input',
name: 'Sloped Rectangle',
shortName: 'sl-rect',
description: 'Manual input step',
aliases: ['manual-input', 'sloped-rectangle'],
handler: slopedRect,
},
{
semanticName: 'Multi-Document',
name: 'Stacked Document',
shortName: 'docs',
description: 'Multiple documents',
aliases: ['documents', 'st-doc', 'stacked-document'],
handler: multiWaveEdgedRectangle,
},
{
semanticName: 'Multi-Process',
name: 'Stacked Rectangle',
shortName: 'st-rect',
description: 'Multiple processes',
aliases: ['procs', 'processes', 'stacked-rectangle'],
handler: multiRect,
},
{
semanticName: 'Stored Data',
name: 'Bow Tie Rectangle',
shortName: 'bow-rect',
description: 'Stored data',
aliases: ['stored-data', 'bow-tie-rectangle'],
handler: bowTieRect,
},
{
semanticName: 'Summary',
name: 'Crossed Circle',
shortName: 'cross-circ',
description: 'Summary',
aliases: ['summary', 'crossed-circle'],
handler: crossedCircle,
},
{
semanticName: 'Tagged Document',
name: 'Tagged Document',
shortName: 'tag-doc',
description: 'Tagged document',
aliases: ['tag-doc', 'tagged-document'],
handler: taggedWaveEdgedRectangle,
},
{
semanticName: 'Tagged Process',
name: 'Tagged Rectangle',
shortName: 'tag-rect',
description: 'Tagged process',
aliases: ['tagged-rectangle', 'tag-proc', 'tagged-process'],
handler: taggedRect,
},
{
semanticName: 'Paper Tape',
name: 'Flag',
shortName: 'flag',
description: 'Paper tape',
aliases: ['paper-tape'],
handler: waveRectangle,
},
{
semanticName: 'Odd',
name: 'Odd',
shortName: 'odd',
description: 'Odd shape',
internalAliases: ['rect_left_inv_arrow'],
handler: rect_left_inv_arrow,
},
{
semanticName: 'Lined Document',
name: 'Lined Document',
shortName: 'lin-doc',
description: 'Lined document',
aliases: ['lined-document'],
handler: linedWaveEdgedRect,
},
];
const generateShapeMap = () => {
// These are the shapes that didn't have documentation present
const shapeMap: Record<string, ShapeHandler> = {
// States
state,
choice,
note,
// Rectangles
rectWithTitle,
labelRect,
// Icons
iconSquare,
iconCircle,
icon,
iconRounded,
imageSquare,
anchor,
};
for (const shape of shapesDefs) {
for (const alias of [
shape.shortName,
...(shape.aliases ?? []),
...(shape.internalAliases ?? []),
]) {
shapeMap[alias] = shape.handler;
}
}
return shapeMap;
};
export const shapes = generateShapeMap();

View File

@@ -1,7 +1,7 @@
import { log } from '../../../logger.js';
import { updateNodeBounds, getNodeClasses } from './util.js';
import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts';
import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs';
@@ -23,7 +23,6 @@ export const anchor = (parent: SVGAElement, node: Node): Promise<SVGAElement> =>
const { cssStyles } = node;
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, { fill: 'black', stroke: 'none', fillStyle: 'solid' });

View File

@@ -1,6 +1,6 @@
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts';
import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs';
@@ -132,7 +132,6 @@ export const bowTieRect = async (parent: SVGAElement, node: Node) => {
...generateArcPoints(w / 2, h / 2, w / 2, -h / 2, rx, ry, true),
];
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});

View File

@@ -1,6 +1,6 @@
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts';
import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs';
@@ -53,7 +53,6 @@ export async function card(parent: SVGAElement, node: Node): Promise<SVGAElement
const { cssStyles } = node;
if (node.look === 'handDrawn') {
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const pathData = createPathFromPoints(points);

View File

@@ -24,7 +24,6 @@ export const circle = async (parent: SVGAElement, node: Node): Promise<SVGAEleme
const { cssStyles } = node;
if (node.look === 'handDrawn') {
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const roughNode = rc.circle(0, 0, radius * 2, options);

View File

@@ -28,7 +28,7 @@ export const crossedCircle = (parent: SVG, node: Node) => {
const radius = node?.width ? node?.width / 2 : node?.height ? node?.height / 2 : 25;
const { cssStyles } = node;
// @ts-ignore - rough is not typed
// @ts-expect-error shapeSvg d3 class is incorrect?
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});

View File

@@ -1,6 +1,6 @@
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts';
import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs';
@@ -84,7 +84,6 @@ export const curlyBraceLeft = async (parent: SVGAElement, node: Node) => {
{ x: w / 2, y: h / 2 + radius },
];
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, { fill: 'none' });

View File

@@ -1,6 +1,6 @@
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts';
import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs';
@@ -87,7 +87,6 @@ export const curlyBraceRight = async (parent: SVGAElement, node: Node) => {
{ x: -w / 2, y: h / 2 + radius },
];
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, { fill: 'none' });

View File

@@ -1,6 +1,6 @@
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts';
import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs';
@@ -101,7 +101,6 @@ export const curlyBraces = async (parent: SVGAElement, node: Node) => {
...generateCirclePoints(-w / 2 + radius + radius / 2, h / 2, radius, 30, -180, -270),
];
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, { fill: 'transparent' });

View File

@@ -6,7 +6,7 @@ import {
generateCirclePoints,
} from './util.js';
import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts';
import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs';
@@ -39,7 +39,6 @@ export const curvedTrapezoid = async (parent: SVGAElement, node: Node) => {
const radius = h / 2;
const { cssStyles } = node;
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});

View File

@@ -89,7 +89,6 @@ export const cylinder = async (parent: SVGAElement, node: Node) => {
const { cssStyles } = node;
if (node.look === 'handDrawn' || (node.look === 'neo' && !useGradient)) {
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const outerPathData = createOuterCylinderPathD(0, 0, w, h, rx, ry);
const innerPathData = createInnerCylinderPathD(0, ry, w, h, rx, ry);

View File

@@ -1,6 +1,6 @@
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts';
import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs';
@@ -34,7 +34,6 @@ export const dividedRectangle = async (parent: SVGAElement, node: Node) => {
const { cssStyles } = node;
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== 'handDrawn') {

View File

@@ -1,6 +1,6 @@
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts';
import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs';
@@ -61,7 +61,6 @@ export const cylinder = async (parent: SVGAElement, node: Node) => {
const { cssStyles } = node;
if (node.look === 'handDrawn') {
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const outerPathData = createOuterCylinderPathD(0, 0, w, h, rx, ry);
const innerPathData = createInnerCylinderPathD(0, ry, w, h, rx, ry);

View File

@@ -30,7 +30,6 @@ export const doublecircle = async (parent: SVGAElement, node: Node): Promise<SVG
const { cssStyles } = node;
if (node.look === 'handDrawn') {
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const outerOptions = userNodeOverrides(node, { roughness: 0.2, strokeWidth: 2.5 });

View File

@@ -1,7 +1,7 @@
import rough from 'roughjs';
import type { SVG } from '../../../diagram-api/types.js';
import { log } from '../../../logger.js';
import type { Node, RenderOptions } from '../../types.d.ts';
import type { Node, ShapeRenderOptions } from '../../types.ts';
import intersect from '../intersect/index.js';
import { userNodeOverrides } from './handDrawnShapeStyles.js';
import { getNodeClasses, updateNodeBounds } from './util.js';
@@ -9,7 +9,7 @@ import { getNodeClasses, updateNodeBounds } from './util.js';
export const filledCircle = (
parent: SVG,
node: Node,
{ config: { themeVariables } }: RenderOptions
{ config: { themeVariables } }: ShapeRenderOptions
) => {
node.label = '';
@@ -42,7 +42,7 @@ export const filledCircle = (
const radius = (node.width ?? 0) / 2;
const { cssStyles } = node;
// @ts-ignore - rough is not typed
// @ts-expect-error shapeSvg d3 class is incorrect?
const rc = rough.svg(shapeSvg);
const { nodeBorder } = themeVariables;
const options = userNodeOverrides(node, { fillStyle: 'solid' });

View File

@@ -1,7 +1,7 @@
import { log } from '../../../logger.js';
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts';
import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs';
import { createPathFromPoints } from './util.js';
@@ -41,7 +41,6 @@ export const flippedTriangle = async (parent: SVGAElement, node: Node): Promise<
const { cssStyles } = node;
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== 'handDrawn') {

View File

@@ -1,14 +1,14 @@
import { getNodeClasses, updateNodeBounds } from './util.js';
import intersect from '../intersect/index.js';
import type { Node, RenderOptions } from '../../types.js';
import type { SVG } from '../../../diagram-api/types.js';
import rough from 'roughjs';
import type { SVG } from '../../../diagram-api/types.js';
import type { Node, ShapeRenderOptions } from '../../types.js';
import intersect from '../intersect/index.js';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import { getNodeClasses, updateNodeBounds } from './util.js';
export const forkJoin = (
parent: SVG,
node: Node,
{ dir, config: { state, themeVariables } }: RenderOptions
{ dir, config: { state, themeVariables } }: ShapeRenderOptions
) => {
const { nodeStyles } = styles2String(node);
node.label = '';

View File

@@ -7,7 +7,7 @@ import {
generateCirclePoints,
} from './util.js';
import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts';
import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs';
@@ -39,7 +39,6 @@ export const halfRoundedRectangle = async (parent: SVGAElement, node: Node) => {
const radius = h / 2;
const { cssStyles } = node;
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});

View File

@@ -57,7 +57,6 @@ export const hexagon = async (parent: SVGAElement, node: Node): Promise<SVGAElem
const { cssStyles } = node;
if (node.look === 'handDrawn') {
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const pathData = createHexagonPathD(0, 0, w, h, m);

View File

@@ -1,9 +1,9 @@
import rough from 'roughjs';
import { log } from '../../../logger.js';
import type { Node } from '../../types.d.ts';
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
import intersect from '../intersect/index.js';
import type { Node } from '../../types.ts';
import { userNodeOverrides } from './handDrawnShapeStyles.js';
import { createPathFromPoints, getNodeClasses, labelHelper, updateNodeBounds } from './util.js';
export const hourglass = async (parent: SVGAElement, node: Node) => {
node.label = '';
@@ -13,7 +13,7 @@ export const hourglass = async (parent: SVGAElement, node: Node) => {
const h = node?.height ? node?.height : 30;
const { cssStyles } = node;
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});

View File

@@ -1,16 +1,16 @@
import { log } from '../../../logger.js';
import { labelHelper, updateNodeBounds } from './util.js';
import type { Node, RenderOptions } from '../../types.d.ts';
import type { SVG } from '../../../diagram-api/types.js';
import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs';
import intersect from '../intersect/index.js';
import type { SVG } from '../../../diagram-api/types.js';
import { log } from '../../../logger.js';
import { getIconSVG } from '../../icons.js';
import type { Node, ShapeRenderOptions } from '../../types.ts';
import intersect from '../intersect/index.js';
import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import { labelHelper, updateNodeBounds } from './util.js';
export const icon = async (
parent: SVG,
node: Node,
{ config: { themeVariables, flowchart } }: RenderOptions
{ config: { themeVariables, flowchart } }: ShapeRenderOptions
) => {
const { labelStyles } = styles2String(node);
node.labelStyle = labelStyles;
@@ -33,7 +33,6 @@ export const icon = async (
const labelPadding = node.label ? 8 : 0;
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, { stroke: 'none', fill: 'none' });
@@ -59,7 +58,11 @@ export const icon = async (
if (node.icon) {
iconElem.html(
`<g>${await getIconSVG(node.icon, { height: iconSize, width: iconSize, fallbackPrefix: '' })}</g>`
`<g>${await getIconSVG(node.icon, {
height: iconSize,
width: iconSize,
fallbackPrefix: '',
})}</g>`
);
const iconBBox = iconElem.node().getBBox();
const iconWidth = iconBBox.width;
@@ -68,7 +71,11 @@ export const icon = async (
const iconY = iconBBox.y;
iconElem.attr(
'transform',
`translate(${-iconWidth / 2 - iconX},${topLabel ? bbox.height / 2 + labelPadding / 2 - iconHeight / 2 - iconY : -bbox.height / 2 - labelPadding / 2 - iconHeight / 2 - iconY})`
`translate(${-iconWidth / 2 - iconX},${
topLabel
? bbox.height / 2 + labelPadding / 2 - iconHeight / 2 - iconY
: -bbox.height / 2 - labelPadding / 2 - iconHeight / 2 - iconY
})`
);
iconElem.selectAll('path').attr('fill', stylesMap.get('stroke') ?? nodeBorder);
iconElem.attr('class', 'icon');
@@ -76,12 +83,16 @@ export const icon = async (
label.attr(
'transform',
`translate(${-bbox.width / 2 - (bbox.x - (bbox.left ?? 0))},${topLabel ? -outerHeight / 2 : outerHeight / 2 - bbox.height})`
`translate(${-bbox.width / 2 - (bbox.x - (bbox.left ?? 0))},${
topLabel ? -outerHeight / 2 : outerHeight / 2 - bbox.height
})`
);
iconShape.attr(
'transform',
`translate(${0},${topLabel ? bbox.height / 2 + labelPadding / 2 : -bbox.height / 2 - labelPadding / 2})`
`translate(${0},${
topLabel ? bbox.height / 2 + labelPadding / 2 : -bbox.height / 2 - labelPadding / 2
})`
);
if (stylesMap.get('stroke')) {

View File

@@ -1,16 +1,16 @@
import { log } from '../../../logger.js';
import { labelHelper, updateNodeBounds } from './util.js';
import type { Node, RenderOptions } from '../../types.d.ts';
import type { SVG } from '../../../diagram-api/types.js';
import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs';
import intersect from '../intersect/index.js';
import type { SVG } from '../../../diagram-api/types.js';
import { log } from '../../../logger.js';
import { getIconSVG } from '../../icons.js';
import type { Node, ShapeRenderOptions } from '../../types.ts';
import intersect from '../intersect/index.js';
import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import { labelHelper, updateNodeBounds } from './util.js';
export const iconCircle = async (
parent: SVG,
node: Node,
{ config: { themeVariables, flowchart } }: RenderOptions
{ config: { themeVariables, flowchart } }: ShapeRenderOptions
) => {
const { labelStyles } = styles2String(node);
node.labelStyle = labelStyles;
@@ -26,11 +26,11 @@ export const iconCircle = async (
const topLabel = node.pos === 't';
const { nodeBorder, mainBkg } = themeVariables;
const { nodeBorder } = themeVariables;
const { stylesMap } = compileStyles(node);
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, { stroke: stylesMap.get('fill') ?? mainBkg });
const options = userNodeOverrides(node, { stroke: 'transparent' });
// const options = userNodeOverrides(node, { stroke: stylesMap.get('fill') ?? mainBkg });
if (node.look !== 'handDrawn') {
options.roughness = 0;
@@ -40,7 +40,11 @@ export const iconCircle = async (
const iconElem = shapeSvg.append('g');
if (node.icon) {
iconElem.html(
`<g>${await getIconSVG(node.icon, { height: iconSize, width: iconSize, fallbackPrefix: '' })}</g>`
`<g>${await getIconSVG(node.icon, {
height: iconSize,
width: iconSize,
fallbackPrefix: '',
})}</g>`
);
}
const iconBBox = iconElem.node().getBBox();

View File

@@ -1,17 +1,17 @@
import { log } from '../../../logger.js';
import { labelHelper, updateNodeBounds } from './util.js';
import type { Node, RenderOptions } from '../../types.d.ts';
import type { SVG } from '../../../diagram-api/types.js';
import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs';
import intersect from '../intersect/index.js';
import type { SVG } from '../../../diagram-api/types.js';
import { log } from '../../../logger.js';
import { getIconSVG } from '../../icons.js';
import type { Node, ShapeRenderOptions } from '../../types.ts';
import intersect from '../intersect/index.js';
import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import { createRoundedRectPathD } from './roundedRectPath.js';
import { labelHelper, updateNodeBounds } from './util.js';
export const iconRounded = async (
parent: SVG,
node: Node,
{ config: { themeVariables, flowchart } }: RenderOptions
{ config: { themeVariables, flowchart } }: ShapeRenderOptions
) => {
const { labelStyles } = styles2String(node);
node.labelStyle = labelStyles;
@@ -51,7 +51,6 @@ export const iconRounded = async (
const x = -width / 2;
const y = -height / 2;
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, { stroke: stylesMap.get('fill') ?? mainBkg });

View File

@@ -1,16 +1,16 @@
import { log } from '../../../logger.js';
import { labelHelper, updateNodeBounds } from './util.js';
import type { Node, RenderOptions } from '../../types.d.ts';
import type { SVG } from '../../../diagram-api/types.js';
import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs';
import intersect from '../intersect/index.js';
import type { SVG } from '../../../diagram-api/types.js';
import { log } from '../../../logger.js';
import { getIconSVG } from '../../icons.js';
import type { Node, ShapeRenderOptions } from '../../types.ts';
import intersect from '../intersect/index.js';
import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import { labelHelper, updateNodeBounds } from './util.js';
export const iconSquare = async (
parent: SVG,
node: Node,
{ config: { themeVariables, flowchart } }: RenderOptions
{ config: { themeVariables, flowchart } }: ShapeRenderOptions
) => {
const { labelStyles } = styles2String(node);
node.labelStyle = labelStyles;
@@ -54,7 +54,6 @@ export const iconSquare = async (
const x = -width / 2;
const y = -height / 2;
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, { stroke: stylesMap.get('fill') ?? mainBkg });

View File

@@ -1,15 +1,14 @@
import { log } from '../../../logger.js';
import { labelHelper, updateNodeBounds } from './util.js';
import type { Node, RenderOptions } from '../../types.d.ts';
import type { SVG } from '../../../diagram-api/types.js';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
// import rough from 'roughjs';
import { log } from '../../../logger.js';
import type { Node, ShapeRenderOptions } from '../../types.ts';
import intersect from '../intersect/index.js';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import { labelHelper, updateNodeBounds } from './util.js';
export const imageSquare = async (
parent: SVG,
node: Node,
{ config: { flowchart } }: RenderOptions
{ config: { flowchart } }: ShapeRenderOptions
) => {
const img = new Image();
img.src = node?.img ?? '';
@@ -69,7 +68,6 @@ export const imageSquare = async (
// const x = -imageWidth / 2;
// const y = -imageHeight / 2;
// @ts-ignore - rough is not typed
// const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});

View File

@@ -55,7 +55,6 @@ export const inv_trapezoid = async (parent: SVGAElement, node: Node): Promise<SV
const { cssStyles } = node;
if (node.look === 'handDrawn') {
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const pathData = createPathFromPoints(points);

View File

@@ -40,7 +40,6 @@ export const lean_left = async (parent: SVGAElement, node: Node): Promise<SVGAEl
const { cssStyles } = node;
if (node.look === 'handDrawn') {
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const pathData = createPathFromPoints(points);

View File

@@ -42,7 +42,6 @@ export const lean_right = async (parent: SVGAElement, node: Node): Promise<SVGAE
const { cssStyles } = node;
if (node.look === 'handDrawn') {
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const pathData = createPathFromPoints(points);

View File

@@ -28,7 +28,7 @@ export const lightningBolt = (parent: SVG, node: Node) => {
{ x: 4 * gapX, y: height / 2 - gapY / 2 },
];
// @ts-ignore - rough is not typed
// @ts-expect-error shapeSvg d3 class is incorrect?
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});

View File

@@ -93,7 +93,6 @@ export const linedCylinder = async (parent: SVGAElement, node: Node) => {
const { cssStyles } = node;
if (node.look === 'handDrawn') {
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const outerPathData = createOuterCylinderPathD(0, 0, w, h, rx, ry, outerOffset);
const innerPathData = createInnerCylinderPathD(0, ry, w, h, rx, ry);

View File

@@ -5,7 +5,7 @@ import {
generateFullSineWavePoints,
} from './util.js';
import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts';
import type { Node } from '../../types.ts';
import rough from 'roughjs';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
@@ -37,7 +37,6 @@ export const linedWaveEdgedRect = async (parent: SVGAElement, node: Node) => {
const finalH = h + waveAmplitude;
const { cssStyles } = node;
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});

View File

@@ -1,5 +1,5 @@
import { labelHelper, getNodeClasses, updateNodeBounds, createPathFromPoints } from './util.js';
import type { Node } from '../../types.d.ts';
import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs';
import intersect from '../intersect/index.js';
@@ -34,7 +34,6 @@ export const multiRect = async (parent: SVGAElement, node: Node) => {
const y = -h / 2;
const { cssStyles } = node;
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});

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