├── docs ├── public │ ├── .nojekyll │ ├── favicon.ico │ ├── favicon.png │ ├── header.png │ ├── manifest.json │ ├── icons │ │ ├── folder.svg │ │ ├── terminal.svg │ │ ├── open-source.svg │ │ ├── public.svg │ │ ├── group.svg │ │ ├── comment.svg │ │ ├── presentation.svg │ │ └── whiteboard.svg │ └── mermaid-logo-horizontal.svg ├── img │ └── er.png ├── community │ └── img │ │ └── er.png ├── config │ ├── img │ │ ├── wrapped text.png │ │ ├── assignWithDepth.png │ │ ├── mathMLDifferences.png │ │ ├── accessibility-div-example.png │ │ ├── accessibility-div-example-2.png │ │ └── object.assign without depth.png │ ├── mermaidCLI.md │ └── setup │ │ ├── README.md │ │ ├── defaultConfig │ │ ├── README.md │ │ └── variables │ │ │ ├── configKeys.md │ │ │ └── default.md │ │ ├── mermaid │ │ ├── variables │ │ │ └── default.md │ │ ├── type-aliases │ │ │ ├── InternalHelpers.md │ │ │ ├── SVG.md │ │ │ ├── SVGGroup.md │ │ │ └── ParseErrorFunction.md │ │ └── interfaces │ │ │ ├── RenderOptions.md │ │ │ └── ParseOptions.md │ │ └── config │ │ ├── variables │ │ └── defaultConfig.md │ │ ├── functions │ │ ├── getUserDefinedConfig.md │ │ ├── saveConfigFromInitialize.md │ │ ├── addDirective.md │ │ ├── updateSiteConfig.md │ │ └── updateCurrentConfig.md │ │ └── README.md ├── intro │ └── img │ │ ├── Code-Preview-Config.png │ │ ├── Live-Editor-Choices.png │ │ └── book-banner-post-release.jpg ├── syntax │ └── img │ │ ├── Gantt-long-weekend-look.png │ │ ├── Gantt-excluded-days-within.png │ │ └── zenuml-participant-annotators.png └── ecosystem │ └── img │ ├── python-mermaid-integration.png │ └── python-mermaid-integration-updated.png ├── .node-version ├── .gitattributes ├── CHANGELOG.md ├── packages ├── mermaid │ ├── src │ │ ├── docs │ │ │ ├── public │ │ │ │ ├── .nojekyll │ │ │ │ ├── favicon.ico │ │ │ │ ├── favicon.png │ │ │ │ ├── header.png │ │ │ │ ├── manifest.json │ │ │ │ ├── icons │ │ │ │ │ ├── folder.svg │ │ │ │ │ ├── terminal.svg │ │ │ │ │ ├── open-source.svg │ │ │ │ │ ├── public.svg │ │ │ │ │ ├── group.svg │ │ │ │ │ ├── comment.svg │ │ │ │ │ └── presentation.svg │ │ │ │ └── mermaid-logo-horizontal.svg │ │ │ ├── img │ │ │ │ └── er.png │ │ │ ├── landing │ │ │ │ ├── er.png │ │ │ │ ├── class.png │ │ │ │ ├── cover.jpg │ │ │ │ ├── gantt.png │ │ │ │ ├── state.png │ │ │ │ ├── flowchart.png │ │ │ │ └── sequence-diagram.png │ │ │ ├── community │ │ │ │ └── img │ │ │ │ │ └── er.png │ │ │ ├── config │ │ │ │ ├── img │ │ │ │ │ ├── wrapped text.png │ │ │ │ │ ├── assignWithDepth.png │ │ │ │ │ ├── mathMLDifferences.png │ │ │ │ │ ├── accessibility-div-example.png │ │ │ │ │ ├── accessibility-div-example-2.png │ │ │ │ │ └── object.assign without depth.png │ │ │ │ ├── mermaidCLI.md │ │ │ │ └── layouts.md │ │ │ ├── intro │ │ │ │ └── img │ │ │ │ │ ├── Code-Preview-Config.png │ │ │ │ │ ├── Live-Editor-Choices.png │ │ │ │ │ └── book-banner-post-release.jpg │ │ │ ├── syntax │ │ │ │ ├── img │ │ │ │ │ ├── Gantt-long-weekend-look.png │ │ │ │ │ ├── Gantt-excluded-days-within.png │ │ │ │ │ └── zenuml-participant-annotators.png │ │ │ │ └── userJourney.md │ │ │ ├── ecosystem │ │ │ │ └── img │ │ │ │ │ ├── python-mermaid-integration.png │ │ │ │ │ └── python-mermaid-integration-updated.png │ │ │ ├── tsconfig.json │ │ │ └── .vitepress │ │ │ │ ├── components │ │ │ │ ├── Contributors.vue │ │ │ │ └── HomePage.vue │ │ │ │ └── theme │ │ │ │ ├── custom.css │ │ │ │ └── mermaid.ts │ │ ├── diagrams │ │ │ ├── kanban │ │ │ │ ├── kanbanTypes.ts │ │ │ │ ├── kanban-definition.ts │ │ │ │ └── detector.ts │ │ │ ├── sankey │ │ │ │ ├── styles.js │ │ │ │ ├── sankeyUtils.ts │ │ │ │ ├── sankeyDetector.ts │ │ │ │ └── sankeyDiagram.ts │ │ │ ├── c4 │ │ │ │ ├── styles.js │ │ │ │ ├── c4Diagram.ts │ │ │ │ └── c4Detector.ts │ │ │ ├── info │ │ │ │ ├── infoTypes.ts │ │ │ │ ├── infoDiagram.ts │ │ │ │ ├── infoDb.ts │ │ │ │ ├── infoParser.ts │ │ │ │ └── infoDetector.ts │ │ │ ├── block │ │ │ │ ├── blockUtils.ts │ │ │ │ ├── blockDiagram.ts │ │ │ │ ├── blockDetector.ts │ │ │ │ └── layout.spec.ts │ │ │ ├── error │ │ │ │ └── errorDiagram.ts │ │ │ ├── timeline │ │ │ │ ├── timeline-definition.ts │ │ │ │ └── detector.ts │ │ │ ├── radar │ │ │ │ ├── diagram.ts │ │ │ │ ├── detector.ts │ │ │ │ └── parser.ts │ │ │ ├── pie │ │ │ │ ├── pieDiagram.ts │ │ │ │ ├── pieDetector.ts │ │ │ │ └── pieParser.ts │ │ │ ├── xychart │ │ │ │ ├── xychartDiagram.ts │ │ │ │ ├── xychartDetector.ts │ │ │ │ └── chartBuilder │ │ │ │ │ └── index.ts │ │ │ ├── er │ │ │ │ ├── erRenderer.spec.ts │ │ │ │ ├── erDiagram.ts │ │ │ │ ├── erDetector.ts │ │ │ │ └── erTypes.ts │ │ │ ├── globalStyles.ts │ │ │ ├── quadrant-chart │ │ │ │ ├── quadrantDiagram.ts │ │ │ │ ├── quadrantDetector.ts │ │ │ │ └── utils.ts │ │ │ ├── packet │ │ │ │ ├── diagram.ts │ │ │ │ └── detector.ts │ │ │ ├── treemap │ │ │ │ ├── diagram.ts │ │ │ │ └── detector.ts │ │ │ ├── common │ │ │ │ ├── populateCommonDb.ts │ │ │ │ └── commonDb.ts │ │ │ ├── flowchart │ │ │ │ ├── parser │ │ │ │ │ └── flowParser.ts │ │ │ │ ├── flowDetector.ts │ │ │ │ ├── elk │ │ │ │ │ └── detector.ts │ │ │ │ └── flowDiagram.ts │ │ │ ├── git │ │ │ │ ├── gitGraphDiagram.ts │ │ │ │ ├── gitGraphDetector.ts │ │ │ │ └── parser │ │ │ │ │ └── desired syntax │ │ │ ├── gantt │ │ │ │ ├── ganttDiagram.ts │ │ │ │ └── ganttDetector.ts │ │ │ ├── architecture │ │ │ │ ├── architectureDiagram.ts │ │ │ │ └── architectureDetector.ts │ │ │ ├── mindmap │ │ │ │ ├── mindmap-definition.ts │ │ │ │ ├── mindmapTypes.ts │ │ │ │ └── detector.ts │ │ │ ├── requirement │ │ │ │ ├── requirementDiagram.ts │ │ │ │ └── requirementDetector.ts │ │ │ ├── user-journey │ │ │ │ ├── journeyDiagram.ts │ │ │ │ └── journeyDetector.ts │ │ │ ├── sequence │ │ │ │ ├── sequenceDetector.ts │ │ │ │ └── sequenceDiagram.ts │ │ │ ├── state │ │ │ │ ├── stateDiagram.ts │ │ │ │ ├── stateDiagram-v2.ts │ │ │ │ ├── stateDetector-V2.ts │ │ │ │ └── stateDetector.ts │ │ │ └── class │ │ │ │ ├── classDiagram.ts │ │ │ │ ├── classDiagram-v2.ts │ │ │ │ ├── svgDraw.spec.js │ │ │ │ ├── classDetector.ts │ │ │ │ ├── parser │ │ │ │ └── class.spec.js │ │ │ │ └── classDetector-V2.ts │ │ ├── type.d.ts │ │ ├── types │ │ │ └── cytoscape-cose-bilkent.d.ts │ │ ├── errors.ts │ │ ├── rendering-util │ │ │ ├── rendering-elements │ │ │ │ ├── intersect │ │ │ │ │ ├── intersect-node.js │ │ │ │ │ ├── intersect-circle.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── intersect-ellipse.js │ │ │ │ │ └── intersect-rect.js │ │ │ │ └── shapes │ │ │ │ │ ├── state.ts │ │ │ │ │ ├── mindmapCircle.ts │ │ │ │ │ ├── squareRect.ts │ │ │ │ │ └── insertPolygonShape.ts │ │ │ ├── uid.ts │ │ │ ├── insertElementsForSize.js │ │ │ └── selectSvgElement.ts │ │ ├── themes │ │ │ ├── theme-helpers.js │ │ │ ├── erDiagram-oldHardcodedValues.ts │ │ │ └── index.js │ │ ├── dagre-wrapper │ │ │ └── intersect │ │ │ │ ├── intersect-node.js │ │ │ │ ├── intersect-circle.js │ │ │ │ ├── index.js │ │ │ │ ├── intersect-ellipse.js │ │ │ │ └── intersect-rect.js │ │ ├── interactionDb.ts │ │ ├── utils │ │ │ ├── base64.ts │ │ │ ├── subGraphTitleMargins.spec.ts │ │ │ ├── subGraphTitleMargins.ts │ │ │ └── imperativeState.ts │ │ ├── diagram-api │ │ │ ├── comments.ts │ │ │ └── regexes.ts │ │ ├── setupGraphViewbox.spec.js │ │ └── __mocks__ │ │ │ └── mermaidAPI.ts │ ├── scripts │ │ ├── docs.cli.mts │ │ └── loadHook.mjs │ ├── .gitignore │ ├── tsconfig.eslint.json │ ├── typedoc.json │ ├── .madgerc │ ├── tsconfig.json │ └── .lintstagedrc.mjs ├── parser │ ├── src │ │ ├── language │ │ │ ├── info │ │ │ │ ├── index.ts │ │ │ │ ├── info.langium │ │ │ │ └── tokenBuilder.ts │ │ │ ├── packet │ │ │ │ ├── index.ts │ │ │ │ ├── tokenBuilder.ts │ │ │ │ └── packet.langium │ │ │ ├── pie │ │ │ │ ├── index.ts │ │ │ │ ├── tokenBuilder.ts │ │ │ │ ├── pie.langium │ │ │ │ └── valueConverter.ts │ │ │ ├── radar │ │ │ │ ├── index.ts │ │ │ │ └── tokenBuilder.ts │ │ │ ├── treemap │ │ │ │ ├── index.ts │ │ │ │ └── tokenBuilder.ts │ │ │ ├── architecture │ │ │ │ ├── index.ts │ │ │ │ ├── arch.langium │ │ │ │ ├── tokenBuilder.ts │ │ │ │ └── valueConverter.ts │ │ │ ├── gitGraph │ │ │ │ ├── index.ts │ │ │ │ ├── reference.langium │ │ │ │ └── tokenBuilder.ts │ │ │ └── common │ │ │ │ ├── index.ts │ │ │ │ └── matcher.ts │ │ └── index.ts │ ├── tsconfig.json │ └── tests │ │ └── packet.test.ts ├── mermaid-example-diagram │ ├── src │ │ ├── types │ │ │ └── index.d.ts │ │ ├── diagram-definition.ts │ │ ├── detector.ts │ │ ├── styles.js │ │ ├── exampleDiagramDb.js │ │ ├── exampleDiagram.spec.js │ │ └── parser │ │ │ └── exampleDiagram.jison │ ├── tsconfig.json │ └── tsconfig.eslint.json ├── mermaid-zenuml │ ├── tsconfig.json │ └── src │ │ ├── zenuml.d.ts │ │ ├── parser.ts │ │ ├── zenuml-definition.ts │ │ └── detector.ts ├── examples │ ├── src │ │ ├── types.ts │ │ └── examples │ │ │ ├── pie.ts │ │ │ ├── treemap.ts │ │ │ ├── state.ts │ │ │ ├── flowchart.ts │ │ │ ├── timeline.ts │ │ │ ├── sequence.ts │ │ │ ├── user-journey.ts │ │ │ ├── radar.ts │ │ │ ├── gantt.ts │ │ │ ├── block.ts │ │ │ ├── git.ts │ │ │ ├── requirement.ts │ │ │ ├── architecture.ts │ │ │ ├── xychart.ts │ │ │ ├── packet.ts │ │ │ ├── class.ts │ │ │ ├── mindmap.ts │ │ │ ├── quadrant-chart.ts │ │ │ └── er.ts │ ├── tsconfig.json │ └── package.json ├── mermaid-layout-elk │ ├── src │ │ ├── find-common-ancestor.d.ts │ │ ├── layouts.ts │ │ └── find-common-ancestor.ts │ └── tsconfig.json ├── mermaid-layout-tidy-tree │ ├── tsconfig.json │ ├── src │ │ ├── layouts.ts │ │ └── non-layered-tidy-tree-layout.d.ts │ └── CHANGELOG.md └── tiny │ └── package.json ├── CONTRIBUTING.md ├── cypress ├── support │ ├── eyes-index.d.ts │ └── e2e.js ├── platform │ ├── xss.png │ ├── exploit.js │ ├── empty.html │ ├── xss22.html │ ├── e2e.html │ ├── iife.html │ ├── flow-elk.html │ ├── render-after-error.html │ ├── regression │ │ └── issue-1874.html │ └── ghsa2.html ├── fixtures │ └── example.json ├── .eslintrc.json ├── tsconfig.json └── integration │ ├── rendering │ ├── info.spec.ts │ ├── marker_unique_id.spec.js │ ├── zenuml.spec.js │ ├── current.spec.js │ └── flowchart-icon.spec.js │ └── other │ ├── iife.spec.js │ ├── external-diagrams.spec.js │ ├── rerender.spec.js │ └── ghsa.spec.js ├── .hadolint.yaml ├── img ├── header.png ├── gray-pie.png ├── gray-class.png ├── gray-flow.png ├── gray-gantt.png ├── gray-state.png ├── gray-journey.png ├── gray-sequence.png ├── GitHub-Mark-32px.png └── gray-user-journey.png ├── .github ├── codeql │ └── codeql-config.yml ├── workflows │ ├── unlock-reopened-issues.yml │ ├── issue-triage.yml │ └── update-browserlist.yml ├── codecov.yaml ├── pr-labeler.yml ├── FUNDING.yml ├── ISSUE_TEMPLATE │ └── config.yml └── stale.yml ├── .husky └── pre-commit ├── .changeset ├── slow-lemons-know.md ├── brave-memes-flash.md ├── chilly-words-march.md ├── short-seals-sort.md ├── ten-plums-bet.md ├── brave-baths-behave.md ├── lazy-brooms-battle.md ├── loud-results-melt.md ├── wide-lines-trade.md ├── curly-apes-prove.md ├── busy-mirrors-try.md ├── sweet-games-build.md ├── tricky-rivers-stand.md ├── chatty-insects-dream.md ├── config.json └── README.md ├── .cspell ├── misc-terms.txt ├── contributors.txt └── mermaid-terms.txt ├── .ackrc ├── FUNDING.json ├── .npmrc ├── pnpm-workspace.yaml ├── .prettierrc.json ├── vitest.workspace.js ├── .vscode └── extensions.json ├── .build ├── generateLangium.ts ├── jisonTransformer.ts └── types.ts ├── .editorconfig ├── tests └── webpack │ ├── public │ └── index.html │ ├── webpack.config.js │ └── package.json ├── Dockerfile ├── patches └── roughjs.patch ├── .vite ├── jisonPlugin.ts └── jsonSchemaPlugin.ts ├── .lintstagedrc.mjs ├── .esbuild └── jisonPlugin.ts ├── .prettierignore ├── tsconfig.eslint.json ├── CITATION.cff ├── scripts └── coverage.ts ├── demos ├── dev │ └── reload.js └── info.html ├── netlify.toml ├── docker-compose.yml └── .gitignore /docs/public/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 22.14.0 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ./packages/mermaid/CHANGELOG.md -------------------------------------------------------------------------------- /packages/mermaid/src/docs/public/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ./packages/mermaid/src/docs/community/contributing.md -------------------------------------------------------------------------------- /cypress/support/eyes-index.d.ts: -------------------------------------------------------------------------------- 1 | import '@applitools/eyes-cypress'; 2 | -------------------------------------------------------------------------------- /packages/parser/src/language/info/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module.js'; 2 | -------------------------------------------------------------------------------- /packages/parser/src/language/packet/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module.js'; 2 | -------------------------------------------------------------------------------- /packages/parser/src/language/pie/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module.js'; 2 | -------------------------------------------------------------------------------- /packages/parser/src/language/radar/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module.js'; 2 | -------------------------------------------------------------------------------- /packages/parser/src/language/treemap/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module.js'; 2 | -------------------------------------------------------------------------------- /.hadolint.yaml: -------------------------------------------------------------------------------- 1 | ignored: 2 | - DL3002 # TODO: Last USER should not be root 3 | -------------------------------------------------------------------------------- /img/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/img/header.png -------------------------------------------------------------------------------- /packages/parser/src/language/architecture/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module.js'; 2 | -------------------------------------------------------------------------------- /packages/parser/src/language/gitGraph/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module.js'; 2 | -------------------------------------------------------------------------------- /docs/img/er.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/docs/img/er.png -------------------------------------------------------------------------------- /img/gray-pie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/img/gray-pie.png -------------------------------------------------------------------------------- /img/gray-class.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/img/gray-class.png -------------------------------------------------------------------------------- /img/gray-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/img/gray-flow.png -------------------------------------------------------------------------------- /img/gray-gantt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/img/gray-gantt.png -------------------------------------------------------------------------------- /img/gray-state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/img/gray-state.png -------------------------------------------------------------------------------- /img/gray-journey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/img/gray-journey.png -------------------------------------------------------------------------------- /img/gray-sequence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/img/gray-sequence.png -------------------------------------------------------------------------------- /cypress/platform/xss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/cypress/platform/xss.png -------------------------------------------------------------------------------- /docs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/docs/public/favicon.ico -------------------------------------------------------------------------------- /docs/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/docs/public/favicon.png -------------------------------------------------------------------------------- /docs/public/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/docs/public/header.png -------------------------------------------------------------------------------- /img/GitHub-Mark-32px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/img/GitHub-Mark-32px.png -------------------------------------------------------------------------------- /.github/codeql/codeql-config.yml: -------------------------------------------------------------------------------- 1 | name: 'CodeQL config' 2 | paths-ignore: 3 | - dist 4 | - cypress 5 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | NODE_OPTIONS="--max_old_space_size=8192" pnpm run pre-commit 3 | -------------------------------------------------------------------------------- /docs/community/img/er.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/docs/community/img/er.png -------------------------------------------------------------------------------- /img/gray-user-journey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/img/gray-user-journey.png -------------------------------------------------------------------------------- /.changeset/slow-lemons-know.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@mermaid': patch 3 | --- 4 | 5 | fix: Mindmap breaking in ELK layout 6 | -------------------------------------------------------------------------------- /packages/mermaid/scripts/docs.cli.mts: -------------------------------------------------------------------------------- 1 | import { processDocs } from './docs.mjs'; 2 | 3 | void processDocs(); 4 | -------------------------------------------------------------------------------- /.cspell/misc-terms.txt: -------------------------------------------------------------------------------- 1 | BRANDES 2 | Buzan 3 | circo 4 | handDrawn 5 | KOEPF 6 | neato 7 | newbranch 8 | validify 9 | -------------------------------------------------------------------------------- /docs/config/img/wrapped text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/docs/config/img/wrapped text.png -------------------------------------------------------------------------------- /.changeset/brave-memes-flash.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'mermaid': patch 3 | --- 4 | 5 | fix: Support edge animation in hand drawn look 6 | -------------------------------------------------------------------------------- /docs/config/img/assignWithDepth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/docs/config/img/assignWithDepth.png -------------------------------------------------------------------------------- /packages/mermaid/src/docs/img/er.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/img/er.png -------------------------------------------------------------------------------- /packages/parser/src/language/architecture/arch.langium: -------------------------------------------------------------------------------- 1 | terminal ARCH_ICON: /\([\w-:]+\)/; 2 | terminal ARCH_TITLE: /\[[\w ]+\]/; -------------------------------------------------------------------------------- /packages/parser/src/language/common/index.ts: -------------------------------------------------------------------------------- 1 | export * from './tokenBuilder.js'; 2 | export * from './valueConverter.js'; 3 | -------------------------------------------------------------------------------- /.changeset/chilly-words-march.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'mermaid': patch 3 | --- 4 | 5 | fix: Correct viewBox casing and make SVGs responsive 6 | -------------------------------------------------------------------------------- /.changeset/short-seals-sort.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'mermaid': minor 3 | --- 4 | 5 | feat: allow to put notes in namespaces on classDiagram 6 | -------------------------------------------------------------------------------- /.changeset/ten-plums-bet.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'mermaid': patch 3 | --- 4 | 5 | fix: Support ComponentQueue_Ext to prevent parsing error 6 | -------------------------------------------------------------------------------- /docs/config/img/mathMLDifferences.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/docs/config/img/mathMLDifferences.png -------------------------------------------------------------------------------- /docs/intro/img/Code-Preview-Config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/docs/intro/img/Code-Preview-Config.png -------------------------------------------------------------------------------- /docs/intro/img/Live-Editor-Choices.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/docs/intro/img/Live-Editor-Choices.png -------------------------------------------------------------------------------- /packages/mermaid/src/docs/landing/er.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/landing/er.png -------------------------------------------------------------------------------- /.ackrc: -------------------------------------------------------------------------------- 1 | --ignore-dir=dist 2 | --ignore-file=match:/^yarn\.lock$/ 3 | --ignore-file=match:/^yarn-error\.log$/ 4 | --ignore-dir=coverage 5 | -------------------------------------------------------------------------------- /docs/intro/img/book-banner-post-release.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/docs/intro/img/book-banner-post-release.jpg -------------------------------------------------------------------------------- /docs/syntax/img/Gantt-long-weekend-look.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/docs/syntax/img/Gantt-long-weekend-look.png -------------------------------------------------------------------------------- /packages/mermaid/src/docs/landing/class.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/landing/class.png -------------------------------------------------------------------------------- /packages/mermaid/src/docs/landing/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/landing/cover.jpg -------------------------------------------------------------------------------- /packages/mermaid/src/docs/landing/gantt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/landing/gantt.png -------------------------------------------------------------------------------- /packages/mermaid/src/docs/landing/state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/landing/state.png -------------------------------------------------------------------------------- /packages/mermaid/src/docs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/public/favicon.ico -------------------------------------------------------------------------------- /packages/mermaid/src/docs/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/public/favicon.png -------------------------------------------------------------------------------- /packages/mermaid/src/docs/public/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/public/header.png -------------------------------------------------------------------------------- /.changeset/brave-baths-behave.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'mermaid': patch 3 | --- 4 | 5 | fix: Prevent HTML tags from being escaped in sandbox label rendering 6 | -------------------------------------------------------------------------------- /FUNDING.json: -------------------------------------------------------------------------------- 1 | { 2 | "drips": { 3 | "ethereum": { 4 | "ownedBy": "0x0831DDFe60d009d9448CC976157b539089aB821E" 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /docs/config/img/accessibility-div-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/docs/config/img/accessibility-div-example.png -------------------------------------------------------------------------------- /docs/syntax/img/Gantt-excluded-days-within.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/docs/syntax/img/Gantt-excluded-days-within.png -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/kanban/kanbanTypes.ts: -------------------------------------------------------------------------------- 1 | import type kanbanDb from './kanbanDb.js'; 2 | 3 | export type KanbanDB = typeof kanbanDb; 4 | -------------------------------------------------------------------------------- /packages/mermaid/src/docs/community/img/er.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/community/img/er.png -------------------------------------------------------------------------------- /.changeset/lazy-brooms-battle.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'mermaid': patch 3 | --- 4 | 5 | feat: add alias support for new participant syntax of sequence diagrams 6 | -------------------------------------------------------------------------------- /.changeset/loud-results-melt.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'mermaid': minor 3 | --- 4 | 5 | feat: Add half-arrowheads (solid & stick) and central connection support 6 | -------------------------------------------------------------------------------- /.changeset/wide-lines-trade.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'mermaid': patch 3 | --- 4 | 5 | fix: Mindmap rendering issue when the number of Level 2 nodes exceeds 11 6 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry=https://registry.npmjs.org 2 | auto-install-peers=true 3 | strict-peer-dependencies=false 4 | package-import-method=clone-or-copy 5 | -------------------------------------------------------------------------------- /docs/config/img/accessibility-div-example-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/docs/config/img/accessibility-div-example-2.png -------------------------------------------------------------------------------- /docs/config/img/object.assign without depth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/docs/config/img/object.assign without depth.png -------------------------------------------------------------------------------- /docs/ecosystem/img/python-mermaid-integration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/docs/ecosystem/img/python-mermaid-integration.png -------------------------------------------------------------------------------- /docs/syntax/img/zenuml-participant-annotators.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/docs/syntax/img/zenuml-participant-annotators.png -------------------------------------------------------------------------------- /packages/mermaid/src/docs/landing/flowchart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/landing/flowchart.png -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'packages/*' 3 | - 'packages/mermaid/src/docs' 4 | - 'packages/mermaid/src/vitepress' 5 | - 'tests/*' 6 | -------------------------------------------------------------------------------- /.changeset/curly-apes-prove.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'mermaid': patch 3 | --- 4 | 5 | fix: Improve participant parsing and prevent recursive loops on invalid syntax 6 | -------------------------------------------------------------------------------- /.changeset/busy-mirrors-try.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'mermaid': patch 3 | --- 4 | 5 | fix: Resolved parsing error where direction TD was not recognized within subgraphs 6 | -------------------------------------------------------------------------------- /packages/mermaid/src/docs/config/img/wrapped text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/config/img/wrapped text.png -------------------------------------------------------------------------------- /packages/mermaid/src/docs/landing/sequence-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/landing/sequence-diagram.png -------------------------------------------------------------------------------- /.changeset/sweet-games-build.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'mermaid': patch 3 | --- 4 | 5 | fix(er-diagram): prevent syntax error when using 'u', numbers, and decimals in node names 6 | -------------------------------------------------------------------------------- /.changeset/tricky-rivers-stand.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'mermaid': patch 3 | --- 4 | 5 | fix: validate dates and tick interval to prevent UI freeze/crash in gantt diagramtype 6 | -------------------------------------------------------------------------------- /packages/mermaid/src/docs/config/img/assignWithDepth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/config/img/assignWithDepth.png -------------------------------------------------------------------------------- /packages/mermaid/src/type.d.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line no-var 2 | declare var injected: { 3 | version: string; 4 | includeLargeFeatures: boolean; 5 | }; 6 | -------------------------------------------------------------------------------- /.changeset/chatty-insects-dream.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'mermaid': patch 3 | --- 4 | 5 | fix(treemap): Fixed treemap classDef style application to properly apply user-defined styles 6 | -------------------------------------------------------------------------------- /docs/ecosystem/img/python-mermaid-integration-updated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/docs/ecosystem/img/python-mermaid-integration-updated.png -------------------------------------------------------------------------------- /packages/mermaid/src/docs/config/img/mathMLDifferences.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/config/img/mathMLDifferences.png -------------------------------------------------------------------------------- /packages/mermaid/src/docs/intro/img/Code-Preview-Config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/intro/img/Code-Preview-Config.png -------------------------------------------------------------------------------- /packages/mermaid/src/docs/intro/img/Live-Editor-Choices.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/intro/img/Live-Editor-Choices.png -------------------------------------------------------------------------------- /packages/mermaid/src/types/cytoscape-cose-bilkent.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'cytoscape-cose-bilkent' { 2 | const coseBilkent: any; 3 | export default coseBilkent; 4 | } 5 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "endOfLine": "auto", 3 | "printWidth": 100, 4 | "singleQuote": true, 5 | "useTabs": false, 6 | "tabWidth": 2, 7 | "trailingComma": "es5" 8 | } 9 | -------------------------------------------------------------------------------- /packages/mermaid/src/docs/intro/img/book-banner-post-release.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/intro/img/book-banner-post-release.jpg -------------------------------------------------------------------------------- /packages/mermaid/src/docs/syntax/img/Gantt-long-weekend-look.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/syntax/img/Gantt-long-weekend-look.png -------------------------------------------------------------------------------- /vitest.workspace.js: -------------------------------------------------------------------------------- 1 | import { defineWorkspace } from 'vitest/config'; 2 | 3 | export default defineWorkspace(['./vite.config.ts', './packages/mermaid/src/docs/vite.config.ts']); 4 | -------------------------------------------------------------------------------- /packages/mermaid-example-diagram/src/types/index.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | 3 | declare global { 4 | interface Window { 5 | mermaid: any; // 👈️ turn off type checking 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/mermaid/.gitignore: -------------------------------------------------------------------------------- 1 | src/vitepress 2 | src/docs/config/setup 3 | README.* 4 | src/docs/public/user-avatars/ 5 | src/docs/.vitepress/cache 6 | src/docs/.vitepress/components.d.ts 7 | -------------------------------------------------------------------------------- /packages/mermaid/src/docs/config/img/accessibility-div-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/config/img/accessibility-div-example.png -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "dbaeumer.vscode-eslint", 4 | "esbenp.prettier-vscode", 5 | "vitest.explorer", 6 | "luniclynx.bison" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/sankey/styles.js: -------------------------------------------------------------------------------- 1 | const getStyles = (options) => 2 | `.label { 3 | font-family: ${options.fontFamily}; 4 | }`; 5 | 6 | export default getStyles; 7 | -------------------------------------------------------------------------------- /packages/mermaid/src/docs/config/img/accessibility-div-example-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/config/img/accessibility-div-example-2.png -------------------------------------------------------------------------------- /packages/mermaid/src/docs/config/img/object.assign without depth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/config/img/object.assign without depth.png -------------------------------------------------------------------------------- /packages/mermaid/src/docs/syntax/img/Gantt-excluded-days-within.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/syntax/img/Gantt-excluded-days-within.png -------------------------------------------------------------------------------- /packages/mermaid/src/docs/ecosystem/img/python-mermaid-integration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/ecosystem/img/python-mermaid-integration.png -------------------------------------------------------------------------------- /packages/mermaid/src/docs/syntax/img/zenuml-participant-annotators.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/syntax/img/zenuml-participant-annotators.png -------------------------------------------------------------------------------- /.build/generateLangium.ts: -------------------------------------------------------------------------------- 1 | import { generate } from 'langium-cli'; 2 | 3 | export async function generateLangium() { 4 | await generate({ file: `./packages/parser/langium-config.json` }); 5 | } 6 | -------------------------------------------------------------------------------- /packages/mermaid/src/docs/config/mermaidCLI.md: -------------------------------------------------------------------------------- 1 | # mermaid CLI 2 | 3 | mermaid CLI has been moved to [mermaid-cli](https://github.com/mermaid-js/mermaid-cli). Please read its documentation instead. 4 | -------------------------------------------------------------------------------- /packages/mermaid/src/errors.ts: -------------------------------------------------------------------------------- 1 | export class UnknownDiagramError extends Error { 2 | constructor(message: string) { 3 | super(message); 4 | this.name = 'UnknownDiagramError'; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /cypress/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io", 4 | "body": "Fixtures are a great way to mock data for responses to routes" 5 | } 6 | -------------------------------------------------------------------------------- /packages/mermaid/src/rendering-util/rendering-elements/intersect/intersect-node.js: -------------------------------------------------------------------------------- 1 | function intersectNode(node, point) { 2 | return node.intersect(point); 3 | } 4 | 5 | export default intersectNode; 6 | -------------------------------------------------------------------------------- /packages/mermaid/src/docs/ecosystem/img/python-mermaid-integration-updated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code/app-mermaid/develop/packages/mermaid/src/docs/ecosystem/img/python-mermaid-integration-updated.png -------------------------------------------------------------------------------- /packages/mermaid/src/themes/theme-helpers.js: -------------------------------------------------------------------------------- 1 | import { adjust } from 'khroma'; 2 | 3 | export const mkBorder = (col, darkMode) => 4 | darkMode ? adjust(col, { s: -40, l: 10 }) : adjust(col, { s: -40, l: -10 }); 5 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/c4/styles.js: -------------------------------------------------------------------------------- 1 | const getStyles = (options) => 2 | `.person { 3 | stroke: ${options.personBorder}; 4 | fill: ${options.personBkg}; 5 | } 6 | `; 7 | 8 | export default getStyles; 9 | -------------------------------------------------------------------------------- /packages/parser/src/language/info/info.langium: -------------------------------------------------------------------------------- 1 | grammar Info 2 | import "../common/common"; 3 | 4 | entry Info: 5 | NEWLINE* 6 | "info" NEWLINE* 7 | ("showInfo" NEWLINE*)? 8 | TitleAndAccessibilities? 9 | ; 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | 10 | [*.md] 11 | indent_size = 4 12 | -------------------------------------------------------------------------------- /cypress/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "cypress/globals": true 4 | }, 5 | "extends": ["plugin:cypress/recommended"], 6 | "plugins": ["cypress"], 7 | "rules": { 8 | "cypress/no-unnecessary-waiting": 0 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.cspell/contributors.txt: -------------------------------------------------------------------------------- 1 | # Contributors to mermaidjs, one per line 2 | Ashish Jain 3 | cpettitt 4 | Dong Cai 5 | fourcube 6 | knsv 7 | Knut Sveidqvist 8 | Nikolay Rozhkov 9 | Peng Xiao 10 | Per Brolin 11 | Sidharth Vinod 12 | subhash-halder 13 | -------------------------------------------------------------------------------- /packages/mermaid-zenuml/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src/**/*.ts"], 8 | "typeRoots": ["./src/types"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/mermaid-example-diagram/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist" 6 | }, 7 | "include": ["./src/**/*.ts"], 8 | "typeRoots": ["./src/types"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/mermaid/src/docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": ["../../../../tsconfig.json"], 4 | "compilerOptions": { 5 | "noEmit": true 6 | }, 7 | "include": ["./**/*.ts", "./.vitepress/**/*.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/parser/src/language/packet/tokenBuilder.ts: -------------------------------------------------------------------------------- 1 | import { AbstractMermaidTokenBuilder } from '../common/index.js'; 2 | 3 | export class PacketTokenBuilder extends AbstractMermaidTokenBuilder { 4 | public constructor() { 5 | super(['packet']); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/parser/src/language/pie/tokenBuilder.ts: -------------------------------------------------------------------------------- 1 | import { AbstractMermaidTokenBuilder } from '../common/index.js'; 2 | 3 | export class PieTokenBuilder extends AbstractMermaidTokenBuilder { 4 | public constructor() { 5 | super(['pie', 'showData']); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/parser/src/language/radar/tokenBuilder.ts: -------------------------------------------------------------------------------- 1 | import { AbstractMermaidTokenBuilder } from '../common/index.js'; 2 | 3 | export class RadarTokenBuilder extends AbstractMermaidTokenBuilder { 4 | public constructor() { 5 | super(['radar-beta']); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/parser/src/language/treemap/tokenBuilder.ts: -------------------------------------------------------------------------------- 1 | import { AbstractMermaidTokenBuilder } from '../common/index.js'; 2 | 3 | export class TreemapTokenBuilder extends AbstractMermaidTokenBuilder { 4 | public constructor() { 5 | super(['treemap']); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/parser/src/language/gitGraph/reference.langium: -------------------------------------------------------------------------------- 1 | // Alphanumerics with underscores, dashes, slashes, and dots 2 | // Must start with an alphanumeric or an underscore 3 | // Cant end with a dash, slash, or dot 4 | terminal REFERENCE returns string: /\w([-\./\w]*[-\w])?/; -------------------------------------------------------------------------------- /packages/parser/src/language/gitGraph/tokenBuilder.ts: -------------------------------------------------------------------------------- 1 | import { AbstractMermaidTokenBuilder } from '../common/index.js'; 2 | 3 | export class GitGraphTokenBuilder extends AbstractMermaidTokenBuilder { 4 | public constructor() { 5 | super(['gitGraph']); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/parser/src/language/info/tokenBuilder.ts: -------------------------------------------------------------------------------- 1 | import { AbstractMermaidTokenBuilder } from '../common/index.js'; 2 | 3 | export class InfoTokenBuilder extends AbstractMermaidTokenBuilder { 4 | public constructor() { 5 | super(['info', 'showInfo']); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/info/infoTypes.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramDB } from '../../diagram-api/types.js'; 2 | 3 | export interface InfoFields { 4 | version: string; 5 | } 6 | 7 | export interface InfoDB extends DiagramDB { 8 | getVersion: () => string; 9 | } 10 | -------------------------------------------------------------------------------- /cypress/platform/exploit.js: -------------------------------------------------------------------------------- 1 | const div = parent.document.createElement('div'); 2 | div.id = 'the-malware'; 3 | div.className = 'malware'; 4 | div.innerHTML = 'XSS Succeeded'; 5 | parent.document.getElementsByTagName('body')[0].appendChild(div); 6 | throw new Error('XSS Succeeded'); 7 | -------------------------------------------------------------------------------- /packages/parser/src/language/architecture/tokenBuilder.ts: -------------------------------------------------------------------------------- 1 | import { AbstractMermaidTokenBuilder } from '../common/index.js'; 2 | 3 | export class ArchitectureTokenBuilder extends AbstractMermaidTokenBuilder { 4 | public constructor() { 5 | super(['architecture']); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tests/webpack/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Getting Started 6 | 7 | 8 |
9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /packages/examples/src/types.ts: -------------------------------------------------------------------------------- 1 | export interface Example { 2 | title: string; 3 | code: string; 4 | isDefault?: boolean; 5 | } 6 | 7 | export interface DiagramMetadata { 8 | id: string; 9 | name: string; 10 | description: string; 11 | examples: Example[]; 12 | } 13 | -------------------------------------------------------------------------------- /packages/mermaid/src/dagre-wrapper/intersect/intersect-node.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param node 3 | * @param point 4 | */ 5 | function intersectNode(node, point) { 6 | // console.info('Intersect Node'); 7 | return node.intersect(point); 8 | } 9 | 10 | export default intersectNode; 11 | -------------------------------------------------------------------------------- /packages/mermaid/src/rendering-util/rendering-elements/intersect/intersect-circle.js: -------------------------------------------------------------------------------- 1 | import intersectEllipse from './intersect-ellipse.js'; 2 | 3 | function intersectCircle(node, rx, point) { 4 | return intersectEllipse(node, rx, rx, point); 5 | } 6 | 7 | export default intersectCircle; 8 | -------------------------------------------------------------------------------- /cypress/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "lib": ["es2020", "dom"], 5 | "types": ["cypress", "node", "@argos-ci/cypress/support"], 6 | "allowImportingTsExtensions": true, 7 | "noEmit": true 8 | }, 9 | "include": ["**/*.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /tests/webpack/webpack.config.js: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line @typescript-eslint/no-require-imports 2 | const path = require('path'); 3 | 4 | module.exports = { 5 | entry: './src/index.js', 6 | output: { 7 | filename: 'main.js', 8 | path: path.resolve(__dirname, 'dist'), 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /packages/examples/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "rootDir": "./src", 6 | "module": "Node16", 7 | "moduleResolution": "Node16" 8 | }, 9 | "include": ["src/**/*"], 10 | "exclude": ["node_modules", "dist"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/mermaid-layout-elk/src/find-common-ancestor.d.ts: -------------------------------------------------------------------------------- 1 | export interface TreeData { 2 | parentById: Record; 3 | childrenById: Record; 4 | } 5 | export declare const findCommonAncestor: ( 6 | id1: string, 7 | id2: string, 8 | { parentById }: TreeData 9 | ) => string; 10 | -------------------------------------------------------------------------------- /packages/mermaid-example-diagram/tsconfig.eslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": ["./tsconfig.json"], 4 | "compilerOptions": { 5 | "noEmit": true 6 | }, 7 | "include": [ 8 | "./src/**/*.spec.js", 9 | "./src/**/*.spec.ts" // test files 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /packages/mermaid-layout-elk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist", 6 | "types": ["vitest/importMeta", "vitest/globals"] 7 | }, 8 | "include": ["./src/**/*.ts", "./src/**/*.d.ts"], 9 | "typeRoots": ["./src/types"] 10 | } 11 | -------------------------------------------------------------------------------- /packages/mermaid-zenuml/src/zenuml.d.ts: -------------------------------------------------------------------------------- 1 | declare module '@zenuml/core' { 2 | interface RenderOptions { 3 | theme?: string; 4 | mode?: string; 5 | } 6 | 7 | export default class ZenUml { 8 | constructor(container: Element); 9 | render(text: string, options?: RenderOptions): Promise; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/parser/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "outDir": "./dist", 6 | "allowJs": false, 7 | "strictPropertyInitialization": false 8 | }, 9 | "include": ["./src/**/*.ts", "./tests/**/*.ts"], 10 | "typeRoots": ["./src/types"] 11 | } 12 | -------------------------------------------------------------------------------- /cypress/platform/empty.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Empty 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /docs/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Mermaid", 3 | "name": "Mermaid JS", 4 | "icons": [ 5 | { 6 | "src": "/favicon.png", 7 | "type": "image/png", 8 | "sizes": "512x512" 9 | } 10 | ], 11 | "background_color": "#6366F1", 12 | "display": "standalone", 13 | "theme_color": "#6366F1" 14 | } 15 | -------------------------------------------------------------------------------- /packages/mermaid-layout-tidy-tree/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist", 6 | "types": ["vitest/importMeta", "vitest/globals"] 7 | }, 8 | "include": ["./src/**/*.ts", "./src/**/*.d.ts"], 9 | "typeRoots": ["./src/types"] 10 | } 11 | -------------------------------------------------------------------------------- /packages/mermaid/src/interactionDb.ts: -------------------------------------------------------------------------------- 1 | let interactionFunctions: (() => void)[] = []; 2 | export const addFunction = (func: () => void) => { 3 | interactionFunctions.push(func); 4 | }; 5 | export const attachFunctions = () => { 6 | interactionFunctions.forEach((f) => { 7 | f(); 8 | }); 9 | interactionFunctions = []; 10 | }; 11 | -------------------------------------------------------------------------------- /packages/mermaid/src/utils/base64.ts: -------------------------------------------------------------------------------- 1 | export function toBase64(str: string) { 2 | // ref: https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem 3 | const utf8Bytes = new TextEncoder().encode(str); 4 | const utf8Str = Array.from(utf8Bytes, (byte) => String.fromCodePoint(byte)).join(''); 5 | return btoa(utf8Str); 6 | } 7 | -------------------------------------------------------------------------------- /packages/mermaid/src/dagre-wrapper/intersect/intersect-circle.js: -------------------------------------------------------------------------------- 1 | import intersectEllipse from './intersect-ellipse.js'; 2 | 3 | /** 4 | * @param node 5 | * @param rx 6 | * @param point 7 | */ 8 | function intersectCircle(node, rx, point) { 9 | return intersectEllipse(node, rx, rx, point); 10 | } 11 | 12 | export default intersectCircle; 13 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagram-api/comments.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Remove all lines starting with `%%` from the text that don't contain a `%%{` 3 | * @param text - The text to remove comments from 4 | * @returns cleaned text 5 | */ 6 | export const cleanupComments = (text: string): string => { 7 | return text.replace(/^\s*%%(?!{)[^\n]+\n?/gm, '').trimStart(); 8 | }; 9 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/info/infoDiagram.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramDefinition } from '../../diagram-api/types.js'; 2 | import { parser } from './infoParser.js'; 3 | import { db } from './infoDb.js'; 4 | import { renderer } from './infoRenderer.js'; 5 | 6 | export const diagram: DiagramDefinition = { 7 | parser, 8 | db, 9 | renderer, 10 | }; 11 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/block/blockUtils.ts: -------------------------------------------------------------------------------- 1 | export const prepareTextForParsing = (text: string): string => { 2 | const textToParse = text 3 | .replaceAll(/^[^\S\n\r]+|[^\S\n\r]+$/g, '') // remove all trailing spaces for each row 4 | .replaceAll(/([\n\r])+/g, '\n') // remove empty lines duplicated 5 | .trim(); 6 | 7 | return textToParse; 8 | }; 9 | -------------------------------------------------------------------------------- /packages/mermaid/src/docs/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Mermaid", 3 | "name": "Mermaid JS", 4 | "icons": [ 5 | { 6 | "src": "/favicon.png", 7 | "type": "image/png", 8 | "sizes": "512x512" 9 | } 10 | ], 11 | "background_color": "#6366F1", 12 | "display": "standalone", 13 | "theme_color": "#6366F1" 14 | } 15 | -------------------------------------------------------------------------------- /packages/mermaid/tsconfig.eslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": ["./tsconfig.json"], 4 | "compilerOptions": { 5 | "noEmit": true 6 | }, 7 | "include": [ 8 | "./src/**/*.spec.js", 9 | "./src/**/*.spec.ts", // test files 10 | "./scripts", 11 | "./.lintstagedrc.mjs" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/sankey/sankeyUtils.ts: -------------------------------------------------------------------------------- 1 | export const prepareTextForParsing = (text: string): string => { 2 | const textToParse = text 3 | .replaceAll(/^[^\S\n\r]+|[^\S\n\r]+$/g, '') // remove all trailing spaces for each row 4 | .replaceAll(/([\n\r])+/g, '\n') // remove empty lines duplicated 5 | .trim(); 6 | 7 | return textToParse; 8 | }; 9 | -------------------------------------------------------------------------------- /cypress/integration/rendering/info.spec.ts: -------------------------------------------------------------------------------- 1 | import { imgSnapshotTest } from '../../helpers/util.ts'; 2 | 3 | describe('info diagram', () => { 4 | it('should handle an info definition', () => { 5 | imgSnapshotTest(`info`); 6 | }); 7 | 8 | it('should handle an info definition with showInfo', () => { 9 | imgSnapshotTest(`info showInfo`); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /packages/mermaid-layout-tidy-tree/src/layouts.ts: -------------------------------------------------------------------------------- 1 | import type { LayoutLoaderDefinition } from 'mermaid'; 2 | 3 | const loader = async () => await import(`./render.js`); 4 | 5 | const tidyTreeLayout: LayoutLoaderDefinition[] = [ 6 | { 7 | name: 'tidy-tree', 8 | loader, 9 | algorithm: 'tidy-tree', 10 | }, 11 | ]; 12 | 13 | export default tidyTreeLayout; 14 | -------------------------------------------------------------------------------- /packages/parser/src/index.ts: -------------------------------------------------------------------------------- 1 | import type { AstNode } from 'langium'; 2 | 3 | export * from './language/index.js'; 4 | export * from './parse.js'; 5 | 6 | /** 7 | * Exclude/omit all `AstNode` attributes recursively. 8 | */ 9 | export type RecursiveAstOmit = T extends object 10 | ? { [P in keyof T as Exclude]: RecursiveAstOmit } 11 | : T; 12 | -------------------------------------------------------------------------------- /packages/mermaid-zenuml/src/parser.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ZenUML manage parsing internally. It uses Antlr4 to parse the DSL. 3 | * The parser is defined in https://github.com/ZenUml/vue-sequence/blob/main/src/parser/index.js 4 | * 5 | * This is a dummy parser that satisfies the mermaid API logic. 6 | */ 7 | export default { 8 | parse: () => { 9 | // no op 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/error/errorDiagram.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramDefinition } from '../../diagram-api/types.js'; 2 | import { renderer } from './errorRenderer.js'; 3 | 4 | const diagram: DiagramDefinition = { 5 | db: {}, 6 | renderer, 7 | parser: { 8 | parse: (): void => { 9 | return; 10 | }, 11 | }, 12 | }; 13 | 14 | export default diagram; 15 | -------------------------------------------------------------------------------- /.github/workflows/unlock-reopened-issues.yml: -------------------------------------------------------------------------------- 1 | name: Unlock reopened issue 2 | 3 | on: 4 | issues: 5 | types: [reopened] 6 | 7 | jobs: 8 | triage: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: Dunning-Kruger/unlock-issues@b06b7f7e5c3f2eaa1c6d5d89f40930e4d6d9699e # v1 12 | with: 13 | repo-token: '${{ secrets.GITHUB_TOKEN }}' 14 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:22.12.0-alpine3.19@sha256:40dc4b415c17b85bea9be05314b4a753f45a4e1716bb31c01182e6c53d51a654 2 | 3 | USER 0:0 4 | 5 | RUN corepack enable \ 6 | && corepack enable pnpm 7 | 8 | RUN apk add --no-cache git~=2.43 \ 9 | && git config --add --system safe.directory /mermaid 10 | 11 | ENV NODE_OPTIONS="--max_old_space_size=8192" 12 | 13 | EXPOSE 9000 3333 14 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/timeline/timeline-definition.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore: JISON doesn't support types 2 | import parser from './parser/timeline.jison'; 3 | import * as db from './timelineDb.js'; 4 | import renderer from './timelineRenderer.js'; 5 | import styles from './styles.js'; 6 | 7 | export const diagram = { 8 | db, 9 | renderer, 10 | parser, 11 | styles, 12 | }; 13 | -------------------------------------------------------------------------------- /cypress/integration/other/iife.spec.js: -------------------------------------------------------------------------------- 1 | describe('IIFE', () => { 2 | beforeEach(() => { 3 | cy.visit('http://localhost:9000/iife.html'); 4 | }); 5 | 6 | it('should render when using mermaid.min.js', () => { 7 | cy.window().should('have.property', 'rendered', true); 8 | cy.get('svg').should('be.visible'); 9 | cy.get('#d2').should('contain', 'Hello'); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/info/infoDb.ts: -------------------------------------------------------------------------------- 1 | import type { InfoFields, InfoDB } from './infoTypes.js'; 2 | 3 | export const DEFAULT_INFO_DB: InfoFields = { 4 | version: injected.version + (injected.includeLargeFeatures ? '' : '-tiny'), 5 | } as const; 6 | 7 | export const getVersion = (): string => DEFAULT_INFO_DB.version; 8 | 9 | export const db: InfoDB = { 10 | getVersion, 11 | }; 12 | -------------------------------------------------------------------------------- /packages/mermaid/src/themes/erDiagram-oldHardcodedValues.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Values that have been hardcoded in src/diagrams/er/styles.js. These can be used by 3 | * theme-_._ files to maintain display styles until themes, styles, renderers are revised. -- 4 | * 2022-09-22 5 | */ 6 | export const oldAttributeBackgroundColorOdd = '#ffffff'; 7 | export const oldAttributeBackgroundColorEven = '#f2f2f2'; 8 | -------------------------------------------------------------------------------- /docs/public/icons/folder.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/radar/diagram.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramDefinition } from '../../diagram-api/types.js'; 2 | import { db } from './db.js'; 3 | import { parser } from './parser.js'; 4 | import { renderer } from './renderer.js'; 5 | import { styles } from './styles.js'; 6 | 7 | export const diagram: DiagramDefinition = { 8 | parser, 9 | db, 10 | renderer, 11 | styles, 12 | }; 13 | -------------------------------------------------------------------------------- /packages/mermaid-zenuml/src/zenuml-definition.ts: -------------------------------------------------------------------------------- 1 | import { injectUtils } from './mermaidUtils.js'; 2 | import parser from './parser.js'; 3 | import renderer from './zenumlRenderer.js'; 4 | 5 | export const diagram = { 6 | db: { 7 | clear: () => { 8 | // no-op 9 | }, 10 | }, 11 | renderer, 12 | parser, 13 | styles: () => { 14 | // no-op 15 | }, 16 | injectUtils, 17 | }; 18 | -------------------------------------------------------------------------------- /cypress/integration/rendering/marker_unique_id.spec.js: -------------------------------------------------------------------------------- 1 | import { urlSnapshotTest } from '../../helpers/util.ts'; 2 | 3 | describe('Marker Unique IDs Per Diagram', () => { 4 | it('should render a blue arrow tip in second digram', () => { 5 | urlSnapshotTest('http://localhost:9000/marker_unique_id.html', { 6 | logLevel: 1, 7 | flowchart: { htmlLabels: false }, 8 | }); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/pie/pieDiagram.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramDefinition } from '../../diagram-api/types.js'; 2 | import { parser } from './pieParser.js'; 3 | import { db } from './pieDb.js'; 4 | import styles from './pieStyles.js'; 5 | import { renderer } from './pieRenderer.js'; 6 | 7 | export const diagram: DiagramDefinition = { 8 | parser, 9 | db, 10 | renderer, 11 | styles, 12 | }; 13 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/xychart/xychartDiagram.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramDefinition } from '../../diagram-api/types.js'; 2 | // @ts-ignore: Jison doesn't support types. 3 | import parser from './parser/xychart.jison'; 4 | import db from './xychartDb.js'; 5 | import renderer from './xychartRenderer.js'; 6 | 7 | export const diagram: DiagramDefinition = { 8 | parser, 9 | db, 10 | renderer, 11 | }; 12 | -------------------------------------------------------------------------------- /patches/roughjs.patch: -------------------------------------------------------------------------------- 1 | diff --git a/bin/rough.d.ts b/bin/rough.d.ts 2 | index 810db1fb34496a5b9f7c0734a7ad8be8605f5534..3624d5b6288a3d2b7d397dfcfffce60558f18cf9 100644 3 | --- a/bin/rough.d.ts 4 | +++ b/bin/rough.d.ts 5 | @@ -8,4 +8,4 @@ declare const _default: { 6 | generator(config?: Config): RoughGenerator; 7 | newSeed(): number; 8 | }; 9 | -export default _default; 10 | +export = _default; 11 | -------------------------------------------------------------------------------- /packages/parser/src/language/packet/packet.langium: -------------------------------------------------------------------------------- 1 | grammar Packet 2 | import "../common/common"; 3 | 4 | entry Packet: 5 | NEWLINE* 6 | ("packet"| "packet-beta") 7 | ( 8 | TitleAndAccessibilities 9 | | blocks+=PacketBlock 10 | | NEWLINE 11 | )* 12 | ; 13 | 14 | PacketBlock: 15 | ( 16 | start=INT('-' end=INT)? 17 | | '+' bits=INT 18 | ) 19 | ':' label=STRING 20 | EOL 21 | ; 22 | -------------------------------------------------------------------------------- /docs/config/mermaidCLI.md: -------------------------------------------------------------------------------- 1 | > **Warning** 2 | > 3 | > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. 4 | > 5 | > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/mermaidCLI.md](../../packages/mermaid/src/docs/config/mermaidCLI.md). 6 | 7 | # mermaid CLI 8 | 9 | mermaid CLI has been moved to [mermaid-cli](https://github.com/mermaid-js/mermaid-cli). Please read its documentation instead. 10 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/er/erRenderer.spec.ts: -------------------------------------------------------------------------------- 1 | import { generateId } from './erRenderer.js'; 2 | 3 | describe('erRenderer', () => { 4 | describe('generateId', () => { 5 | it('should be deterministic', () => { 6 | const id1 = generateId('hello world', 'my-prefix'); 7 | const id2 = generateId('hello world', 'my-prefix'); 8 | 9 | expect(id1).toBe(id2); 10 | }); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/globalStyles.ts: -------------------------------------------------------------------------------- 1 | export const getIconStyles = () => ` 2 | /* Font Awesome icon styling - consolidated */ 3 | .label-icon { 4 | display: inline-block; 5 | height: 1em; 6 | overflow: visible; 7 | vertical-align: -0.125em; 8 | } 9 | 10 | .node .label-icon path { 11 | fill: currentColor; 12 | stroke: revert; 13 | stroke-width: revert; 14 | } 15 | `; 16 | -------------------------------------------------------------------------------- /packages/mermaid/src/docs/public/icons/folder.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /cypress/integration/other/external-diagrams.spec.js: -------------------------------------------------------------------------------- 1 | import { urlSnapshotTest } from '../../helpers/util.ts'; 2 | 3 | describe('mermaid', () => { 4 | describe('registerDiagram', () => { 5 | it('should work on @mermaid-js/mermaid-example-diagram', () => { 6 | const url = 'http://localhost:9000/external-diagrams-example-diagram.html'; 7 | urlSnapshotTest(url, {}, false, false); 8 | }); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/mermaid/src/rendering-util/uid.ts: -------------------------------------------------------------------------------- 1 | export class Uid { 2 | private static count = 0; 3 | id: string; 4 | href: string; 5 | 6 | public static next(name: string): Uid { 7 | return new Uid(name + ++Uid.count); 8 | } 9 | 10 | constructor(id: string) { 11 | this.id = id; 12 | this.href = `#${id}`; 13 | } 14 | 15 | toString(): string { 16 | return 'url(' + this.href + ')'; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/mermaid/typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://typedoc.org/schema.json", 3 | "plugin": ["typedoc-plugin-markdown"], 4 | "readme": "none", 5 | "githubPages": false, 6 | "sourceLinkTemplate": "https://github.com/mermaid-js/mermaid/blob/{gitRevision}/{path}#L{line}", 7 | "gitRevision": "master", 8 | "out": "src/docs/config/setup", 9 | "entryPointStrategy": "expand", 10 | "hideBreadcrumbs": true 11 | } 12 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/er/erDiagram.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore: TODO: Fix ts errors 2 | import erParser from './parser/erDiagram.jison'; 3 | import { ErDB } from './erDb.js'; 4 | import * as renderer from './erRenderer-unified.js'; 5 | import erStyles from './styles.js'; 6 | 7 | export const diagram = { 8 | parser: erParser, 9 | get db() { 10 | return new ErDB(); 11 | }, 12 | renderer, 13 | styles: erStyles, 14 | }; 15 | -------------------------------------------------------------------------------- /packages/mermaid/.madgerc: -------------------------------------------------------------------------------- 1 | { 2 | "detectiveOptions": { 3 | "ts": { 4 | "skipTypeImports": true 5 | }, 6 | "es6": { 7 | "skipTypeImports": true 8 | } 9 | }, 10 | "fileExtensions": [ 11 | "js", 12 | "ts" 13 | ], 14 | "excludeRegExp": [ 15 | "node_modules", 16 | "docs", 17 | "vitepress", 18 | "detector", 19 | "Detector" 20 | ], 21 | "tsConfig": "./tsconfig.json" 22 | } 23 | -------------------------------------------------------------------------------- /cypress/integration/rendering/zenuml.spec.js: -------------------------------------------------------------------------------- 1 | import { imgSnapshotTest } from '../../helpers/util.ts'; 2 | 3 | describe('Zen UML', () => { 4 | it('Basic Zen UML diagram', () => { 5 | imgSnapshotTest( 6 | ` 7 | zenuml 8 | A.method() { 9 | if(x) { 10 | B.method() { 11 | selfCall() { return X } 12 | } 13 | } 14 | } 15 | `, 16 | {} 17 | ); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /docs/public/icons/terminal.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/quadrant-chart/quadrantDiagram.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramDefinition } from '../../diagram-api/types.js'; 2 | // @ts-ignore: JISON doesn't support types 3 | import parser from './parser/quadrant.jison'; 4 | import db from './quadrantDb.js'; 5 | import renderer from './quadrantRenderer.js'; 6 | 7 | export const diagram: DiagramDefinition = { 8 | parser, 9 | db, 10 | renderer, 11 | styles: () => '', 12 | }; 13 | -------------------------------------------------------------------------------- /packages/mermaid/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist", 6 | "types": ["vitest/importMeta", "vitest/globals"] 7 | }, 8 | "include": [ 9 | "./src/**/*.ts", 10 | "./package.json", 11 | "src/diagrams/gantt/ganttDb.js", 12 | "src/diagrams/git/gitGraphRenderer.js", 13 | "src/diagrams/class/classRenderer.js" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/packet/diagram.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramDefinition } from '../../diagram-api/types.js'; 2 | import { PacketDB } from './db.js'; 3 | import { parser } from './parser.js'; 4 | import { renderer } from './renderer.js'; 5 | import { styles } from './styles.js'; 6 | 7 | export const diagram: DiagramDefinition = { 8 | parser, 9 | get db() { 10 | return new PacketDB(); 11 | }, 12 | renderer, 13 | styles, 14 | }; 15 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/treemap/diagram.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramDefinition } from '../../diagram-api/types.js'; 2 | import { TreeMapDB } from './db.js'; 3 | import { parser } from './parser.js'; 4 | import { renderer } from './renderer.js'; 5 | import styles from './styles.js'; 6 | 7 | export const diagram: DiagramDefinition = { 8 | parser, 9 | get db() { 10 | return new TreeMapDB(); 11 | }, 12 | renderer, 13 | styles, 14 | }; 15 | -------------------------------------------------------------------------------- /packages/mermaid/.lintstagedrc.mjs: -------------------------------------------------------------------------------- 1 | import baseConfig from '../../.lintstagedrc.mjs'; 2 | export default { 3 | ...baseConfig, 4 | 'src/docs/**': ['pnpm --filter mermaid run docs:build --git'], 5 | 'src/docs.mts': ['pnpm --filter mermaid run docs:build --git'], 6 | 'src/(defaultConfig|config|mermaidAPI).ts': ['pnpm --filter mermaid run docs:build --git'], 7 | 'src/schemas/config.schema.yaml': ['pnpm --filter mermaid run types:build-config --git'], 8 | }; 9 | -------------------------------------------------------------------------------- /packages/mermaid-example-diagram/src/diagram-definition.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore: TODO Fix ts errors 2 | import parser from './parser/exampleDiagram.jison'; 3 | import * as db from './exampleDiagramDb.js'; 4 | import renderer from './exampleDiagramRenderer.js'; 5 | import styles from './styles.js'; 6 | import { injectUtils } from './mermaidUtils.js'; 7 | 8 | export const diagram = { 9 | db, 10 | renderer, 11 | parser, 12 | styles, 13 | injectUtils, 14 | }; 15 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/info/infoParser.ts: -------------------------------------------------------------------------------- 1 | import type { Info } from '@mermaid-js/parser'; 2 | import { parse } from '@mermaid-js/parser'; 3 | import type { ParserDefinition } from '../../diagram-api/types.js'; 4 | import { log } from '../../logger.js'; 5 | 6 | export const parser: ParserDefinition = { 7 | parse: async (input: string): Promise => { 8 | const ast: Info = await parse('info', input); 9 | log.debug(ast); 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/kanban/kanban-definition.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore: JISON doesn't support types 2 | import parser from './parser/kanban.jison'; 3 | import db from './kanbanDb.js'; 4 | import renderer from './kanbanRenderer.js'; 5 | import styles from './styles.js'; 6 | import type { DiagramDefinition } from '../../diagram-api/types.js'; 7 | 8 | export const diagram: DiagramDefinition = { 9 | db, 10 | renderer, 11 | parser, 12 | styles, 13 | }; 14 | -------------------------------------------------------------------------------- /packages/mermaid/src/docs/public/icons/terminal.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /packages/parser/src/language/common/matcher.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Matches single and multi line accessible description 3 | */ 4 | export const accessibilityDescrRegex = /accDescr(?:[\t ]*:([^\n\r]*)|\s*{([^}]*)})/; 5 | 6 | /** 7 | * Matches single line accessible title 8 | */ 9 | export const accessibilityTitleRegex = /accTitle[\t ]*:([^\n\r]*)/; 10 | 11 | /** 12 | * Matches a single line title 13 | */ 14 | export const titleRegex = /title([\t ][^\n\r]*|)/; 15 | -------------------------------------------------------------------------------- /docs/config/setup/README.md: -------------------------------------------------------------------------------- 1 | > **Warning** 2 | > 3 | > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. 4 | > 5 | > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/README.md](../../../packages/mermaid/src/docs/config/setup/README.md). 6 | 7 | **mermaid** 8 | 9 | --- 10 | 11 | # mermaid 12 | 13 | ## Modules 14 | 15 | - [config](config/README.md) 16 | - [defaultConfig](defaultConfig/README.md) 17 | - [mermaid](mermaid/README.md) 18 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/block/blockDiagram.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramDefinition } from '../../diagram-api/types.js'; 2 | // @ts-ignore: jison doesn't export types 3 | import parser from './parser/block.jison'; 4 | import db from './blockDB.js'; 5 | import flowStyles from './styles.js'; 6 | import renderer from './blockRenderer.js'; 7 | 8 | export const diagram: DiagramDefinition = { 9 | parser, 10 | db, 11 | renderer, 12 | styles: flowStyles, 13 | }; 14 | -------------------------------------------------------------------------------- /.vite/jisonPlugin.ts: -------------------------------------------------------------------------------- 1 | import { transformJison } from '../.build/jisonTransformer.js'; 2 | 3 | const fileRegex = /\.(jison)$/; 4 | 5 | export default function jison() { 6 | return { 7 | name: 'jison', 8 | transform(src: string, id: string) { 9 | if (fileRegex.test(id)) { 10 | return { 11 | code: transformJison(src), 12 | map: null, // provide source map if available 13 | }; 14 | } 15 | }, 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /cypress/platform/xss22.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
 8 |   graph TD
 9 | A --> B["<a href='javascript#9;t#colon;alert(document.location)'>AAA</a>"]
10 |     
11 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /.lintstagedrc.mjs: -------------------------------------------------------------------------------- 1 | export default { 2 | '!(docs/**/*)*.{ts,js,html,md,mts}': [ 3 | 'eslint --cache --cache-strategy content --fix', 4 | // don't cache prettier yet, since we use `prettier-plugin-jsdoc`, 5 | // and prettier doesn't invalidate cache on plugin updates" 6 | // https://prettier.io/docs/en/cli.html#--cache 7 | 'prettier --write', 8 | ], 9 | '.cspell/*.txt': ['tsx scripts/fixCSpell.ts'], 10 | '**/*.jison': ['pnpm -w run lint:jison'], 11 | }; 12 | -------------------------------------------------------------------------------- /packages/mermaid/src/dagre-wrapper/intersect/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Borrowed with love from dagre-d3. Many thanks to cpettitt! 3 | */ 4 | 5 | import node from './intersect-node.js'; 6 | import circle from './intersect-circle.js'; 7 | import ellipse from './intersect-ellipse.js'; 8 | import polygon from './intersect-polygon.js'; 9 | import rect from './intersect-rect.js'; 10 | 11 | export default { 12 | node, 13 | circle, 14 | ellipse, 15 | polygon, 16 | rect, 17 | }; 18 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/common/populateCommonDb.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramAST } from '@mermaid-js/parser'; 2 | import type { DiagramDB } from '../../diagram-api/types.js'; 3 | 4 | export function populateCommonDb(ast: DiagramAST, db: DiagramDB) { 5 | if (ast.accDescr) { 6 | db.setAccDescription?.(ast.accDescr); 7 | } 8 | if (ast.accTitle) { 9 | db.setAccTitle?.(ast.accTitle); 10 | } 11 | if (ast.title) { 12 | db.setDiagramTitle?.(ast.title); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cypress/integration/rendering/current.spec.js: -------------------------------------------------------------------------------- 1 | import { imgSnapshotTest } from '../../helpers/util.ts'; 2 | 3 | describe('Current diagram', () => { 4 | it('should render a state with states in it', () => { 5 | imgSnapshotTest( 6 | ` 7 | stateDiagram 8 | state PersonalizedCockpit { 9 | Other 10 | state Parent { 11 | C 12 | } 13 | } 14 | `, 15 | { 16 | logLevel: 0, 17 | } 18 | ); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /docs/config/setup/defaultConfig/README.md: -------------------------------------------------------------------------------- 1 | > **Warning** 2 | > 3 | > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. 4 | > 5 | > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/defaultConfig/README.md](../../../../packages/mermaid/src/docs/config/setup/defaultConfig/README.md). 6 | 7 | [**mermaid**](../README.md) 8 | 9 | --- 10 | 11 | # defaultConfig 12 | 13 | ## Variables 14 | 15 | - [configKeys](variables/configKeys.md) 16 | - [default](variables/default.md) 17 | -------------------------------------------------------------------------------- /docs/public/icons/open-source.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | -------------------------------------------------------------------------------- /packages/examples/src/examples/pie.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramMetadata } from '../types.js'; 2 | 3 | export default { 4 | id: 'pie', 5 | name: 'Pie Chart', 6 | description: 'Visualize data as proportional segments of a circle', 7 | examples: [ 8 | { 9 | title: 'Basic Pie Chart', 10 | isDefault: true, 11 | code: `pie title Pets adopted by volunteers 12 | "Dogs" : 386 13 | "Cats" : 85 14 | "Rats" : 15`, 15 | }, 16 | ], 17 | } satisfies DiagramMetadata; 18 | -------------------------------------------------------------------------------- /packages/mermaid-zenuml/src/detector.ts: -------------------------------------------------------------------------------- 1 | import type { ExternalDiagramDefinition } from 'mermaid'; 2 | 3 | const id = 'zenuml'; 4 | 5 | const detector = (txt: string) => { 6 | return /^\s*zenuml/.test(txt); 7 | }; 8 | 9 | const loader = async () => { 10 | const { diagram } = await import('./zenuml-definition.js'); 11 | return { id, diagram }; 12 | }; 13 | 14 | const plugin: ExternalDiagramDefinition = { 15 | id, 16 | detector, 17 | loader, 18 | }; 19 | 20 | export default plugin; 21 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/flowchart/parser/flowParser.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore: JISON doesn't support types 2 | import flowJisonParser from './flow.jison'; 3 | 4 | const newParser = Object.assign({}, flowJisonParser); 5 | 6 | newParser.parse = (src: string): unknown => { 7 | // remove the trailing whitespace after closing curly braces when ending a line break 8 | const newSrc = src.replace(/}\s*\n/g, '}\n'); 9 | return flowJisonParser.parse(newSrc); 10 | }; 11 | 12 | export default newParser; 13 | -------------------------------------------------------------------------------- /packages/mermaid/src/rendering-util/rendering-elements/intersect/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Borrowed with love from dagre-d3. Many thanks to cpettitt! 3 | */ 4 | 5 | import node from './intersect-node.js'; 6 | import circle from './intersect-circle.js'; 7 | import ellipse from './intersect-ellipse.js'; 8 | import polygon from './intersect-polygon.js'; 9 | import rect from './intersect-rect.js'; 10 | 11 | export default { 12 | node, 13 | circle, 14 | ellipse, 15 | polygon, 16 | rect, 17 | }; 18 | -------------------------------------------------------------------------------- /packages/mermaid/src/rendering-util/rendering-elements/shapes/state.ts: -------------------------------------------------------------------------------- 1 | import type { Node, RectOptions } from '../../types.js'; 2 | import type { D3Selection } from '../../../types.js'; 3 | import { drawRect } from './drawRect.js'; 4 | 5 | export async function state(parent: D3Selection, node: Node) { 6 | const options = { 7 | rx: 5, 8 | ry: 5, 9 | classes: 'flowchart-node', 10 | } as RectOptions; 11 | return drawRect(parent, node, options); 12 | } 13 | -------------------------------------------------------------------------------- /.build/jisonTransformer.ts: -------------------------------------------------------------------------------- 1 | import jison from 'jison'; 2 | 3 | export const transformJison = (src: string): string => { 4 | // @ts-ignore - Jison is not typed properly 5 | const parser = new jison.Generator(src, { 6 | moduleType: 'js', 7 | 'token-stack': true, 8 | }); 9 | const source = parser.generate({ moduleMain: '() => {}' }); 10 | const exporter = ` 11 | parser.parser = parser; 12 | export { parser }; 13 | export default parser; 14 | `; 15 | return `${source} ${exporter}`; 16 | }; 17 | -------------------------------------------------------------------------------- /packages/mermaid/src/rendering-util/rendering-elements/shapes/mindmapCircle.ts: -------------------------------------------------------------------------------- 1 | import { circle } from './circle.js'; 2 | import type { Node, MindmapOptions } from '../../types.js'; 3 | import type { D3Selection } from '../../../types.js'; 4 | 5 | export async function mindmapCircle( 6 | parent: D3Selection, 7 | node: Node 8 | ) { 9 | const options = { 10 | padding: node.padding ?? 0, 11 | } as MindmapOptions; 12 | return circle(parent, node, options); 13 | } 14 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json", 3 | "changelog": ["@changesets/changelog-github", { "repo": "mermaid-js/mermaid" }], 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "public", 8 | "baseBranch": "master", 9 | "updateInternalDependencies": "patch", 10 | "bumpVersionsWithWorkspaceProtocolOnly": true, 11 | "ignore": ["@mermaid-js/docs", "@mermaid-js/webpack-test", "@mermaid-js/mermaid-example-diagram"] 12 | } 13 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/git/gitGraphDiagram.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore: JISON doesn't support types 2 | import { parser } from './gitGraphParser.js'; 3 | import { db } from './gitGraphAst.js'; 4 | import gitGraphRenderer from './gitGraphRenderer.js'; 5 | import gitGraphStyles from './styles.js'; 6 | import type { DiagramDefinition } from '../../diagram-api/types.js'; 7 | 8 | export const diagram: DiagramDefinition = { 9 | parser, 10 | db, 11 | renderer: gitGraphRenderer, 12 | styles: gitGraphStyles, 13 | }; 14 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/gantt/ganttDiagram.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore: JISON doesn't support types 2 | import ganttParser from './parser/gantt.jison'; 3 | import ganttDb from './ganttDb.js'; 4 | import ganttRenderer from './ganttRenderer.js'; 5 | import ganttStyles from './styles.js'; 6 | import type { DiagramDefinition } from '../../diagram-api/types.js'; 7 | 8 | export const diagram: DiagramDefinition = { 9 | parser: ganttParser, 10 | db: ganttDb, 11 | renderer: ganttRenderer, 12 | styles: ganttStyles, 13 | }; 14 | -------------------------------------------------------------------------------- /packages/mermaid/src/docs/public/icons/open-source.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | -------------------------------------------------------------------------------- /packages/mermaid-example-diagram/src/detector.ts: -------------------------------------------------------------------------------- 1 | import type { ExternalDiagramDefinition } from 'mermaid'; 2 | 3 | const id = 'example-diagram'; 4 | 5 | const detector = (txt: string) => { 6 | return /^\s*example-diagram/.test(txt); 7 | }; 8 | 9 | const loader = async () => { 10 | const { diagram } = await import('./diagram-definition.js'); 11 | return { id, diagram }; 12 | }; 13 | 14 | const plugin: ExternalDiagramDefinition = { 15 | id, 16 | detector, 17 | loader, 18 | }; 19 | 20 | export default plugin; 21 | -------------------------------------------------------------------------------- /packages/mermaid-layout-tidy-tree/src/non-layered-tidy-tree-layout.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'non-layered-tidy-tree-layout' { 2 | export class BoundingBox { 3 | constructor(gap: number, bottomPadding: number); 4 | } 5 | 6 | export class Layout { 7 | constructor(boundingBox: BoundingBox); 8 | layout(data: any): { 9 | result: any; 10 | boundingBox: { 11 | left: number; 12 | right: number; 13 | top: number; 14 | bottom: number; 15 | }; 16 | }; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/architecture/architectureDiagram.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramDefinition } from '../../diagram-api/types.js'; 2 | import { parser } from './architectureParser.js'; 3 | import { ArchitectureDB } from './architectureDb.js'; 4 | import styles from './architectureStyles.js'; 5 | import { renderer } from './architectureRenderer.js'; 6 | 7 | export const diagram: DiagramDefinition = { 8 | parser, 9 | get db() { 10 | return new ArchitectureDB(); 11 | }, 12 | renderer, 13 | styles, 14 | }; 15 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/mindmap/mindmap-definition.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore: JISON doesn't support types 2 | import parser from './parser/mindmap.jison'; 3 | import { MindmapDB } from './mindmapDb.js'; 4 | import renderer from './mindmapRenderer.js'; 5 | import styles from './styles.js'; 6 | import type { DiagramDefinition } from '../../diagram-api/types.js'; 7 | 8 | export const diagram: DiagramDefinition = { 9 | get db() { 10 | return new MindmapDB(); 11 | }, 12 | renderer, 13 | parser, 14 | styles, 15 | }; 16 | -------------------------------------------------------------------------------- /packages/parser/src/language/pie/pie.langium: -------------------------------------------------------------------------------- 1 | grammar Pie 2 | import "../common/common"; 3 | 4 | entry Pie: 5 | NEWLINE* 6 | "pie" showData?="showData"? 7 | ( 8 | TitleAndAccessibilities 9 | | sections+=PieSection 10 | | NEWLINE 11 | )* 12 | ; 13 | 14 | PieSection: 15 | label=STRING ":" value=NUMBER_PIE EOL 16 | ; 17 | 18 | terminal FLOAT_PIE returns number: /-?[0-9]+\.[0-9]+(?!\.)/; 19 | terminal INT_PIE returns number: /-?(0|[1-9][0-9]*)(?!\.)/; 20 | terminal NUMBER_PIE returns number: FLOAT_PIE | INT_PIE; -------------------------------------------------------------------------------- /packages/mermaid-layout-elk/src/layouts.ts: -------------------------------------------------------------------------------- 1 | import type { LayoutLoaderDefinition } from 'mermaid'; 2 | 3 | const loader = async () => await import(`./render.js`); 4 | const algos = ['elk.stress', 'elk.force', 'elk.mrtree', 'elk.sporeOverlap']; 5 | 6 | const layouts: LayoutLoaderDefinition[] = [ 7 | { 8 | name: 'elk', 9 | loader, 10 | algorithm: 'elk.layered', 11 | }, 12 | ...algos.map((algo) => ({ 13 | name: algo, 14 | loader, 15 | algorithm: algo, 16 | })), 17 | ]; 18 | 19 | export default layouts; 20 | -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts: -------------------------------------------------------------------------------- 1 | import type { RequiredDeep } from 'type-fest'; 2 | 3 | export interface MindmapNode { 4 | id: number; 5 | nodeId: string; 6 | level: number; 7 | descr: string; 8 | type: number; 9 | children: MindmapNode[]; 10 | width: number; 11 | padding: number; 12 | section?: number; 13 | height?: number; 14 | class?: string; 15 | icon?: string; 16 | x?: number; 17 | y?: number; 18 | isRoot?: boolean; 19 | } 20 | 21 | export type FilledMindMapNode = RequiredDeep; 22 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/block/blockDetector.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types.js'; 2 | 3 | const id = 'block'; 4 | 5 | const detector: DiagramDetector = (txt) => { 6 | return /^\s*block(-beta)?/.test(txt); 7 | }; 8 | 9 | const loader = async () => { 10 | const { diagram } = await import('./blockDiagram.js'); 11 | return { id, diagram }; 12 | }; 13 | 14 | const plugin: ExternalDiagramDefinition = { 15 | id, 16 | detector, 17 | loader, 18 | }; 19 | 20 | export default plugin; 21 | -------------------------------------------------------------------------------- /cypress/platform/e2e.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /packages/examples/src/examples/treemap.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramMetadata } from '../types.js'; 2 | 3 | export default { 4 | id: 'treemap', 5 | name: 'Treemap', 6 | description: 'Visualize hierarchical data as nested rectangles', 7 | examples: [ 8 | { 9 | title: 'Treemap', 10 | isDefault: true, 11 | code: `treemap-beta 12 | "Section 1" 13 | "Leaf 1.1": 12 14 | "Section 1.2" 15 | "Leaf 1.2.1": 12 16 | "Section 2" 17 | "Leaf 2.1": 20 18 | "Leaf 2.2": 25`, 19 | }, 20 | ], 21 | } satisfies DiagramMetadata; 22 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/requirement/requirementDiagram.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramDefinition } from '../../diagram-api/types.js'; 2 | // @ts-ignore: JISON doesn't support types 3 | import parser from './parser/requirementDiagram.jison'; 4 | import { RequirementDB } from './requirementDb.js'; 5 | import styles from './styles.js'; 6 | import * as renderer from './requirementRenderer.js'; 7 | 8 | export const diagram: DiagramDefinition = { 9 | parser, 10 | get db() { 11 | return new RequirementDB(); 12 | }, 13 | renderer, 14 | styles, 15 | }; 16 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/sankey/sankeyDetector.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types.js'; 2 | 3 | const id = 'sankey'; 4 | 5 | const detector: DiagramDetector = (txt) => { 6 | return /^\s*sankey(-beta)?/.test(txt); 7 | }; 8 | 9 | const loader = async () => { 10 | const { diagram } = await import('./sankeyDiagram.js'); 11 | return { id, diagram }; 12 | }; 13 | 14 | const plugin: ExternalDiagramDefinition = { 15 | id, 16 | detector, 17 | loader, 18 | }; 19 | 20 | export default plugin; 21 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/user-journey/journeyDiagram.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramDefinition } from '../../diagram-api/types.js'; 2 | // @ts-ignore: JISON doesn't support types 3 | import parser from './parser/journey.jison'; 4 | import db from './journeyDb.js'; 5 | import styles from './styles.js'; 6 | import renderer from './journeyRenderer.js'; 7 | 8 | export const diagram: DiagramDefinition = { 9 | parser, 10 | db, 11 | renderer, 12 | styles, 13 | init: (cnf) => { 14 | renderer.setConf(cnf.journey); 15 | db.clear(); 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /.esbuild/jisonPlugin.ts: -------------------------------------------------------------------------------- 1 | import { readFile } from 'node:fs/promises'; 2 | import { transformJison } from '../.build/jisonTransformer.js'; 3 | import type { Plugin } from 'esbuild'; 4 | 5 | export const jisonPlugin: Plugin = { 6 | name: 'jison', 7 | setup(build) { 8 | build.onLoad({ filter: /\.jison$/ }, async (args) => { 9 | // Load the file from the file system 10 | const source = await readFile(args.path, 'utf8'); 11 | const contents = transformJison(source); 12 | return { contents, warnings: [] }; 13 | }); 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/pie/pieDetector.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DiagramDetector, 3 | DiagramLoader, 4 | ExternalDiagramDefinition, 5 | } from '../../diagram-api/types.js'; 6 | 7 | const id = 'pie'; 8 | 9 | const detector: DiagramDetector = (txt) => { 10 | return /^\s*pie/.test(txt); 11 | }; 12 | 13 | const loader: DiagramLoader = async () => { 14 | const { diagram } = await import('./pieDiagram.js'); 15 | return { id, diagram }; 16 | }; 17 | 18 | export const pie: ExternalDiagramDefinition = { 19 | id, 20 | detector, 21 | loader, 22 | }; 23 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/info/infoDetector.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DiagramDetector, 3 | DiagramLoader, 4 | ExternalDiagramDefinition, 5 | } from '../../diagram-api/types.js'; 6 | 7 | const id = 'info'; 8 | 9 | const detector: DiagramDetector = (txt) => { 10 | return /^\s*info/.test(txt); 11 | }; 12 | 13 | const loader: DiagramLoader = async () => { 14 | const { diagram } = await import('./infoDiagram.js'); 15 | return { id, diagram }; 16 | }; 17 | 18 | export const info: ExternalDiagramDefinition = { 19 | id, 20 | detector, 21 | loader, 22 | }; 23 | -------------------------------------------------------------------------------- /packages/examples/src/examples/state.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramMetadata } from '../types.js'; 2 | 3 | export default { 4 | id: 'stateDiagram', 5 | name: 'State Diagram', 6 | description: 'Visualize the states and transitions of a system', 7 | examples: [ 8 | { 9 | title: 'Basic State Diagram', 10 | code: `stateDiagram-v2 11 | [*] --> Still 12 | Still --> [*] 13 | Still --> Moving 14 | Moving --> Still 15 | Moving --> Crash 16 | Crash --> [*]`, 17 | isDefault: true, 18 | }, 19 | ], 20 | } satisfies DiagramMetadata; 21 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/radar/detector.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DiagramDetector, 3 | DiagramLoader, 4 | ExternalDiagramDefinition, 5 | } from '../../diagram-api/types.js'; 6 | 7 | const id = 'radar'; 8 | 9 | const detector: DiagramDetector = (txt) => { 10 | return /^\s*radar-beta/.test(txt); 11 | }; 12 | 13 | const loader: DiagramLoader = async () => { 14 | const { diagram } = await import('./diagram.js'); 15 | return { id, diagram }; 16 | }; 17 | 18 | export const radar: ExternalDiagramDefinition = { 19 | id, 20 | detector, 21 | loader, 22 | }; 23 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/treemap/detector.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DiagramDetector, 3 | DiagramLoader, 4 | ExternalDiagramDefinition, 5 | } from '../../diagram-api/types.js'; 6 | 7 | const id = 'treemap'; 8 | 9 | const detector: DiagramDetector = (txt) => { 10 | return /^\s*treemap/.test(txt); 11 | }; 12 | 13 | const loader: DiagramLoader = async () => { 14 | const { diagram } = await import('./diagram.js'); 15 | return { id, diagram }; 16 | }; 17 | 18 | export const treemap: ExternalDiagramDefinition = { 19 | id, 20 | detector, 21 | loader, 22 | }; 23 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | cypress/platform/xss3.html 3 | .cache 4 | .pnpm-store 5 | coverage 6 | # Autogenerated by PNPM 7 | pnpm-lock.yaml 8 | stats 9 | **/.vitepress/components.d.ts 10 | **/.vitepress/cache 11 | .nyc_output 12 | # Autogenerated by `pnpm run --filter mermaid types:build-config` 13 | packages/mermaid/src/config.type.ts 14 | # autogenereated by langium-cli 15 | generated/ 16 | # Ignore the files creates in /demos/dev except for example.html 17 | demos/dev/** 18 | !/demos/dev/example.html 19 | # TODO: Lots of errors to fix 20 | cypress/platform/state-refactor.html 21 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/packet/detector.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DiagramDetector, 3 | DiagramLoader, 4 | ExternalDiagramDefinition, 5 | } from '../../diagram-api/types.js'; 6 | 7 | const id = 'packet'; 8 | 9 | const detector: DiagramDetector = (txt) => { 10 | return /^\s*packet(-beta)?/.test(txt); 11 | }; 12 | 13 | const loader: DiagramLoader = async () => { 14 | const { diagram } = await import('./diagram.js'); 15 | return { id, diagram }; 16 | }; 17 | 18 | export const packet: ExternalDiagramDefinition = { 19 | id, 20 | detector, 21 | loader, 22 | }; 23 | -------------------------------------------------------------------------------- /packages/mermaid/src/rendering-util/insertElementsForSize.js: -------------------------------------------------------------------------------- 1 | import { select } from 'd3'; 2 | 3 | export const getDiagramElement = (id, securityLevel) => { 4 | let sandboxElement; 5 | if (securityLevel === 'sandbox') { 6 | sandboxElement = select('#i' + id); 7 | } 8 | const root = 9 | securityLevel === 'sandbox' 10 | ? select(sandboxElement.nodes()[0].contentDocument.body) 11 | : select('body'); 12 | 13 | const svg = root.select(`[id="${id}"]`); 14 | 15 | // Run the renderer. This is what draws the final graph. 16 | 17 | return svg; 18 | }; 19 | -------------------------------------------------------------------------------- /packages/parser/src/language/pie/valueConverter.ts: -------------------------------------------------------------------------------- 1 | import type { CstNode, GrammarAST, ValueType } from 'langium'; 2 | 3 | import { AbstractMermaidValueConverter } from '../common/index.js'; 4 | 5 | export class PieValueConverter extends AbstractMermaidValueConverter { 6 | protected runCustomConverter( 7 | rule: GrammarAST.AbstractRule, 8 | input: string, 9 | _cstNode: CstNode 10 | ): ValueType | undefined { 11 | if (rule.name !== 'PIE_SECTION_LABEL') { 12 | return undefined; 13 | } 14 | return input.replace(/"/g, '').trim(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.github/codecov.yaml: -------------------------------------------------------------------------------- 1 | codecov: 2 | branch: develop 3 | 4 | comment: 5 | layout: 'reach, diff, flags, files' 6 | behavior: default 7 | require_changes: false # if true: only post the comment if coverage changes 8 | require_base: no # [yes :: must have a base report to post] 9 | require_head: yes # [yes :: must have a head report to post] 10 | 11 | coverage: 12 | status: 13 | project: 14 | off 15 | # Turing off for now as code coverage isn't stable and causes unnecessary build failures. 16 | # default: 17 | # threshold: 2% 18 | patch: off 19 | -------------------------------------------------------------------------------- /packages/examples/src/examples/flowchart.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramMetadata } from '../types.js'; 2 | 3 | export default { 4 | id: 'flowchart-v2', 5 | name: 'Flowchart', 6 | description: 'Visualize flowcharts and directed graphs', 7 | examples: [ 8 | { 9 | title: 'Basic Flowchart', 10 | isDefault: true, 11 | code: `flowchart TD 12 | A[Christmas] -->|Get money| B(Go shopping) 13 | B --> C{Let me think} 14 | C -->|One| D[Laptop] 15 | C -->|Two| E[iPhone] 16 | C -->|Three| F[fa:fa-car Car]`, 17 | }, 18 | ], 19 | } satisfies DiagramMetadata; 20 | -------------------------------------------------------------------------------- /packages/examples/src/examples/timeline.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramMetadata } from '../types.js'; 2 | 3 | export default { 4 | id: 'timeline', 5 | name: 'Timeline Diagram', 6 | description: 'Visualize events and milestones in chronological order', 7 | examples: [ 8 | { 9 | title: 'Project Timeline', 10 | isDefault: true, 11 | code: `timeline 12 | title History of Social Media Platform 13 | 2002 : LinkedIn 14 | 2004 : Facebook 15 | : Google 16 | 2005 : YouTube 17 | 2006 : Twitter`, 18 | }, 19 | ], 20 | } satisfies DiagramMetadata; 21 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/er/erDetector.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DiagramDetector, 3 | DiagramLoader, 4 | ExternalDiagramDefinition, 5 | } from '../../diagram-api/types.js'; 6 | 7 | const id = 'er'; 8 | 9 | const detector: DiagramDetector = (txt) => { 10 | return /^\s*erDiagram/.test(txt); 11 | }; 12 | 13 | const loader: DiagramLoader = async () => { 14 | const { diagram } = await import('./erDiagram.js'); 15 | return { id, diagram }; 16 | }; 17 | 18 | const plugin: ExternalDiagramDefinition = { 19 | id, 20 | detector, 21 | loader, 22 | }; 23 | 24 | export default plugin; 25 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/gantt/ganttDetector.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DiagramDetector, 3 | DiagramLoader, 4 | ExternalDiagramDefinition, 5 | } from '../../diagram-api/types.js'; 6 | 7 | const id = 'gantt'; 8 | 9 | const detector: DiagramDetector = (txt) => { 10 | return /^\s*gantt/.test(txt); 11 | }; 12 | 13 | const loader: DiagramLoader = async () => { 14 | const { diagram } = await import('./ganttDiagram.js'); 15 | return { id, diagram }; 16 | }; 17 | 18 | const plugin: ExternalDiagramDefinition = { 19 | id, 20 | detector, 21 | loader, 22 | }; 23 | 24 | export default plugin; 25 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/kanban/detector.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DiagramDetector, 3 | DiagramLoader, 4 | ExternalDiagramDefinition, 5 | } from '../../diagram-api/types.js'; 6 | const id = 'kanban'; 7 | 8 | const detector: DiagramDetector = (txt) => { 9 | return /^\s*kanban/.test(txt); 10 | }; 11 | 12 | const loader: DiagramLoader = async () => { 13 | const { diagram } = await import('./kanban-definition.js'); 14 | return { id, diagram }; 15 | }; 16 | 17 | const plugin: ExternalDiagramDefinition = { 18 | id, 19 | detector, 20 | loader, 21 | }; 22 | 23 | export default plugin; 24 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/mindmap/detector.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DiagramDetector, 3 | DiagramLoader, 4 | ExternalDiagramDefinition, 5 | } from '../../diagram-api/types.js'; 6 | const id = 'mindmap'; 7 | 8 | const detector: DiagramDetector = (txt) => { 9 | return /^\s*mindmap/.test(txt); 10 | }; 11 | 12 | const loader: DiagramLoader = async () => { 13 | const { diagram } = await import('./mindmap-definition.js'); 14 | return { id, diagram }; 15 | }; 16 | 17 | const plugin: ExternalDiagramDefinition = { 18 | id, 19 | detector, 20 | loader, 21 | }; 22 | 23 | export default plugin; 24 | -------------------------------------------------------------------------------- /packages/examples/src/examples/sequence.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramMetadata } from '../types.js'; 2 | 3 | export default { 4 | id: 'sequence', 5 | name: 'Sequence Diagram', 6 | description: 'Visualize interactions between objects over time', 7 | examples: [ 8 | { 9 | title: 'Basic Sequence', 10 | isDefault: true, 11 | code: `sequenceDiagram 12 | Alice->>+John: Hello John, how are you? 13 | Alice->>+John: John, can you hear me? 14 | John-->>-Alice: Hi Alice, I can hear you! 15 | John-->>-Alice: I feel great!`, 16 | }, 17 | ], 18 | } satisfies DiagramMetadata; 19 | -------------------------------------------------------------------------------- /tests/webpack/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mermaid-js/webpack-test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "private": true, 6 | "module": "commonjs", 7 | "scripts": { 8 | "build": "webpack", 9 | "serve": "webpack serve" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "webpack": "^5.91.0", 16 | "webpack-cli": "^4.10.0", 17 | "webpack-dev-server": "^4.15.2" 18 | }, 19 | "dependencies": { 20 | "@mermaid-js/mermaid-example-diagram": "workspace:*", 21 | "mermaid": "workspace:*" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/timeline/detector.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DiagramDetector, 3 | DiagramLoader, 4 | ExternalDiagramDefinition, 5 | } from '../../diagram-api/types.js'; 6 | 7 | const id = 'timeline'; 8 | 9 | const detector: DiagramDetector = (txt) => { 10 | return /^\s*timeline/.test(txt); 11 | }; 12 | 13 | const loader: DiagramLoader = async () => { 14 | const { diagram } = await import('./timeline-definition.js'); 15 | return { id, diagram }; 16 | }; 17 | 18 | const plugin: ExternalDiagramDefinition = { 19 | id, 20 | detector, 21 | loader, 22 | }; 23 | 24 | export default plugin; 25 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/c4/c4Diagram.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore: JISON doesn't support types 2 | import parser from './parser/c4Diagram.jison'; 3 | import db from './c4Db.js'; 4 | import renderer from './c4Renderer.js'; 5 | import styles from './styles.js'; 6 | import type { MermaidConfig } from '../../config.type.js'; 7 | import type { DiagramDefinition } from '../../diagram-api/types.js'; 8 | 9 | export const diagram: DiagramDefinition = { 10 | parser, 11 | db, 12 | renderer, 13 | styles, 14 | init: ({ c4, wrap }: MermaidConfig) => { 15 | renderer.setConf(c4); 16 | db.setWrap(wrap); 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/user-journey/journeyDetector.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DiagramDetector, 3 | DiagramLoader, 4 | ExternalDiagramDefinition, 5 | } from '../../diagram-api/types.js'; 6 | 7 | const id = 'journey'; 8 | 9 | const detector: DiagramDetector = (txt) => { 10 | return /^\s*journey/.test(txt); 11 | }; 12 | 13 | const loader: DiagramLoader = async () => { 14 | const { diagram } = await import('./journeyDiagram.js'); 15 | return { id, diagram }; 16 | }; 17 | 18 | const plugin: ExternalDiagramDefinition = { 19 | id, 20 | detector, 21 | loader, 22 | }; 23 | 24 | export default plugin; 25 | -------------------------------------------------------------------------------- /packages/mermaid/src/rendering-util/rendering-elements/shapes/squareRect.ts: -------------------------------------------------------------------------------- 1 | import type { Node, RectOptions } from '../../types.js'; 2 | import type { D3Selection } from '../../../types.js'; 3 | import { drawRect } from './drawRect.js'; 4 | 5 | export async function squareRect(parent: D3Selection, node: Node) { 6 | const options = { 7 | rx: 0, 8 | ry: 0, 9 | classes: '', 10 | labelPaddingX: node.labelPaddingX ?? (node?.padding || 0) * 2, 11 | labelPaddingY: (node?.padding || 0) * 1, 12 | } as RectOptions; 13 | return drawRect(parent, node, options); 14 | } 15 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/xychart/xychartDetector.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DiagramDetector, 3 | DiagramLoader, 4 | ExternalDiagramDefinition, 5 | } from '../../diagram-api/types.js'; 6 | 7 | const id = 'xychart'; 8 | 9 | const detector: DiagramDetector = (txt) => { 10 | return /^\s*xychart(-beta)?/.test(txt); 11 | }; 12 | 13 | const loader: DiagramLoader = async () => { 14 | const { diagram } = await import('./xychartDiagram.js'); 15 | return { id, diagram }; 16 | }; 17 | 18 | const plugin: ExternalDiagramDefinition = { 19 | id, 20 | detector, 21 | loader, 22 | }; 23 | 24 | export default plugin; 25 | -------------------------------------------------------------------------------- /tsconfig.eslint.json: -------------------------------------------------------------------------------- 1 | { 2 | // extend your base config to share compilerOptions, etc 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | // ensure that nobody can accidentally use this config for a build 6 | "noEmit": true, 7 | "allowJs": true 8 | }, 9 | "include": [ 10 | "./.build/*.ts", 11 | "./.esbuild/*.ts", 12 | "./.vite/*.ts", 13 | "./cypress.config.ts", 14 | "./tests", 15 | "./scripts", 16 | "./cypress", 17 | "./__mocks__", 18 | "./demos/dev", 19 | "./vite.config.ts", 20 | "./vitest.workspace.js", 21 | "eslint.config.js" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /.cspell/mermaid-terms.txt: -------------------------------------------------------------------------------- 1 | Adamiecki 2 | arrowend 3 | Bendpoints 4 | bmatrix 5 | braintree 6 | catmull 7 | compositTitleSize 8 | cose 9 | curv 10 | doublecircle 11 | elem 12 | elems 13 | gantt 14 | gitgraph 15 | gzipped 16 | handDrawn 17 | kanban 18 | marginx 19 | marginy 20 | Markdownish 21 | mermaidchart 22 | mermaidjs 23 | mindmap 24 | mindmaps 25 | mrtree 26 | multigraph 27 | nodesep 28 | NOTEGROUP 29 | Pinterest 30 | procs 31 | rankdir 32 | ranksep 33 | rect 34 | rects 35 | sandboxed 36 | siebling 37 | statediagram 38 | substate 39 | unfixable 40 | Viewbox 41 | viewports 42 | visio 43 | vitepress 44 | xlink 45 | xychart 46 | -------------------------------------------------------------------------------- /docs/config/setup/mermaid/variables/default.md: -------------------------------------------------------------------------------- 1 | > **Warning** 2 | > 3 | > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. 4 | > 5 | > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/mermaid/variables/default.md](../../../../../packages/mermaid/src/docs/config/setup/mermaid/variables/default.md). 6 | 7 | [**mermaid**](../../README.md) 8 | 9 | --- 10 | 11 | # Variable: default 12 | 13 | > `const` **default**: [`Mermaid`](../interfaces/Mermaid.md) 14 | 15 | Defined in: [packages/mermaid/src/mermaid.ts:454](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L454) 16 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/sequence/sequenceDetector.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DiagramDetector, 3 | DiagramLoader, 4 | ExternalDiagramDefinition, 5 | } from '../../diagram-api/types.js'; 6 | 7 | const id = 'sequence'; 8 | 9 | const detector: DiagramDetector = (txt) => { 10 | return /^\s*sequenceDiagram/.test(txt); 11 | }; 12 | 13 | const loader: DiagramLoader = async () => { 14 | const { diagram } = await import('./sequenceDiagram.js'); 15 | return { id, diagram }; 16 | }; 17 | 18 | const plugin: ExternalDiagramDefinition = { 19 | id, 20 | detector, 21 | loader, 22 | }; 23 | 24 | export default plugin; 25 | -------------------------------------------------------------------------------- /packages/tiny/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mermaid-js/tiny", 3 | "version": "11.12.1", 4 | "description": "Tiny version of mermaid", 5 | "type": "commonjs", 6 | "main": "./dist/mermaid.tiny.js", 7 | "scripts": { 8 | "clean": "rimraf dist" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/mermaid-js/mermaid" 13 | }, 14 | "author": "Sidharth Vinod", 15 | "license": "MIT", 16 | "dependencies": {}, 17 | "devDependencies": {}, 18 | "files": [ 19 | "dist/", 20 | "README.md" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/quadrant-chart/quadrantDetector.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DiagramDetector, 3 | DiagramLoader, 4 | ExternalDiagramDefinition, 5 | } from '../../diagram-api/types.js'; 6 | 7 | const id = 'quadrantChart'; 8 | 9 | const detector: DiagramDetector = (txt) => { 10 | return /^\s*quadrantChart/.test(txt); 11 | }; 12 | 13 | const loader: DiagramLoader = async () => { 14 | const { diagram } = await import('./quadrantDiagram.js'); 15 | return { id, diagram }; 16 | }; 17 | 18 | const plugin: ExternalDiagramDefinition = { 19 | id, 20 | detector, 21 | loader, 22 | }; 23 | 24 | export default plugin; 25 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | cff-version: 1.2.0 2 | title: 'Mermaid: Generate diagrams from markdown-like text' 3 | message: >- 4 | If you use this software, please cite it using the metadata from this file. 5 | type: software 6 | authors: 7 | - family-names: Sveidqvist 8 | given-names: Knut 9 | - name: 'Contributors to Mermaid' 10 | repository-code: 'https://github.com/mermaid-js/mermaid' 11 | date-released: 2014-12-02 12 | url: 'https://mermaid.js.org/' 13 | abstract: >- 14 | JavaScript based diagramming and charting tool that renders Markdown-inspired 15 | text definitions to create and modify diagrams dynamically. 16 | license: MIT 17 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/c4/c4Detector.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DiagramDetector, 3 | DiagramLoader, 4 | ExternalDiagramDefinition, 5 | } from '../../diagram-api/types.js'; 6 | 7 | const id = 'c4'; 8 | 9 | const detector: DiagramDetector = (txt) => { 10 | return /^\s*C4Context|C4Container|C4Component|C4Dynamic|C4Deployment/.test(txt); 11 | }; 12 | 13 | const loader: DiagramLoader = async () => { 14 | const { diagram } = await import('./c4Diagram.js'); 15 | return { id, diagram }; 16 | }; 17 | 18 | const plugin: ExternalDiagramDefinition = { 19 | id, 20 | detector, 21 | loader, 22 | }; 23 | 24 | export default plugin; 25 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/git/gitGraphDetector.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramDetector, DiagramLoader } from '../../diagram-api/types.js'; 2 | import type { ExternalDiagramDefinition } from '../../diagram-api/types.js'; 3 | 4 | const id = 'gitGraph'; 5 | 6 | const detector: DiagramDetector = (txt) => { 7 | return /^\s*gitGraph/.test(txt); 8 | }; 9 | 10 | const loader: DiagramLoader = async () => { 11 | const { diagram } = await import('./gitGraphDiagram.js'); 12 | return { id, diagram }; 13 | }; 14 | 15 | const plugin: ExternalDiagramDefinition = { 16 | id, 17 | detector, 18 | loader, 19 | }; 20 | 21 | export default plugin; 22 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/requirement/requirementDetector.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DiagramDetector, 3 | DiagramLoader, 4 | ExternalDiagramDefinition, 5 | } from '../../diagram-api/types.js'; 6 | 7 | const id = 'requirement'; 8 | 9 | const detector: DiagramDetector = (txt) => { 10 | return /^\s*requirement(Diagram)?/.test(txt); 11 | }; 12 | 13 | const loader: DiagramLoader = async () => { 14 | const { diagram } = await import('./requirementDiagram.js'); 15 | return { id, diagram }; 16 | }; 17 | 18 | const plugin: ExternalDiagramDefinition = { 19 | id, 20 | detector, 21 | loader, 22 | }; 23 | 24 | export default plugin; 25 | -------------------------------------------------------------------------------- /docs/config/setup/defaultConfig/variables/configKeys.md: -------------------------------------------------------------------------------- 1 | > **Warning** 2 | > 3 | > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. 4 | > 5 | > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/defaultConfig/variables/configKeys.md](../../../../../packages/mermaid/src/docs/config/setup/defaultConfig/variables/configKeys.md). 6 | 7 | [**mermaid**](../../README.md) 8 | 9 | --- 10 | 11 | # Variable: configKeys 12 | 13 | > `const` **configKeys**: `Set`<`string`> 14 | 15 | Defined in: [packages/mermaid/src/defaultConfig.ts:292](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L292) 16 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/architecture/architectureDetector.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DiagramDetector, 3 | DiagramLoader, 4 | ExternalDiagramDefinition, 5 | } from '../../diagram-api/types.js'; 6 | 7 | const id = 'architecture'; 8 | 9 | const detector: DiagramDetector = (txt) => { 10 | return /^\s*architecture/.test(txt); 11 | }; 12 | 13 | const loader: DiagramLoader = async () => { 14 | const { diagram } = await import('./architectureDiagram.js'); 15 | return { id, diagram }; 16 | }; 17 | 18 | const architecture: ExternalDiagramDefinition = { 19 | id, 20 | detector, 21 | loader, 22 | }; 23 | 24 | export default architecture; 25 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/block/layout.spec.ts: -------------------------------------------------------------------------------- 1 | import { calculateBlockPosition } from './layout.js'; 2 | 3 | describe('Layout', function () { 4 | it('should calculate position correctly', () => { 5 | expect(calculateBlockPosition(2, 0)).toEqual({ px: 0, py: 0 }); 6 | expect(calculateBlockPosition(2, 1)).toEqual({ px: 1, py: 0 }); 7 | expect(calculateBlockPosition(2, 2)).toEqual({ px: 0, py: 1 }); 8 | expect(calculateBlockPosition(2, 3)).toEqual({ px: 1, py: 1 }); 9 | expect(calculateBlockPosition(2, 4)).toEqual({ px: 0, py: 2 }); 10 | expect(calculateBlockPosition(1, 3)).toEqual({ px: 0, py: 3 }); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /.github/workflows/issue-triage.yml: -------------------------------------------------------------------------------- 1 | name: Apply triage label to new issue 2 | 3 | on: 4 | issues: 5 | types: [opened] 6 | 7 | permissions: # added using https://github.com/step-security/secure-repo 8 | contents: read 9 | 10 | jobs: 11 | triage: 12 | permissions: 13 | issues: write # for andymckay/labeler to label issues 14 | pull-requests: write # for andymckay/labeler to label PRs 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: andymckay/labeler@e6c4322d0397f3240f0e7e30a33b5c5df2d39e90 # 1.0.4 18 | with: 19 | repo-token: '${{ secrets.GITHUB_TOKEN }}' 20 | add-labels: 'Status: Triage' 21 | -------------------------------------------------------------------------------- /docs/config/setup/mermaid/type-aliases/InternalHelpers.md: -------------------------------------------------------------------------------- 1 | > **Warning** 2 | > 3 | > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. 4 | > 5 | > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/mermaid/type-aliases/InternalHelpers.md](../../../../../packages/mermaid/src/docs/config/setup/mermaid/type-aliases/InternalHelpers.md). 6 | 7 | [**mermaid**](../../README.md) 8 | 9 | --- 10 | 11 | # Type Alias: InternalHelpers 12 | 13 | > **InternalHelpers** = _typeof_ `internalHelpers` 14 | 15 | Defined in: [packages/mermaid/src/internals.ts:33](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/internals.ts#L33) 16 | -------------------------------------------------------------------------------- /packages/examples/src/examples/user-journey.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramMetadata } from '../types.js'; 2 | 3 | export default { 4 | id: 'journey', 5 | name: 'User Journey Diagram', 6 | description: 'Visualize user interactions and experiences with a system', 7 | examples: [ 8 | { 9 | title: 'My Working Day', 10 | isDefault: true, 11 | code: `journey 12 | title My working day 13 | section Go to work 14 | Make tea: 5: Me 15 | Go upstairs: 3: Me 16 | Do work: 1: Me, Cat 17 | section Go home 18 | Go downstairs: 5: Me 19 | Sit down: 5: Me`, 20 | }, 21 | ], 22 | } satisfies DiagramMetadata; 23 | -------------------------------------------------------------------------------- /docs/config/setup/mermaid/type-aliases/SVG.md: -------------------------------------------------------------------------------- 1 | > **Warning** 2 | > 3 | > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. 4 | > 5 | > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/mermaid/type-aliases/SVG.md](../../../../../packages/mermaid/src/docs/config/setup/mermaid/type-aliases/SVG.md). 6 | 7 | [**mermaid**](../../README.md) 8 | 9 | --- 10 | 11 | # Type Alias: SVG 12 | 13 | > **SVG** = `d3.Selection`<`SVGSVGElement`, `unknown`, `Element` | `null`, `unknown`> 14 | 15 | Defined in: [packages/mermaid/src/diagram-api/types.ts:128](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L128) 16 | -------------------------------------------------------------------------------- /packages/examples/src/examples/radar.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramMetadata } from '../types.js'; 2 | 3 | export default { 4 | id: 'radar', 5 | name: 'Radar Diagram', 6 | description: 'Visualize data in a radial format', 7 | examples: [ 8 | { 9 | title: 'Student Grades', 10 | isDefault: true, 11 | code: `--- 12 | title: "Grades" 13 | --- 14 | radar-beta 15 | axis m["Math"], s["Science"], e["English"] 16 | axis h["History"], g["Geography"], a["Art"] 17 | curve a["Alice"]{85, 90, 80, 70, 75, 90} 18 | curve b["Bob"]{70, 75, 85, 80, 90, 85} 19 | 20 | max 100 21 | min 0 22 | `, 23 | }, 24 | ], 25 | } satisfies DiagramMetadata; 26 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/xychart/chartBuilder/index.ts: -------------------------------------------------------------------------------- 1 | import type { SVGGroup } from '../../../diagram-api/types.js'; 2 | import type { DrawableElem, XYChartConfig, XYChartData, XYChartThemeConfig } from './interfaces.js'; 3 | import { Orchestrator } from './orchestrator.js'; 4 | 5 | export class XYChartBuilder { 6 | static build( 7 | config: XYChartConfig, 8 | chartData: XYChartData, 9 | chartThemeConfig: XYChartThemeConfig, 10 | tmpSVGGroup: SVGGroup 11 | ): DrawableElem[] { 12 | const orchestrator = new Orchestrator(config, chartData, chartThemeConfig, tmpSVGGroup); 13 | return orchestrator.getDrawableElement(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /docs/config/setup/config/variables/defaultConfig.md: -------------------------------------------------------------------------------- 1 | > **Warning** 2 | > 3 | > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. 4 | > 5 | > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/config/variables/defaultConfig.md](../../../../../packages/mermaid/src/docs/config/setup/config/variables/defaultConfig.md). 6 | 7 | [**mermaid**](../../README.md) 8 | 9 | --- 10 | 11 | # Variable: defaultConfig 12 | 13 | > `const` **defaultConfig**: [`MermaidConfig`](../../mermaid/interfaces/MermaidConfig.md) 14 | 15 | Defined in: [packages/mermaid/src/config.ts:8](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L8) 16 | -------------------------------------------------------------------------------- /docs/public/icons/public.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/sankey/sankeyDiagram.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramDefinition } from '../../diagram-api/types.js'; 2 | // @ts-ignore: jison doesn't export types 3 | import parser from './parser/sankey.jison'; 4 | import db from './sankeyDB.js'; 5 | import renderer from './sankeyRenderer.js'; 6 | import { prepareTextForParsing } from './sankeyUtils.js'; 7 | import sankeyStyles from './styles.js'; 8 | 9 | const originalParse = parser.parse.bind(parser); 10 | parser.parse = (text: string) => originalParse(prepareTextForParsing(text)); 11 | 12 | export const diagram: DiagramDefinition = { 13 | styles: sankeyStyles, 14 | parser, 15 | db, 16 | renderer, 17 | }; 18 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/state/stateDiagram.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramDefinition } from '../../diagram-api/types.js'; 2 | // @ts-ignore: JISON doesn't support types 3 | import parser from './parser/stateDiagram.jison'; 4 | import { StateDB } from './stateDb.js'; 5 | import styles from './styles.js'; 6 | import renderer from './stateRenderer.js'; 7 | 8 | export const diagram: DiagramDefinition = { 9 | parser, 10 | get db() { 11 | return new StateDB(1); 12 | }, 13 | renderer, 14 | styles, 15 | init: (cnf) => { 16 | if (!cnf.state) { 17 | cnf.state = {}; 18 | } 19 | cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /packages/examples/src/examples/gantt.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramMetadata } from '../types.js'; 2 | 3 | export default { 4 | id: 'gantt', 5 | name: 'Gantt Chart', 6 | description: 'Visualize project schedules and timelines', 7 | examples: [ 8 | { 9 | title: 'Basic Project Timeline', 10 | isDefault: true, 11 | code: `gantt 12 | title A Gantt Diagram 13 | dateFormat YYYY-MM-DD 14 | section Section 15 | A task :a1, 2014-01-01, 30d 16 | Another task :after a1 , 20d 17 | section Another 18 | Task in sec :2014-01-12 , 12d 19 | another task : 24d`, 20 | }, 21 | ], 22 | } satisfies DiagramMetadata; 23 | -------------------------------------------------------------------------------- /packages/mermaid/src/rendering-util/rendering-elements/shapes/insertPolygonShape.ts: -------------------------------------------------------------------------------- 1 | import type { D3Selection } from '../../../types.js'; 2 | 3 | export function insertPolygonShape( 4 | parent: D3Selection, 5 | w: number, 6 | h: number, 7 | points: { x: number; y: number }[] 8 | ) { 9 | return parent 10 | .insert('polygon', ':first-child') 11 | .attr( 12 | 'points', 13 | points 14 | .map(function (d) { 15 | return d.x + ',' + d.y; 16 | }) 17 | .join(' ') 18 | ) 19 | .attr('class', 'label-container') 20 | .attr('transform', 'translate(' + -w / 2 + ',' + h / 2 + ')'); 21 | } 22 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/class/classDiagram.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramDefinition } from '../../diagram-api/types.js'; 2 | // @ts-ignore: JISON doesn't support types 3 | import parser from './parser/classDiagram.jison'; 4 | import { ClassDB } from './classDb.js'; 5 | import styles from './styles.js'; 6 | import renderer from './classRenderer-v3-unified.js'; 7 | 8 | export const diagram: DiagramDefinition = { 9 | parser, 10 | get db() { 11 | return new ClassDB(); 12 | }, 13 | renderer, 14 | styles, 15 | init: (cnf) => { 16 | if (!cnf.class) { 17 | cnf.class = {}; 18 | } 19 | cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /docs/config/setup/mermaid/type-aliases/SVGGroup.md: -------------------------------------------------------------------------------- 1 | > **Warning** 2 | > 3 | > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. 4 | > 5 | > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/mermaid/type-aliases/SVGGroup.md](../../../../../packages/mermaid/src/docs/config/setup/mermaid/type-aliases/SVGGroup.md). 6 | 7 | [**mermaid**](../../README.md) 8 | 9 | --- 10 | 11 | # Type Alias: SVGGroup 12 | 13 | > **SVGGroup** = `d3.Selection`<`SVGGElement`, `unknown`, `Element` | `null`, `unknown`> 14 | 15 | Defined in: [packages/mermaid/src/diagram-api/types.ts:130](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L130) 16 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/class/classDiagram-v2.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramDefinition } from '../../diagram-api/types.js'; 2 | // @ts-ignore: JISON doesn't support types 3 | import parser from './parser/classDiagram.jison'; 4 | import { ClassDB } from './classDb.js'; 5 | import styles from './styles.js'; 6 | import renderer from './classRenderer-v3-unified.js'; 7 | 8 | export const diagram: DiagramDefinition = { 9 | parser, 10 | get db() { 11 | return new ClassDB(); 12 | }, 13 | renderer, 14 | styles, 15 | init: (cnf) => { 16 | if (!cnf.class) { 17 | cnf.class = {}; 18 | } 19 | cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/state/stateDiagram-v2.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramDefinition } from '../../diagram-api/types.js'; 2 | // @ts-ignore: JISON doesn't support types 3 | import parser from './parser/stateDiagram.jison'; 4 | import { StateDB } from './stateDb.js'; 5 | import styles from './styles.js'; 6 | import renderer from './stateRenderer-v3-unified.js'; 7 | 8 | export const diagram: DiagramDefinition = { 9 | parser, 10 | get db() { 11 | return new StateDB(2); 12 | }, 13 | renderer, 14 | styles, 15 | init: (cnf) => { 16 | if (!cnf.state) { 17 | cnf.state = {}; 18 | } 19 | cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /packages/mermaid/src/docs/public/icons/public.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /.github/pr-labeler.yml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/release-drafter/release-drafter/master/schema.json 2 | autolabeler: 3 | - label: 'Type: Bug / Error' 4 | branch: 5 | - '/bug\/.+/' 6 | - '/fix\/.+/' 7 | - label: 'Type: Enhancement' 8 | branch: 9 | - '/feature\/.+/' 10 | - '/feat\/.+/' 11 | - label: 'Type: Other' 12 | branch: 13 | - '/other\/.+/' 14 | - '/chore\/.+/' 15 | - '/test\/.+/' 16 | - '/refactor\/.+/' 17 | - label: 'Area: Documentation' 18 | branch: 19 | - '/docs\/.+/' 20 | 21 | template: | 22 | This field is unused, as we only use this config file for labeling PRs. 23 | -------------------------------------------------------------------------------- /cypress/integration/other/rerender.spec.js: -------------------------------------------------------------------------------- 1 | describe('Rerendering', () => { 2 | it('should be able to render after an error has occurred', () => { 3 | const url = 'http://localhost:9000/render-after-error.html'; 4 | cy.visit(url); 5 | cy.get('#graphDiv').should('exist'); 6 | }); 7 | 8 | it('should be able to render and rerender a graph via API', () => { 9 | const url = 'http://localhost:9000/rerender.html'; 10 | cy.visit(url); 11 | cy.get('#graph [id^=flowchart-A]').should('have.text', 'XMas'); 12 | 13 | cy.get('body').find('#rerender').click({ force: true }); 14 | 15 | cy.get('#graph [id^=flowchart-A]').should('have.text', 'Saturday'); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/examples/src/examples/block.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramMetadata } from '../types.js'; 2 | 3 | export default { 4 | id: 'block', 5 | name: 'Block Diagram', 6 | description: 'Create block-based visualizations with beta styling', 7 | examples: [ 8 | { 9 | title: 'Basic Block Layout', 10 | isDefault: true, 11 | code: `block-beta 12 | columns 1 13 | db(("DB")) 14 | blockArrowId6<["   "]>(down) 15 | block:ID 16 | A 17 | B["A wide one in the middle"] 18 | C 19 | end 20 | space 21 | D 22 | ID --> D 23 | C --> D 24 | style B fill:#969,stroke:#333,stroke-width:4px`, 25 | }, 26 | ], 27 | } satisfies DiagramMetadata; 28 | -------------------------------------------------------------------------------- /packages/examples/src/examples/git.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramMetadata } from '../types.js'; 2 | 3 | export default { 4 | id: 'gitGraph', 5 | name: 'Git Graph', 6 | description: 'Visualize Git repository history and branch relationships', 7 | examples: [ 8 | { 9 | title: 'Basic Git Flow', 10 | isDefault: true, 11 | code: `gitGraph 12 | commit 13 | branch develop 14 | checkout develop 15 | commit 16 | commit 17 | checkout main 18 | merge develop 19 | commit 20 | branch feature 21 | checkout feature 22 | commit 23 | commit 24 | checkout main 25 | merge feature`, 26 | }, 27 | ], 28 | } satisfies DiagramMetadata; 29 | -------------------------------------------------------------------------------- /packages/examples/src/examples/requirement.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramMetadata } from '../types.js'; 2 | 3 | export default { 4 | id: 'requirement', 5 | name: 'Requirement Diagram', 6 | description: 'Visualize system requirements and their relationships', 7 | examples: [ 8 | { 9 | title: 'Basic Requirements', 10 | code: `requirementDiagram 11 | 12 | requirement test_req { 13 | id: 1 14 | text: the test text. 15 | risk: high 16 | verifymethod: test 17 | } 18 | 19 | element test_entity { 20 | type: simulation 21 | } 22 | 23 | test_entity - satisfies -> test_req`, 24 | isDefault: true, 25 | }, 26 | ], 27 | } satisfies DiagramMetadata; 28 | -------------------------------------------------------------------------------- /packages/mermaid-example-diagram/src/styles.js: -------------------------------------------------------------------------------- 1 | const genSections = (options) => { 2 | let sections = ''; 3 | 4 | for (let i = 0; i < options.THEME_COLOR_LIMIT; i++) { 5 | sections += ` 6 | .section-${i} rect { 7 | fill: ${options['cScale' + i]}; 8 | stroke: ${options['cScalePeer' + i]}; 9 | stroke-width: 4; 10 | } 11 | .section-${i} rect.inverted { 12 | fill: ${options['cScaleInv' + i]}; 13 | } 14 | .section-${i} text { 15 | fill: ${options['cScaleLabel' + i]}; 16 | } 17 | 18 | `; 19 | } 20 | return sections; 21 | }; 22 | 23 | const getStyles = (options) => 24 | ` 25 | ${genSections(options)} 26 | `; 27 | export default getStyles; 28 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagram-api/regexes.ts: -------------------------------------------------------------------------------- 1 | // Match Jekyll-style front matter blocks (https://jekyllrb.com/docs/front-matter/). 2 | // Based on regex used by Jekyll: https://github.com/jekyll/jekyll/blob/6dd3cc21c40b98054851846425af06c64f9fb466/lib/jekyll/document.rb#L10 3 | // Note that JS doesn't support the "\A" anchor, which means we can't use 4 | // multiline mode. 5 | // Relevant YAML spec: https://yaml.org/spec/1.2.2/#914-explicit-documents 6 | export const frontMatterRegex = /^-{3}\s*[\n\r](.*?)[\n\r]-{3}\s*[\n\r]+/s; 7 | 8 | export const directiveRegex = 9 | /%{2}{\s*(?:(\w+)\s*:|(\w+))\s*(?:(\w+)|((?:(?!}%{2}).|\r?\n)*))?\s*(?:}%{2})?/gi; 10 | 11 | export const anyCommentRegex = /\s*%%.*\n/gm; 12 | -------------------------------------------------------------------------------- /packages/mermaid/src/rendering-util/rendering-elements/intersect/intersect-ellipse.js: -------------------------------------------------------------------------------- 1 | function intersectEllipse(node, rx, ry, point) { 2 | // Formulae from: https://mathworld.wolfram.com/Ellipse-LineIntersection.html 3 | 4 | var cx = node.x; 5 | var cy = node.y; 6 | 7 | var px = cx - point.x; 8 | var py = cy - point.y; 9 | 10 | var det = Math.sqrt(rx * rx * py * py + ry * ry * px * px); 11 | 12 | var dx = Math.abs((rx * ry * px) / det); 13 | if (point.x < cx) { 14 | dx = -dx; 15 | } 16 | var dy = Math.abs((rx * ry * py) / det); 17 | if (point.y < cy) { 18 | dy = -dy; 19 | } 20 | 21 | return { x: cx + dx, y: cy + dy }; 22 | } 23 | 24 | export default intersectEllipse; 25 | -------------------------------------------------------------------------------- /docs/public/mermaid-logo-horizontal.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /scripts/coverage.ts: -------------------------------------------------------------------------------- 1 | import { execSync } from 'child_process'; 2 | import { cp } from 'fs/promises'; 3 | 4 | const main = async () => { 5 | const coverageDir = 'coverage'; 6 | const coverageFiles = ['vitest', 'cypress'].map( 7 | (dir) => `${coverageDir}/${dir}/coverage-final.json` 8 | ); 9 | 10 | //copy coverage files from vitest and cypress to coverage folder 11 | await Promise.all( 12 | coverageFiles.map((file) => cp(file, `${coverageDir}/combined/${file.split('/')[1]}.json`)) 13 | ); 14 | 15 | execSync('npx nyc merge coverage/combined coverage/combined-final.json'); 16 | execSync('npx nyc report -t coverage --report-dir coverage/html --reporter=html-spa'); 17 | }; 18 | 19 | void main(); 20 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/quadrant-chart/utils.ts: -------------------------------------------------------------------------------- 1 | class InvalidStyleError extends Error { 2 | constructor(style: string, value: string, type: string) { 3 | super(`value for ${style} ${value} is invalid, please use a valid ${type}`); 4 | this.name = 'InvalidStyleError'; 5 | } 6 | } 7 | 8 | function validateHexCode(value: string): boolean { 9 | return !/^#?([\dA-Fa-f]{6}|[\dA-Fa-f]{3})$/.test(value); 10 | } 11 | 12 | function validateNumber(value: string): boolean { 13 | return !/^\d+$/.test(value); 14 | } 15 | 16 | function validateSizeInPixels(value: string): boolean { 17 | return !/^\d+px$/.test(value); 18 | } 19 | 20 | export { validateHexCode, validateNumber, validateSizeInPixels, InvalidStyleError }; 21 | -------------------------------------------------------------------------------- /packages/mermaid/src/docs/config/layouts.md: -------------------------------------------------------------------------------- 1 | # Layouts 2 | 3 | This page lists the available layout algorithms supported in Mermaid diagrams. 4 | 5 | ## Supported Layouts 6 | 7 | - **elk**: [ELK (Eclipse Layout Kernel)](https://www.eclipse.org/elk/) 8 | - **tidy-tree**: Tidy tree layout for hierarchical diagrams [Tidy Tree Configuration](/config/tidy-tree) 9 | - **cose-bilkent**: Cose Bilkent layout for force-directed graphs 10 | - **dagre**: Dagre layout for layered graphs 11 | 12 | ## How to Use 13 | 14 | You can specify the layout in your diagram's YAML config or initialization options. For example: 15 | 16 | ```mermaid 17 | --- 18 | config: 19 | layout: elk 20 | --- 21 | graph TD; 22 | A-->B; 23 | B-->C; 24 | ``` 25 | -------------------------------------------------------------------------------- /packages/parser/tests/packet.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | 3 | import { Packet } from '../src/language/index.js'; 4 | import { expectNoErrorsOrAlternatives, packetParse as parse } from './test-util.js'; 5 | 6 | describe('packet', () => { 7 | it.each([ 8 | `packet-beta`, 9 | ` packet-beta `, 10 | `\tpacket-beta\t`, 11 | ` 12 | \tpacket-beta 13 | `, 14 | `packet`, 15 | ` packet `, 16 | `\tpacket\t`, 17 | ` 18 | \tpacket 19 | `, 20 | ])('should handle regular packet', (context: string) => { 21 | const result = parse(context); 22 | expectNoErrorsOrAlternatives(result); 23 | expect(result.value.$type).toBe(Packet); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/git/parser/desired syntax: -------------------------------------------------------------------------------- 1 | commit 2 | branch develop 3 | checkout develop 4 | commit 5 | branch featureB 6 | checkout featureB 7 | commit 8 | checkout master 9 | branch hotfix 10 | checkout hotfix 11 | commit 12 | checkout develop 13 | commit 14 | checkout featureB 15 | commit 16 | checkout master 17 | merge hotfix 18 | checkout featureB 19 | commit 20 | checkout develop 21 | branch featureA 22 | commit 23 | checkout develop 24 | merge hotfix 25 | checkout featureA 26 | commit 27 | checkout featureB 28 | commit 29 | checkout develop 30 | merge featureA 31 | branch release 32 | checkout release 33 | commit 34 | checkout master 35 | commit 36 | checkout release 37 | merge master 38 | checkout develop 39 | merge release -------------------------------------------------------------------------------- /packages/mermaid/src/docs/public/mermaid-logo-horizontal.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /packages/mermaid/src/utils/subGraphTitleMargins.spec.ts: -------------------------------------------------------------------------------- 1 | import { getSubGraphTitleMargins } from './subGraphTitleMargins.js'; 2 | import * as configApi from '../config.js'; 3 | 4 | describe('getSubGraphTitleMargins', () => { 5 | it('should get subgraph title margins after config has been set', () => { 6 | const config_0 = { 7 | flowchart: { 8 | subGraphTitleMargin: { 9 | top: 10, 10 | bottom: 5, 11 | }, 12 | }, 13 | }; 14 | 15 | configApi.setSiteConfig(config_0); 16 | expect(getSubGraphTitleMargins(config_0)).toEqual({ 17 | subGraphTitleTopMargin: 10, 18 | subGraphTitleBottomMargin: 5, 19 | subGraphTitleTotalMargin: 15, 20 | }); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /demos/dev/reload.js: -------------------------------------------------------------------------------- 1 | // Connect to the server and reload the page if the server sends a reload message 2 | const connectToEvents = () => { 3 | const events = new EventSource('/events'); 4 | const loadTime = Date.now(); 5 | events.onmessage = (event) => { 6 | const time = JSON.parse(event.data); 7 | if (time && time > loadTime) { 8 | location.reload(); 9 | } 10 | }; 11 | events.onerror = (error) => { 12 | console.error(error); 13 | events.close(); 14 | // Try to reconnect after 1 second in case of errors 15 | setTimeout(connectToEvents, 1000); 16 | }; 17 | events.onopen = () => { 18 | console.log('Connected to live reload server'); 19 | }; 20 | }; 21 | 22 | setTimeout(connectToEvents, 500); 23 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: 4 | - knsv 5 | - sidharthv96 6 | #patreon: # Replace with a single Patreon username 7 | #open_collective: # Replace with a single Open Collective username 8 | #ko_fi: # Replace with a single Ko-fi username 9 | #tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 10 | #community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 11 | #liberapay: # Replace with a single Liberapay username 12 | #issuehunt: # Replace with a single IssueHunt username 13 | #otechie: # Replace with a single Otechie username 14 | #custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 15 | -------------------------------------------------------------------------------- /cypress/platform/iife.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
 4 | graph TB
 5 |       a --> b
 6 |       a --> c
 7 |       b --> d
 8 |       c --> d
 9 |     
10 | 11 |
12 | 13 | 14 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /packages/examples/src/examples/architecture.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramMetadata } from '../types.js'; 2 | 3 | export default { 4 | id: 'architecture', 5 | name: 'Architecture Diagram', 6 | description: 'Visualize system architecture and components', 7 | examples: [ 8 | { 9 | title: 'Basic System Architecture', 10 | isDefault: true, 11 | code: `architecture-beta 12 | group api(cloud)[API] 13 | 14 | service db(database)[Database] in api 15 | service disk1(disk)[Storage] in api 16 | service disk2(disk)[Storage] in api 17 | service server(server)[Server] in api 18 | 19 | db:L -- R:server 20 | disk1:T -- B:server 21 | disk2:T -- B:db`, 22 | }, 23 | ], 24 | } satisfies DiagramMetadata; 25 | -------------------------------------------------------------------------------- /packages/examples/src/examples/xychart.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramMetadata } from '../types.js'; 2 | 3 | export default { 4 | id: 'xychart', 5 | name: 'XY Chart', 6 | description: 'Create scatter plots and line charts with customizable axes', 7 | examples: [ 8 | { 9 | title: 'Sales Revenue', 10 | isDefault: true, 11 | code: `xychart-beta 12 | title "Sales Revenue" 13 | x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] 14 | y-axis "Revenue (in $)" 4000 --> 11000 15 | bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] 16 | line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]`, 17 | }, 18 | ], 19 | } satisfies DiagramMetadata; 20 | -------------------------------------------------------------------------------- /packages/mermaid/src/docs/.vitepress/components/Contributors.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 28 | -------------------------------------------------------------------------------- /packages/mermaid/src/utils/subGraphTitleMargins.ts: -------------------------------------------------------------------------------- 1 | import type { FlowchartDiagramConfig } from '../config.type.js'; 2 | 3 | export const getSubGraphTitleMargins = ({ 4 | flowchart, 5 | }: { 6 | flowchart: FlowchartDiagramConfig; 7 | }): { 8 | subGraphTitleTopMargin: number; 9 | subGraphTitleBottomMargin: number; 10 | subGraphTitleTotalMargin: number; 11 | } => { 12 | const subGraphTitleTopMargin = flowchart?.subGraphTitleMargin?.top ?? 0; 13 | const subGraphTitleBottomMargin = flowchart?.subGraphTitleMargin?.bottom ?? 0; 14 | const subGraphTitleTotalMargin = subGraphTitleTopMargin + subGraphTitleBottomMargin; 15 | 16 | return { 17 | subGraphTitleTopMargin, 18 | subGraphTitleBottomMargin, 19 | subGraphTitleTotalMargin, 20 | }; 21 | }; 22 | -------------------------------------------------------------------------------- /cypress/platform/flow-elk.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
 4 |       flowchart-elk
 5 |       a[hello] --> b[world]
 6 |       b --> c{test}
 7 |       c --> one
 8 |       c --> two
 9 |       c --> three
10 |     
11 | 12 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /packages/mermaid/src/dagre-wrapper/intersect/intersect-ellipse.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param node 3 | * @param rx 4 | * @param ry 5 | * @param point 6 | */ 7 | function intersectEllipse(node, rx, ry, point) { 8 | // Formulae from: https://mathworld.wolfram.com/Ellipse-LineIntersection.html 9 | 10 | var cx = node.x; 11 | var cy = node.y; 12 | 13 | var px = cx - point.x; 14 | var py = cy - point.y; 15 | 16 | var det = Math.sqrt(rx * rx * py * py + ry * ry * px * px); 17 | 18 | var dx = Math.abs((rx * ry * px) / det); 19 | if (point.x < cx) { 20 | dx = -dx; 21 | } 22 | var dy = Math.abs((rx * ry * py) / det); 23 | if (point.y < cy) { 24 | dy = -dy; 25 | } 26 | 27 | return { x: cx + dx, y: cy + dy }; 28 | } 29 | 30 | export default intersectEllipse; 31 | -------------------------------------------------------------------------------- /packages/parser/src/language/architecture/valueConverter.ts: -------------------------------------------------------------------------------- 1 | import type { CstNode, GrammarAST, ValueType } from 'langium'; 2 | 3 | import { AbstractMermaidValueConverter } from '../common/index.js'; 4 | 5 | export class ArchitectureValueConverter extends AbstractMermaidValueConverter { 6 | protected runCustomConverter( 7 | rule: GrammarAST.AbstractRule, 8 | input: string, 9 | _cstNode: CstNode 10 | ): ValueType | undefined { 11 | if (rule.name === 'ARCH_ICON') { 12 | return input.replace(/[()]/g, '').trim(); 13 | } else if (rule.name === 'ARCH_TEXT_ICON') { 14 | return input.replace(/["()]/g, ''); 15 | } else if (rule.name === 'ARCH_TITLE') { 16 | return input.replace(/[[\]]/g, '').trim(); 17 | } 18 | return undefined; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /docs/config/setup/config/functions/getUserDefinedConfig.md: -------------------------------------------------------------------------------- 1 | > **Warning** 2 | > 3 | > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. 4 | > 5 | > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/config/functions/getUserDefinedConfig.md](../../../../../packages/mermaid/src/docs/config/setup/config/functions/getUserDefinedConfig.md). 6 | 7 | [**mermaid**](../../README.md) 8 | 9 | --- 10 | 11 | # Function: getUserDefinedConfig() 12 | 13 | > **getUserDefinedConfig**(): [`MermaidConfig`](../../mermaid/interfaces/MermaidConfig.md) 14 | 15 | Defined in: [packages/mermaid/src/config.ts:252](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L252) 16 | 17 | ## Returns 18 | 19 | [`MermaidConfig`](../../mermaid/interfaces/MermaidConfig.md) 20 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | # Settings in the [build] context are global and are applied to 2 | # all contexts unless otherwise overridden by more specific contexts. 3 | [build] 4 | # Directory where the build system installs dependencies 5 | # and runs your build. Store your package.json, .nvmrc, etc here. 6 | # If not set, defaults to the root directory. 7 | base = "" 8 | 9 | # Directory that contains the deploy-ready HTML files and 10 | # assets generated by the build. This is an absolute path relative 11 | # to the base directory, which is the root by default (/). 12 | # This sample publishes the directory located at the absolute 13 | # path "root/project/build-output" 14 | 15 | publish = "mermaid-live-editor/docs" 16 | 17 | # Default build command. 18 | command = "./scripts/editor.bash" 19 | -------------------------------------------------------------------------------- /packages/mermaid-example-diagram/src/exampleDiagramDb.js: -------------------------------------------------------------------------------- 1 | /** Created by knut on 15-01-14. */ 2 | import { log } from './mermaidUtils.js'; 3 | 4 | var message = ''; 5 | var info = false; 6 | 7 | export const setMessage = (txt) => { 8 | log.debug('Setting message to: ' + txt); 9 | message = txt; 10 | }; 11 | 12 | export const getMessage = () => { 13 | return message; 14 | }; 15 | 16 | /** 17 | * Sets the info flag 18 | * 19 | * @param {boolean} inf 20 | */ 21 | export const setInfo = (inf) => { 22 | info = inf; 23 | }; 24 | 25 | export const getInfo = () => { 26 | return info; 27 | }; 28 | 29 | export const clear = () => { 30 | message = ''; 31 | info = false; 32 | }; 33 | 34 | export default { 35 | setMessage, 36 | getMessage, 37 | setInfo, 38 | getInfo, 39 | clear, 40 | }; 41 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/state/stateDetector-V2.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DiagramDetector, 3 | DiagramLoader, 4 | ExternalDiagramDefinition, 5 | } from '../../diagram-api/types.js'; 6 | 7 | const id = 'stateDiagram'; 8 | 9 | const detector: DiagramDetector = (txt, config) => { 10 | if (/^\s*stateDiagram-v2/.test(txt)) { 11 | return true; 12 | } 13 | if (/^\s*stateDiagram/.test(txt) && config?.state?.defaultRenderer === 'dagre-wrapper') { 14 | return true; 15 | } 16 | return false; 17 | }; 18 | 19 | const loader: DiagramLoader = async () => { 20 | const { diagram } = await import('./stateDiagram-v2.js'); 21 | return { id, diagram }; 22 | }; 23 | 24 | const plugin: ExternalDiagramDefinition = { 25 | id, 26 | detector, 27 | loader, 28 | }; 29 | 30 | export default plugin; 31 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/pie/pieParser.ts: -------------------------------------------------------------------------------- 1 | import type { Pie } from '@mermaid-js/parser'; 2 | import { parse } from '@mermaid-js/parser'; 3 | import { log } from '../../logger.js'; 4 | import type { ParserDefinition } from '../../diagram-api/types.js'; 5 | import { populateCommonDb } from '../common/populateCommonDb.js'; 6 | import type { PieDB } from './pieTypes.js'; 7 | import { db } from './pieDb.js'; 8 | 9 | const populateDb = (ast: Pie, db: PieDB) => { 10 | populateCommonDb(ast, db); 11 | db.setShowData(ast.showData); 12 | ast.sections.map(db.addSection); 13 | }; 14 | 15 | export const parser: ParserDefinition = { 16 | parse: async (input: string): Promise => { 17 | const ast: Pie = await parse('pie', input); 18 | log.debug(ast); 19 | populateDb(ast, db); 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /docs/config/setup/config/functions/saveConfigFromInitialize.md: -------------------------------------------------------------------------------- 1 | > **Warning** 2 | > 3 | > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. 4 | > 5 | > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/config/functions/saveConfigFromInitialize.md](../../../../../packages/mermaid/src/docs/config/setup/config/functions/saveConfigFromInitialize.md). 6 | 7 | [**mermaid**](../../README.md) 8 | 9 | --- 10 | 11 | # Function: saveConfigFromInitialize() 12 | 13 | > **saveConfigFromInitialize**(`conf`): `void` 14 | 15 | Defined in: [packages/mermaid/src/config.ts:75](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L75) 16 | 17 | ## Parameters 18 | 19 | ### conf 20 | 21 | [`MermaidConfig`](../../mermaid/interfaces/MermaidConfig.md) 22 | 23 | ## Returns 24 | 25 | `void` 26 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/er/erTypes.ts: -------------------------------------------------------------------------------- 1 | export interface EntityNode { 2 | id: string; 3 | label: string; 4 | attributes: Attribute[]; 5 | alias: string; 6 | shape: string; 7 | look?: string; 8 | cssClasses?: string; 9 | cssStyles?: string[]; 10 | cssCompiledStyles?: string[]; 11 | } 12 | 13 | export interface Attribute { 14 | type: string; 15 | name: string; 16 | keys: ('PK' | 'FK' | 'UK')[]; 17 | comment: string; 18 | } 19 | 20 | export interface Relationship { 21 | entityA: string; 22 | roleA: string; 23 | entityB: string; 24 | relSpec: RelSpec; 25 | } 26 | 27 | export interface RelSpec { 28 | cardA: string; 29 | cardB: string; 30 | relType: string; 31 | } 32 | 33 | export interface EntityClass { 34 | id: string; 35 | styles: string[]; 36 | textStyles: string[]; 37 | } 38 | -------------------------------------------------------------------------------- /packages/mermaid/src/docs/.vitepress/theme/custom.css: -------------------------------------------------------------------------------- 1 | @import 'font-awesome/css/font-awesome.min.css'; 2 | @import '@mdi/font/css/materialdesignicons.min.css'; 3 | 4 | /* Colors: Brand */ 5 | :root { 6 | /* use for colored text */ 7 | --vp-c-pink-1: #e0095f; 8 | 9 | /* use for hover state of button */ 10 | --vp-c-pink-2: #b0134a; 11 | 12 | /* use for background button color */ 13 | --vp-c-pink-3: #e0095f; 14 | 15 | /* use for custom container or badges */ 16 | --vp-c-pink-4: rgba(159, 122, 234, 0.14); 17 | } 18 | 19 | :root { 20 | --vp-c-brand-1: var(--vp-c-pink-1); 21 | --vp-c-brand-2: var(--vp-c-pink-2); 22 | --vp-c-brand-3: var(--vp-c-pink-3); 23 | } 24 | 25 | .vp-doc > div { 26 | width: 100%; 27 | } 28 | 29 | a.edit { 30 | margin: 12px; 31 | position: relative; 32 | top: 10px; 33 | } 34 | -------------------------------------------------------------------------------- /packages/mermaid/src/themes/index.js: -------------------------------------------------------------------------------- 1 | import { getThemeVariables as baseThemeVariables } from './theme-base.js'; 2 | import { getThemeVariables as darkThemeVariables } from './theme-dark.js'; 3 | import { getThemeVariables as defaultThemeVariables } from './theme-default.js'; 4 | import { getThemeVariables as forestThemeVariables } from './theme-forest.js'; 5 | import { getThemeVariables as neutralThemeVariables } from './theme-neutral.js'; 6 | 7 | export default { 8 | base: { 9 | getThemeVariables: baseThemeVariables, 10 | }, 11 | dark: { 12 | getThemeVariables: darkThemeVariables, 13 | }, 14 | default: { 15 | getThemeVariables: defaultThemeVariables, 16 | }, 17 | forest: { 18 | getThemeVariables: forestThemeVariables, 19 | }, 20 | neutral: { 21 | getThemeVariables: neutralThemeVariables, 22 | }, 23 | }; 24 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | mermaid: 3 | build: 4 | context: . 5 | dockerfile: Dockerfile 6 | stdin_open: true 7 | tty: true 8 | working_dir: /mermaid 9 | mem_limit: '8G' 10 | volumes: 11 | - ./:/mermaid 12 | - root_cache:/root/.cache 13 | - root_local:/root/.local 14 | - root_npm:/root/.npm 15 | - /tmp:/tmp 16 | ports: 17 | - 9000:9000 18 | - 3333:3333 19 | cypress: 20 | image: cypress/included:14.0.3 21 | stdin_open: true 22 | tty: true 23 | working_dir: /mermaid 24 | mem_limit: '2G' 25 | entrypoint: cypress 26 | environment: 27 | - DISPLAY 28 | volumes: 29 | - ./:/mermaid 30 | - /tmp/.X11-unix:/tmp/.X11-unix 31 | network_mode: host 32 | 33 | volumes: 34 | root_cache: 35 | root_local: 36 | root_npm: 37 | -------------------------------------------------------------------------------- /docs/public/icons/group.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /packages/mermaid-example-diagram/src/exampleDiagram.spec.js: -------------------------------------------------------------------------------- 1 | import { parser } from './parser/exampleDiagram.jison'; 2 | import * as db from './exampleDiagramDb.js'; 3 | import { injectUtils } from './mermaidUtils.js'; 4 | // Todo fix utils functions for tests 5 | import { 6 | log, 7 | setLogLevel, 8 | getConfig, 9 | sanitizeText, 10 | setupGraphViewBox, 11 | } from '../../mermaid/src/diagram-api/diagramAPI.js'; 12 | 13 | injectUtils(log, setLogLevel, getConfig, sanitizeText, setupGraphViewBox); 14 | 15 | describe('when parsing an info graph it', function () { 16 | let ex; 17 | beforeEach(function () { 18 | ex = parser; 19 | ex.yy = db; 20 | }); 21 | 22 | it('should handle an example-diagram definition', function () { 23 | let str = `example-diagram 24 | showInfo`; 25 | 26 | ex.parse(str); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /packages/mermaid-example-diagram/src/parser/exampleDiagram.jison: -------------------------------------------------------------------------------- 1 | %lex 2 | 3 | %options case-insensitive 4 | 5 | %{ 6 | // Pre-lexer code can go here 7 | %} 8 | 9 | %% 10 | 11 | "example-diagram" return 'example-diagram' ; 12 | [\s\n\r]+ return 'NL' ; 13 | [\s]+ return 'space'; 14 | "showInfo" return 'showInfo'; 15 | <> return 'EOF' ; 16 | . return 'TXT' ; 17 | 18 | /lex 19 | 20 | %start start 21 | 22 | %% /* language grammar */ 23 | 24 | start 25 | // %{ : example-diagram document 'EOF' { return yy; } } 26 | : example-diagram document 'EOF' { return yy; } 27 | ; 28 | 29 | document 30 | : /* empty */ 31 | | document line 32 | ; 33 | 34 | line 35 | : statement { } 36 | | 'NL' 37 | ; 38 | 39 | statement 40 | : showInfo { yy.setInfo(true); } 41 | ; 42 | 43 | %% 44 | -------------------------------------------------------------------------------- /packages/mermaid/scripts/loadHook.mjs: -------------------------------------------------------------------------------- 1 | import { fileURLToPath } from 'node:url'; 2 | /** @import import { LoadHook } from "node:module"; */ 3 | /** 4 | * @type {LoadHook} 5 | * 6 | * Load hook that short circuits the loading of `.schema.yaml` files with `export default {}`. 7 | * These would normally be loaded using ESBuild, but that doesn't work for these local scripts. 8 | * 9 | * @see https://nodejs.org/api/module.html#loadurl-context-nextload 10 | */ 11 | export const load = async (url, context, nextLoad) => { 12 | const filePath = url.startsWith('file://') ? fileURLToPath(url) : url; 13 | if (filePath.endsWith('.schema.yaml')) { 14 | return { 15 | format: 'module', 16 | shortCircuit: true, 17 | source: `export default {}`, 18 | }; 19 | } else { 20 | return await nextLoad(url, context); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /packages/examples/src/examples/packet.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramMetadata } from '../types.js'; 2 | 3 | export default { 4 | id: 'packet', 5 | name: 'Packet Diagram', 6 | description: 'Visualize packet data and network traffic', 7 | examples: [ 8 | { 9 | title: 'TCP Packet', 10 | isDefault: true, 11 | code: `--- 12 | title: "TCP Packet" 13 | --- 14 | packet 15 | 0-15: "Source Port" 16 | 16-31: "Destination Port" 17 | 32-63: "Sequence Number" 18 | 64-95: "Acknowledgment Number" 19 | 96-99: "Data Offset" 20 | 100-105: "Reserved" 21 | 106: "URG" 22 | 107: "ACK" 23 | 108: "PSH" 24 | 109: "RST" 25 | 110: "SYN" 26 | 111: "FIN" 27 | 112-127: "Window" 28 | 128-143: "Checksum" 29 | 144-159: "Urgent Pointer" 30 | 160-191: "(Options and Padding)" 31 | 192-255: "Data (variable length)"`, 32 | }, 33 | ], 34 | } satisfies DiagramMetadata; 35 | -------------------------------------------------------------------------------- /docs/public/icons/comment.svg: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /packages/mermaid-layout-elk/src/find-common-ancestor.ts: -------------------------------------------------------------------------------- 1 | export interface TreeData { 2 | parentById: Record; 3 | childrenById: Record; 4 | } 5 | 6 | export const findCommonAncestor = (id1: string, id2: string, { parentById }: TreeData) => { 7 | const visited = new Set(); 8 | let currentId = id1; 9 | 10 | // Edge case with self edges 11 | if (id1 === id2) { 12 | return parentById[id1] || 'root'; 13 | } 14 | 15 | while (currentId) { 16 | visited.add(currentId); 17 | if (currentId === id2) { 18 | return currentId; 19 | } 20 | currentId = parentById[currentId]; 21 | } 22 | 23 | currentId = id2; 24 | while (currentId) { 25 | if (visited.has(currentId)) { 26 | return currentId; 27 | } 28 | currentId = parentById[currentId]; 29 | } 30 | 31 | return 'root'; 32 | }; 33 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/radar/parser.ts: -------------------------------------------------------------------------------- 1 | import type { Radar } from '@mermaid-js/parser'; 2 | import { parse } from '@mermaid-js/parser'; 3 | import type { ParserDefinition } from '../../diagram-api/types.js'; 4 | import { log } from '../../logger.js'; 5 | import { populateCommonDb } from '../common/populateCommonDb.js'; 6 | import { db } from './db.js'; 7 | 8 | const populate = (ast: Radar) => { 9 | populateCommonDb(ast, db); 10 | const { axes, curves, options } = ast; 11 | // Here we can add specific logic between the AST and the DB 12 | db.setAxes(axes); 13 | db.setCurves(curves); 14 | db.setOptions(options); 15 | }; 16 | 17 | export const parser: ParserDefinition = { 18 | parse: async (input: string): Promise => { 19 | const ast: Radar = await parse('radar', input); 20 | log.debug(ast); 21 | populate(ast); 22 | }, 23 | }; 24 | -------------------------------------------------------------------------------- /docs/config/setup/config/functions/addDirective.md: -------------------------------------------------------------------------------- 1 | > **Warning** 2 | > 3 | > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. 4 | > 5 | > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/config/functions/addDirective.md](../../../../../packages/mermaid/src/docs/config/setup/config/functions/addDirective.md). 6 | 7 | [**mermaid**](../../README.md) 8 | 9 | --- 10 | 11 | # Function: addDirective() 12 | 13 | > **addDirective**(`directive`): `void` 14 | 15 | Defined in: [packages/mermaid/src/config.ts:188](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L188) 16 | 17 | Pushes in a directive to the configuration 18 | 19 | ## Parameters 20 | 21 | ### directive 22 | 23 | [`MermaidConfig`](../../mermaid/interfaces/MermaidConfig.md) 24 | 25 | The directive to push in 26 | 27 | ## Returns 28 | 29 | `void` 30 | -------------------------------------------------------------------------------- /packages/mermaid/src/docs/public/icons/group.svg: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /docs/config/setup/mermaid/interfaces/RenderOptions.md: -------------------------------------------------------------------------------- 1 | > **Warning** 2 | > 3 | > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. 4 | > 5 | > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/mermaid/interfaces/RenderOptions.md](../../../../../packages/mermaid/src/docs/config/setup/mermaid/interfaces/RenderOptions.md). 6 | 7 | [**mermaid**](../../README.md) 8 | 9 | --- 10 | 11 | # Interface: RenderOptions 12 | 13 | Defined in: [packages/mermaid/src/rendering-util/render.ts:10](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L10) 14 | 15 | ## Properties 16 | 17 | ### algorithm? 18 | 19 | > `optional` **algorithm**: `string` 20 | 21 | Defined in: [packages/mermaid/src/rendering-util/render.ts:11](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L11) 22 | -------------------------------------------------------------------------------- /docs/config/setup/mermaid/type-aliases/ParseErrorFunction.md: -------------------------------------------------------------------------------- 1 | > **Warning** 2 | > 3 | > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. 4 | > 5 | > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/mermaid/type-aliases/ParseErrorFunction.md](../../../../../packages/mermaid/src/docs/config/setup/mermaid/type-aliases/ParseErrorFunction.md). 6 | 7 | [**mermaid**](../../README.md) 8 | 9 | --- 10 | 11 | # Type Alias: ParseErrorFunction() 12 | 13 | > **ParseErrorFunction** = (`err`, `hash?`) => `void` 14 | 15 | Defined in: [packages/mermaid/src/Diagram.ts:10](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/Diagram.ts#L10) 16 | 17 | ## Parameters 18 | 19 | ### err 20 | 21 | `string` | [`DetailedError`](../interfaces/DetailedError.md) | `unknown` 22 | 23 | ### hash? 24 | 25 | `any` 26 | 27 | ## Returns 28 | 29 | `void` 30 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/state/stateDetector.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DiagramDetector, 3 | DiagramLoader, 4 | ExternalDiagramDefinition, 5 | } from '../../diagram-api/types.js'; 6 | 7 | const id = 'state'; 8 | 9 | const detector: DiagramDetector = (txt, config) => { 10 | // If we have confirmed to only use new state diagrams this function should always return false 11 | // as in not signalling true for a legacy state diagram 12 | if (config?.state?.defaultRenderer === 'dagre-wrapper') { 13 | return false; 14 | } 15 | return /^\s*stateDiagram/.test(txt); 16 | }; 17 | 18 | const loader: DiagramLoader = async () => { 19 | const { diagram } = await import('./stateDiagram.js'); 20 | return { id, diagram }; 21 | }; 22 | 23 | const plugin: ExternalDiagramDefinition = { 24 | id, 25 | detector, 26 | loader, 27 | }; 28 | 29 | export default plugin; 30 | -------------------------------------------------------------------------------- /packages/mermaid/src/docs/public/icons/comment.svg: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /docs/config/setup/config/functions/updateSiteConfig.md: -------------------------------------------------------------------------------- 1 | > **Warning** 2 | > 3 | > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. 4 | > 5 | > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/config/functions/updateSiteConfig.md](../../../../../packages/mermaid/src/docs/config/setup/config/functions/updateSiteConfig.md). 6 | 7 | [**mermaid**](../../README.md) 8 | 9 | --- 10 | 11 | # Function: updateSiteConfig() 12 | 13 | > **updateSiteConfig**(`conf`): [`MermaidConfig`](../../mermaid/interfaces/MermaidConfig.md) 14 | 15 | Defined in: [packages/mermaid/src/config.ts:79](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L79) 16 | 17 | ## Parameters 18 | 19 | ### conf 20 | 21 | [`MermaidConfig`](../../mermaid/interfaces/MermaidConfig.md) 22 | 23 | ## Returns 24 | 25 | [`MermaidConfig`](../../mermaid/interfaces/MermaidConfig.md) 26 | -------------------------------------------------------------------------------- /docs/public/icons/presentation.svg: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /packages/examples/src/examples/class.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramMetadata } from '../types.js'; 2 | 3 | export default { 4 | id: 'classDiagram', 5 | name: 'Class Diagram', 6 | description: 'Visualize class structures and relationships in object-oriented programming', 7 | examples: [ 8 | { 9 | title: 'Basic Class Inheritance', 10 | isDefault: true, 11 | code: `classDiagram 12 | Animal <|-- Duck 13 | Animal <|-- Fish 14 | Animal <|-- Zebra 15 | Animal : +int age 16 | Animal : +String gender 17 | Animal: +isMammal() 18 | Animal: +mate() 19 | class Duck{ 20 | +String beakColor 21 | +swim() 22 | +quack() 23 | } 24 | class Fish{ 25 | -int sizeInFeet 26 | -canEat() 27 | } 28 | class Zebra{ 29 | +bool is_wild 30 | +run() 31 | }`, 32 | }, 33 | ], 34 | } satisfies DiagramMetadata; 35 | -------------------------------------------------------------------------------- /packages/examples/src/examples/mindmap.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramMetadata } from '../types.js'; 2 | 3 | export default { 4 | id: 'mindmap', 5 | name: 'Mindmap', 6 | description: 'Visualize ideas and concepts in a tree-like structure', 7 | examples: [ 8 | { 9 | title: 'Basic Mindmap', 10 | isDefault: true, 11 | code: `mindmap 12 | root((mindmap)) 13 | Origins 14 | Long history 15 | ::icon(fa fa-book) 16 | Popularisation 17 | British popular psychology author Tony Buzan 18 | Research 19 | On effectiveness
and features 20 | On Automatic creation 21 | Uses 22 | Creative techniques 23 | Strategic planning 24 | Argument mapping 25 | Tools 26 | Pen and paper 27 | Mermaid`, 28 | }, 29 | ], 30 | } satisfies DiagramMetadata; 31 | 32 | // cspell:ignore Buzan 33 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/class/svgDraw.spec.js: -------------------------------------------------------------------------------- 1 | import svgDraw from './svgDraw.js'; 2 | import { JSDOM } from 'jsdom'; 3 | 4 | describe('given a string representing a class, ', function () { 5 | describe('when class name includes generic, ', function () { 6 | it('should return correct text for generic', function () { 7 | const classDef = { 8 | id: 'Car', 9 | type: 'T', 10 | label: 'Car', 11 | }; 12 | 13 | let actual = svgDraw.getClassTitleString(classDef); 14 | expect(actual).toBe('Car'); 15 | }); 16 | it('should return correct text for nested generics', function () { 17 | const classDef = { 18 | id: 'Car', 19 | type: 'T~T~', 20 | label: 'Car', 21 | }; 22 | 23 | let actual = svgDraw.getClassTitleString(classDef); 24 | expect(actual).toBe('Car>'); 25 | }); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /cypress/integration/other/ghsa.spec.js: -------------------------------------------------------------------------------- 1 | import { urlSnapshotTest, openURLAndVerifyRendering } from '../../helpers/util.ts'; 2 | 3 | describe('CSS injections', () => { 4 | it('should not allow CSS injections outside of the diagram', () => { 5 | urlSnapshotTest('http://localhost:9000/ghsa1.html', { 6 | logLevel: 1, 7 | flowchart: { htmlLabels: false }, 8 | }); 9 | }); 10 | it('should not allow adding styletags affecting the page', () => { 11 | urlSnapshotTest('http://localhost:9000/ghsa3.html', { 12 | logLevel: 1, 13 | flowchart: { htmlLabels: false }, 14 | }); 15 | }); 16 | it('should not allow manipulating styletags using arrowheads', () => { 17 | openURLAndVerifyRendering('http://localhost:9000/xss23-css.html', { 18 | logLevel: 1, 19 | arrowMarkerAbsolute: false, 20 | flowchart: { htmlLabels: true }, 21 | }); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /cypress/support/e2e.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | import '@cypress/code-coverage/support'; 17 | import '@applitools/eyes-cypress/commands'; 18 | import '@argos-ci/cypress/support'; 19 | // Import commands.js using ES2015 syntax: 20 | import './commands'; 21 | 22 | // Alternatively you can use CommonJS syntax: 23 | // require('./commands') 24 | -------------------------------------------------------------------------------- /packages/examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mermaid-js/examples", 3 | "version": "1.0.0", 4 | "description": "Mermaid examples package", 5 | "author": "Sidharth Vinod", 6 | "license": "MIT", 7 | "type": "module", 8 | "module": "./dist/mermaid-examples.core.mjs", 9 | "types": "./dist/mermaid.d.ts", 10 | "exports": { 11 | ".": { 12 | "types": "./dist/index.d.ts", 13 | "import": "./dist/mermaid-examples.core.mjs", 14 | "default": "./dist/mermaid-examples.core.mjs" 15 | } 16 | }, 17 | "files": [ 18 | "dist" 19 | ], 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/mermaid-js/mermaid" 23 | }, 24 | "scripts": { 25 | "clean": "rimraf dist" 26 | }, 27 | "dependencies": {}, 28 | "devDependencies": { 29 | "mermaid": "workspace:*" 30 | }, 31 | "publishConfig": { 32 | "access": "public" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/sequence/sequenceDiagram.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramDefinition } from '../../diagram-api/types.js'; 2 | // @ts-ignore: JISON doesn't support types 3 | import parser from './parser/sequenceDiagram.jison'; 4 | import { SequenceDB } from './sequenceDb.js'; 5 | import styles from './styles.js'; 6 | import { setConfig } from '../../diagram-api/diagramAPI.js'; 7 | import renderer from './sequenceRenderer.js'; 8 | import type { MermaidConfig } from '../../config.type.js'; 9 | 10 | export const diagram: DiagramDefinition = { 11 | parser, 12 | get db() { 13 | return new SequenceDB(); 14 | }, 15 | renderer, 16 | styles, 17 | init: (cnf: MermaidConfig) => { 18 | if (!cnf.sequence) { 19 | cnf.sequence = {}; 20 | } 21 | if (cnf.wrap) { 22 | cnf.sequence.wrap = cnf.wrap; 23 | setConfig({ sequence: { wrap: cnf.wrap } }); 24 | } 25 | }, 26 | }; 27 | -------------------------------------------------------------------------------- /packages/mermaid/src/rendering-util/selectSvgElement.ts: -------------------------------------------------------------------------------- 1 | import { select } from 'd3'; 2 | import { getConfig } from '../diagram-api/diagramAPI.js'; 3 | import type { HTML, SVG } from '../diagram-api/types.js'; 4 | 5 | /** 6 | * Selects the SVG element using {@link id}. 7 | * 8 | * @param id - The diagram ID. 9 | * @returns The selected {@link SVG} element using {@link id}. 10 | */ 11 | export const selectSvgElement = (id: string): SVG => { 12 | const { securityLevel } = getConfig(); 13 | // handle root and document for when rendering in sandbox mode 14 | let root: HTML = select('body'); 15 | if (securityLevel === 'sandbox') { 16 | const sandboxElement: HTML = select(`#i${id}`); 17 | const doc: Document = sandboxElement.node()?.contentDocument ?? document; 18 | root = select(doc.body as HTMLIFrameElement); 19 | } 20 | const svg: SVG = root.select(`#${id}`); 21 | return svg; 22 | }; 23 | -------------------------------------------------------------------------------- /packages/mermaid/src/dagre-wrapper/intersect/intersect-rect.js: -------------------------------------------------------------------------------- 1 | const intersectRect = (node, point) => { 2 | var x = node.x; 3 | var y = node.y; 4 | 5 | // Rectangle intersection algorithm from: 6 | // https://math.stackexchange.com/questions/108113/find-edge-between-two-boxes 7 | var dx = point.x - x; 8 | var dy = point.y - y; 9 | var w = node.width / 2; 10 | var h = node.height / 2; 11 | 12 | var sx, sy; 13 | if (Math.abs(dy) * w > Math.abs(dx) * h) { 14 | // Intersection is top or bottom of rect. 15 | if (dy < 0) { 16 | h = -h; 17 | } 18 | sx = dy === 0 ? 0 : (h * dx) / dy; 19 | sy = h; 20 | } else { 21 | // Intersection is left or right of rect. 22 | if (dx < 0) { 23 | w = -w; 24 | } 25 | sx = w; 26 | sy = dx === 0 ? 0 : (w * dy) / dx; 27 | } 28 | 29 | return { x: x + sx, y: y + sy }; 30 | }; 31 | 32 | export default intersectRect; 33 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/class/classDetector.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DiagramDetector, 3 | DiagramLoader, 4 | ExternalDiagramDefinition, 5 | } from '../../diagram-api/types.js'; 6 | 7 | const id = 'class'; 8 | 9 | const detector: DiagramDetector = (txt, config) => { 10 | // If we have configured to use dagre-wrapper then we should never return true in this function 11 | if (config?.class?.defaultRenderer === 'dagre-wrapper') { 12 | return false; 13 | } 14 | // We have not opted to use the new renderer so we should return true if we detect a class diagram 15 | return /^\s*classDiagram/.test(txt); 16 | }; 17 | 18 | const loader: DiagramLoader = async () => { 19 | const { diagram } = await import('./classDiagram.js'); 20 | return { id, diagram }; 21 | }; 22 | 23 | const plugin: ExternalDiagramDefinition = { 24 | id, 25 | detector, 26 | loader, 27 | }; 28 | 29 | export default plugin; 30 | -------------------------------------------------------------------------------- /packages/mermaid/src/docs/public/icons/presentation.svg: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /packages/examples/src/examples/quadrant-chart.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramMetadata } from '../types.js'; 2 | 3 | export default { 4 | id: 'quadrantChart', 5 | name: 'Quadrant Chart', 6 | description: 'Visualize items in a 2x2 matrix based on two variables', 7 | examples: [ 8 | { 9 | title: 'Product Positioning', 10 | isDefault: true, 11 | code: `quadrantChart 12 | title Reach and engagement of campaigns 13 | x-axis Low Reach --> High Reach 14 | y-axis Low Engagement --> High Engagement 15 | quadrant-1 We should expand 16 | quadrant-2 Need to promote 17 | quadrant-3 Re-evaluate 18 | quadrant-4 May be improved 19 | Campaign A: [0.3, 0.6] 20 | Campaign B: [0.45, 0.23] 21 | Campaign C: [0.57, 0.69] 22 | Campaign D: [0.78, 0.34] 23 | Campaign E: [0.40, 0.34] 24 | Campaign F: [0.35, 0.78]`, 25 | }, 26 | ], 27 | } satisfies DiagramMetadata; 28 | -------------------------------------------------------------------------------- /packages/mermaid-layout-tidy-tree/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @mermaid-js/layout-tidy-tree 2 | 3 | ## 0.2.0 4 | 5 | ### Minor Changes 6 | 7 | - [#6802](https://github.com/mermaid-js/mermaid/pull/6802) [`c8e5027`](https://github.com/mermaid-js/mermaid/commit/c8e50276e877c4de7593a09ec458c99353e65af8) Thanks [@darshanr0107](https://github.com/darshanr0107)! - feat: Update mindmap rendering to support multiple layouts, improved edge intersections, and new shapes 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [[`33bc4a0`](https://github.com/mermaid-js/mermaid/commit/33bc4a0b4e2ca6d937bb0a8c4e2081b1362b2800), [`e0b45c2`](https://github.com/mermaid-js/mermaid/commit/e0b45c2d2b41c2a9038bf87646fa3ccd7560eb20), [`012530e`](https://github.com/mermaid-js/mermaid/commit/012530e98e9b8b80962ab270b6bb3b6d9f6ada05), [`c8e5027`](https://github.com/mermaid-js/mermaid/commit/c8e50276e877c4de7593a09ec458c99353e65af8)]: 12 | - mermaid@11.11.0 13 | -------------------------------------------------------------------------------- /demos/info.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Mermaid Quick Test Page 7 | 8 | 13 | 14 | 15 | 16 |

Info diagram demos

17 |
18 |       info
19 |     
20 | 21 |
22 |
23 |       info showInfo
24 |     
25 | 26 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /packages/mermaid/src/rendering-util/rendering-elements/intersect/intersect-rect.js: -------------------------------------------------------------------------------- 1 | const intersectRect = (node, point) => { 2 | var x = node.x; 3 | var y = node.y; 4 | 5 | // Rectangle intersection algorithm from: 6 | // https://math.stackexchange.com/questions/108113/find-edge-between-two-boxes 7 | var dx = point.x - x; 8 | var dy = point.y - y; 9 | var w = node.width / 2; 10 | var h = node.height / 2; 11 | 12 | var sx, sy; 13 | if (Math.abs(dy) * w > Math.abs(dx) * h) { 14 | // Intersection is top or bottom of rect. 15 | if (dy < 0) { 16 | h = -h; 17 | } 18 | sx = dy === 0 ? 0 : (h * dx) / dy; 19 | sy = h; 20 | } else { 21 | // Intersection is left or right of rect. 22 | if (dx < 0) { 23 | w = -w; 24 | } 25 | sx = w; 26 | sy = dx === 0 ? 0 : (w * dy) / dx; 27 | } 28 | 29 | return { x: x + sx, y: y + sy }; 30 | }; 31 | 32 | export default intersectRect; 33 | -------------------------------------------------------------------------------- /.build/types.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | import { packageOptions } from './common.js'; 3 | import { execSync } from 'child_process'; 4 | 5 | const buildType = (packageName: string) => { 6 | console.log(`Building types for ${packageName}`); 7 | try { 8 | const out = execSync(`tsc -p ./packages/${packageName}/tsconfig.json --emitDeclarationOnly`); 9 | if (out.length > 0) { 10 | console.log(out.toString()); 11 | } 12 | } catch (e) { 13 | if (e.stdout.length > 0) { 14 | console.error(e.stdout.toString()); 15 | } 16 | if (e.stderr.length > 0) { 17 | console.error(e.stderr.toString()); 18 | } 19 | // Exit the build process if we are in CI 20 | if (process.env.CI) { 21 | throw new Error(`Failed to build types for ${packageName}`); 22 | } 23 | } 24 | }; 25 | 26 | for (const { packageName } of Object.values(packageOptions)) { 27 | buildType(packageName); 28 | } 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: GitHub Discussions 4 | url: https://github.com/mermaid-js/mermaid/discussions 5 | about: Ask the Community questions or share your own graphs in our discussions. 6 | - name: Discord 7 | url: https://discord.gg/sKeNQX4Wtj 8 | about: Join our Community on Discord for Help and a casual chat. 9 | - name: Documentation 10 | url: https://mermaid.js.org 11 | about: Read our documentation for all that Mermaid.js can offer. 12 | - name: Live Editor 13 | url: https://mermaid.live 14 | about: Try the live editor to preview graphs in no time. 15 | - name: Live Editor - Develop 16 | url: https://develop.git.mermaid.live 17 | about: Try unreleased changes in the develop branch. 18 | - name: Live Editor - Next 19 | url: https://next.git.mermaid.live 20 | about: Try unreleased changes in the next branch. 21 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/flowchart/flowDetector.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DiagramDetector, 3 | DiagramLoader, 4 | ExternalDiagramDefinition, 5 | } from '../../diagram-api/types.js'; 6 | 7 | const id = 'flowchart'; 8 | 9 | const detector: DiagramDetector = (txt, config) => { 10 | // If we have conferred to only use new flow charts this function should always return false 11 | // as in not signalling true for a legacy flowchart 12 | if ( 13 | config?.flowchart?.defaultRenderer === 'dagre-wrapper' || 14 | config?.flowchart?.defaultRenderer === 'elk' 15 | ) { 16 | return false; 17 | } 18 | return /^\s*graph/.test(txt); 19 | }; 20 | 21 | const loader: DiagramLoader = async () => { 22 | const { diagram } = await import('./flowDiagram.js'); 23 | return { id, diagram }; 24 | }; 25 | 26 | const plugin: ExternalDiagramDefinition = { 27 | id, 28 | detector, 29 | loader, 30 | }; 31 | 32 | export default plugin; 33 | -------------------------------------------------------------------------------- /packages/mermaid/src/docs/syntax/userJourney.md: -------------------------------------------------------------------------------- 1 | # User Journey Diagram 2 | 3 | > User journeys describe at a high level of detail exactly what steps different users take to complete a specific task within a system, application or website. This technique shows the current (as-is) user workflow, and reveals areas of improvement for the to-be workflow. (Wikipedia) 4 | 5 | Mermaid can render user journey diagrams: 6 | 7 | ```mermaid-example 8 | journey 9 | title My working day 10 | section Go to work 11 | Make tea: 5: Me 12 | Go upstairs: 3: Me 13 | Do work: 1: Me, Cat 14 | section Go home 15 | Go downstairs: 5: Me 16 | Sit down: 5: Me 17 | ``` 18 | 19 | Each user journey is split into sections, these describe the part of the task 20 | the user is trying to complete. 21 | 22 | Tasks syntax is `Task name: : ` 23 | 24 | Score is a number between 1 and 5, inclusive. 25 | -------------------------------------------------------------------------------- /cypress/integration/rendering/flowchart-icon.spec.js: -------------------------------------------------------------------------------- 1 | import { imgSnapshotTest } from '../../helpers/util.ts'; 2 | 3 | const themes = ['default', 'forest', 'dark', 'base', 'neutral']; 4 | 5 | describe('when rendering flowchart with icons', () => { 6 | for (const theme of themes) { 7 | it(`should render icons from fontawesome library on theme ${theme}`, () => { 8 | imgSnapshotTest( 9 | `flowchart TD 10 | A("fab:fa-twitter Twitter") --> B("fab:fa-facebook Facebook") 11 | B --> C("fa:fa-coffee Coffee") 12 | C --> D("fa:fa-car Car") 13 | D --> E("fab:fa-github GitHub") 14 | `, 15 | { theme } 16 | ); 17 | }); 18 | 19 | it(`should render registered icons on theme ${theme}`, () => { 20 | imgSnapshotTest( 21 | `flowchart TD 22 | A("fa:fa-bell Bell") 23 | `, 24 | { theme } 25 | ); 26 | }); 27 | } 28 | }); 29 | -------------------------------------------------------------------------------- /packages/examples/src/examples/er.ts: -------------------------------------------------------------------------------- 1 | import type { DiagramMetadata } from '../types.js'; 2 | 3 | export default { 4 | id: 'er', 5 | name: 'Entity Relationship Diagram', 6 | description: 'Visualize database schemas and relationships between entities', 7 | examples: [ 8 | { 9 | title: 'Basic ER Schema', 10 | isDefault: true, 11 | code: `erDiagram 12 | CUSTOMER ||--o{ ORDER : places 13 | ORDER ||--|{ ORDER_ITEM : contains 14 | PRODUCT ||--o{ ORDER_ITEM : includes 15 | CUSTOMER { 16 | string id 17 | string name 18 | string email 19 | } 20 | ORDER { 21 | string id 22 | date orderDate 23 | string status 24 | } 25 | PRODUCT { 26 | string id 27 | string name 28 | float price 29 | } 30 | ORDER_ITEM { 31 | int quantity 32 | float price 33 | }`, 34 | }, 35 | ], 36 | } satisfies DiagramMetadata; 37 | -------------------------------------------------------------------------------- /.vite/jsonSchemaPlugin.ts: -------------------------------------------------------------------------------- 1 | import type { PluginOption } from 'vite'; 2 | import { getDefaults, getSchema, loadSchema } from '../.build/jsonSchema.js'; 3 | 4 | /** 5 | * Vite plugin that handles JSON Schemas saved as a `.schema.yaml` file. 6 | * 7 | * Use `my-example.schema.yaml?only-defaults=true` to only load the default values. 8 | */ 9 | export default function jsonSchemaPlugin(): PluginOption { 10 | return { 11 | name: 'json-schema-plugin', 12 | transform(src: string, id: string) { 13 | const idAsUrl = new URL(id, 'file:///'); 14 | 15 | if (!idAsUrl.pathname.endsWith('schema.yaml')) { 16 | return; 17 | } 18 | 19 | const jsonSchema = loadSchema(src, idAsUrl.pathname); 20 | return { 21 | code: idAsUrl.searchParams.get('only-defaults') 22 | ? getDefaults(jsonSchema) 23 | : getSchema(jsonSchema), 24 | map: null, // no source map 25 | }; 26 | }, 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /docs/config/setup/defaultConfig/variables/default.md: -------------------------------------------------------------------------------- 1 | > **Warning** 2 | > 3 | > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. 4 | > 5 | > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/defaultConfig/variables/default.md](../../../../../packages/mermaid/src/docs/config/setup/defaultConfig/variables/default.md). 6 | 7 | [**mermaid**](../../README.md) 8 | 9 | --- 10 | 11 | # Variable: default 12 | 13 | > `const` **default**: `RequiredDeep`<[`MermaidConfig`](../../mermaid/interfaces/MermaidConfig.md)> 14 | 15 | Defined in: [packages/mermaid/src/defaultConfig.ts:18](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L18) 16 | 17 | Default mermaid configuration options. 18 | 19 | Please see the Mermaid config JSON Schema for the default JSON values. 20 | Non-JSON JS default values are listed in this file, e.g. functions, or 21 | `undefined` (explicitly set so that `configKeys` finds them). 22 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/flowchart/elk/detector.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DiagramDetector, 3 | DiagramLoader, 4 | ExternalDiagramDefinition, 5 | } from '../../../diagram-api/types.js'; 6 | 7 | const id = 'flowchart-elk'; 8 | 9 | const detector: DiagramDetector = (txt, config = {}): boolean => { 10 | if ( 11 | // If diagram explicitly states flowchart-elk 12 | /^\s*flowchart-elk/.test(txt) || 13 | // If a flowchart/graph diagram has their default renderer set to elk 14 | (/^\s*(flowchart|graph)/.test(txt) && config?.flowchart?.defaultRenderer === 'elk') 15 | ) { 16 | config.layout = 'elk'; 17 | return true; 18 | } 19 | return false; 20 | }; 21 | 22 | const loader: DiagramLoader = async () => { 23 | const { diagram } = await import('../flowDiagram.js'); 24 | return { id, diagram }; 25 | }; 26 | 27 | const plugin: ExternalDiagramDefinition = { 28 | id, 29 | detector, 30 | loader, 31 | }; 32 | 33 | export default plugin; 34 | -------------------------------------------------------------------------------- /cypress/platform/render-after-error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Mermaid Quick Test Page 7 | 8 | 9 | 10 |
11 | 12 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /docs/config/setup/mermaid/interfaces/ParseOptions.md: -------------------------------------------------------------------------------- 1 | > **Warning** 2 | > 3 | > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. 4 | > 5 | > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/mermaid/interfaces/ParseOptions.md](../../../../../packages/mermaid/src/docs/config/setup/mermaid/interfaces/ParseOptions.md). 6 | 7 | [**mermaid**](../../README.md) 8 | 9 | --- 10 | 11 | # Interface: ParseOptions 12 | 13 | Defined in: [packages/mermaid/src/types.ts:89](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L89) 14 | 15 | ## Properties 16 | 17 | ### suppressErrors? 18 | 19 | > `optional` **suppressErrors**: `boolean` 20 | 21 | Defined in: [packages/mermaid/src/types.ts:94](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L94) 22 | 23 | If `true`, parse will return `false` instead of throwing error when the diagram is invalid. 24 | The `parseError` function will not be called. 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | node_modules/ 4 | coverage/ 5 | .idea/ 6 | .pnpm-store/ 7 | .instructions/ 8 | 9 | dist 10 | v8-compile-cache-0 11 | 12 | yarn-error.log 13 | .npmrc 14 | token 15 | 16 | package-lock.json 17 | 18 | # ignore files in /.vscode/ except for launch.json and extensions.json 19 | /.vscode/** 20 | !/.vscode/launch.json 21 | !/.vscode/extensions.json 22 | 23 | cypress/platform/current.html 24 | cypress/platform/experimental.html 25 | local/ 26 | 27 | _site 28 | Gemfile.lock 29 | /.vs 30 | 31 | cypress/screenshots/ 32 | cypress/snapshots/ 33 | 34 | # eslint --cache file 35 | .eslintcache 36 | .tsbuildinfo 37 | tsconfig.tsbuildinfo 38 | 39 | #knsv*.html 40 | local*.html 41 | stats/ 42 | 43 | **/user-avatars/* 44 | **/contributor-names.json 45 | .pnpm-store 46 | .nyc_output 47 | 48 | demos/dev/** 49 | !/demos/dev/example.html 50 | !/demos/dev/reload.js 51 | tsx-0/** 52 | vite.config.ts.timestamp-* 53 | 54 | # autogenereated by langium-cli 55 | generated/ 56 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/flowchart/flowDiagram.ts: -------------------------------------------------------------------------------- 1 | import type { MermaidConfig } from '../../config.type.js'; 2 | import { setConfig } from '../../diagram-api/diagramAPI.js'; 3 | import { FlowDB } from './flowDb.js'; 4 | import renderer from './flowRenderer-v3-unified.js'; 5 | // @ts-ignore: JISON doesn't support types 6 | //import flowParser from './parser/flow.jison'; 7 | import flowParser from './parser/flowParser.ts'; 8 | import flowStyles from './styles.js'; 9 | 10 | export const diagram = { 11 | parser: flowParser, 12 | get db() { 13 | return new FlowDB(); 14 | }, 15 | renderer, 16 | styles: flowStyles, 17 | init: (cnf: MermaidConfig) => { 18 | if (!cnf.flowchart) { 19 | cnf.flowchart = {}; 20 | } 21 | if (cnf.layout) { 22 | setConfig({ layout: cnf.layout }); 23 | } 24 | cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; 25 | setConfig({ flowchart: { arrowMarkerAbsolute: cnf.arrowMarkerAbsolute } }); 26 | }, 27 | }; 28 | -------------------------------------------------------------------------------- /packages/mermaid/src/setupGraphViewbox.spec.js: -------------------------------------------------------------------------------- 1 | import utils from './utils.js'; 2 | import assignWithDepth from './assignWithDepth.js'; 3 | import { detectType } from './diagram-api/detectType.js'; 4 | import { addDiagrams } from './diagram-api/diagram-orchestration.js'; 5 | import { calculateSvgSizeAttrs } from './setupGraphViewbox.js'; 6 | addDiagrams(); 7 | 8 | describe('when calculating SVG size', function () { 9 | it('should return width 100% when useMaxWidth is true', function () { 10 | const attrs = calculateSvgSizeAttrs(100, 200, true); 11 | // expect(attrs.get('height')).toEqual(100); 12 | expect(attrs.get('style')).toEqual('max-width: 200px;'); 13 | expect(attrs.get('width')).toEqual('100%'); 14 | }); 15 | it('should return absolute width when useMaxWidth is false', function () { 16 | const attrs = calculateSvgSizeAttrs(100, 200, false); 17 | // expect(attrs.get('height')).toEqual(100); 18 | expect(attrs.get('width')).toEqual(200); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /cypress/platform/regression/issue-1874.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Example

4 |
 5 | %%{init:{"theme":"base", "sequence": {"mirrorActors":false},"themeVariables": {"actorBkg":"red"}}}%%
 6 | sequenceDiagram
 7 |     Bert->>+Ernie: Start looking for the cookie!
 8 |     Ernie-->>-Bert: Found it!
 9 |     Note left of Ernie: Cookies are good
10 |     
11 |
12 | %%{init:{"theme":"base", "themeVariables": {}}}%%
13 | sequenceDiagram
14 |     Bert->>+Ernie: Start looking for the cookie!
15 |     Ernie-->>-Bert: Found it!
16 |     Note left of Ernie: Cookies are good
17 |     
18 | 19 | 31 | 32 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/class/parser/class.spec.js: -------------------------------------------------------------------------------- 1 | import { parser } from './classDiagram.jison'; 2 | import { ClassDB } from '../classDb.js'; 3 | 4 | describe('class diagram', function () { 5 | let classDb; 6 | beforeEach(function () { 7 | classDb = new ClassDB(); 8 | parser.yy = classDb; 9 | parser.yy.clear(); 10 | }); 11 | 12 | describe('prototype properties', function () { 13 | it.each(['__proto__', 'constructor'])('should work with a %s property', function (prop) { 14 | expect(() => parser.parse(`classDiagram\nclass ${prop}`)).not.toThrow(); 15 | expect(() => parser.parse(`classDiagram\nnamespace ${prop} {\n\tclass A\n}`)).not.toThrow(); 16 | }); 17 | }); 18 | 19 | describe('backtick escaping', function () { 20 | it('should handle backtick-quoted namespace names', function () { 21 | expect(() => 22 | parser.parse(`classDiagram\nnamespace \`A::B\` {\n\tclass \`IPC::Sender\`\n}`) 23 | ).not.toThrow(); 24 | }); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /packages/mermaid/src/__mocks__/mermaidAPI.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Mocks for `./mermaidAPI`. 3 | * 4 | * We can't easily use `vi.spyOn(mermaidAPI, "function")` since the object is frozen with `Object.freeze()`. 5 | */ 6 | import * as configApi from '../config.js'; 7 | import { vi } from 'vitest'; 8 | import { mermaidAPI as mAPI } from '../mermaidAPI.js'; 9 | 10 | // original version cannot be modified since it was frozen with `Object.freeze()` 11 | export const mermaidAPI = { 12 | render: vi.fn().mockResolvedValue({ 13 | svg: '', 14 | }), 15 | parse: mAPI.parse, 16 | initialize: vi.fn(), 17 | getConfig: configApi.getConfig, 18 | setConfig: configApi.setConfig, 19 | getSiteConfig: configApi.getSiteConfig, 20 | updateSiteConfig: configApi.updateSiteConfig, 21 | reset: () => { 22 | configApi.reset(); 23 | }, 24 | globalReset: () => { 25 | configApi.reset(configApi.defaultConfig); 26 | }, 27 | defaultConfig: configApi.defaultConfig, 28 | }; 29 | 30 | export default mermaidAPI; 31 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/class/classDetector-V2.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DiagramDetector, 3 | DiagramLoader, 4 | ExternalDiagramDefinition, 5 | } from '../../diagram-api/types.js'; 6 | 7 | const id = 'classDiagram'; 8 | 9 | const detector: DiagramDetector = (txt, config) => { 10 | // If we have configured to use dagre-wrapper then we should return true in this function for classDiagram code thus making it use the new class diagram 11 | if (/^\s*classDiagram/.test(txt) && config?.class?.defaultRenderer === 'dagre-wrapper') { 12 | return true; 13 | } 14 | // We have not opted to use the new renderer so we should return true if we detect a class diagram 15 | return /^\s*classDiagram-v2/.test(txt); 16 | }; 17 | 18 | const loader: DiagramLoader = async () => { 19 | const { diagram } = await import('./classDiagram-v2.js'); 20 | return { id, diagram }; 21 | }; 22 | 23 | const plugin: ExternalDiagramDefinition = { 24 | id, 25 | detector, 26 | loader, 27 | }; 28 | 29 | export default plugin; 30 | -------------------------------------------------------------------------------- /cypress/platform/ghsa2.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 |
7 |

This element does not belong to the SVG but we can style it

8 |
9 | 10 | 11 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /docs/config/setup/config/README.md: -------------------------------------------------------------------------------- 1 | > **Warning** 2 | > 3 | > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. 4 | > 5 | > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/config/README.md](../../../../packages/mermaid/src/docs/config/setup/config/README.md). 6 | 7 | [**mermaid**](../README.md) 8 | 9 | --- 10 | 11 | # config 12 | 13 | ## Variables 14 | 15 | - [defaultConfig](variables/defaultConfig.md) 16 | 17 | ## Functions 18 | 19 | - [addDirective](functions/addDirective.md) 20 | - [getConfig](functions/getConfig.md) 21 | - [getSiteConfig](functions/getSiteConfig.md) 22 | - [getUserDefinedConfig](functions/getUserDefinedConfig.md) 23 | - [reset](functions/reset.md) 24 | - [sanitize](functions/sanitize.md) 25 | - [saveConfigFromInitialize](functions/saveConfigFromInitialize.md) 26 | - [setConfig](functions/setConfig.md) 27 | - [setSiteConfig](functions/setSiteConfig.md) 28 | - [updateCurrentConfig](functions/updateCurrentConfig.md) 29 | - [updateSiteConfig](functions/updateSiteConfig.md) 30 | -------------------------------------------------------------------------------- /packages/mermaid/src/docs/.vitepress/components/HomePage.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 27 | -------------------------------------------------------------------------------- /packages/mermaid/src/utils/imperativeState.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Resettable state storage. 3 | * @example 4 | * ``` 5 | * const state = new ImperativeState(() => ({ 6 | * foo: undefined as string | undefined, 7 | * bar: [] as number[], 8 | * baz: 1 as number | undefined, 9 | * })); 10 | * 11 | * state.records.foo = "hi"; 12 | * console.log(state.records.foo); // prints "hi"; 13 | * state.reset(); 14 | * console.log(state.records.foo); // prints "default"; 15 | * 16 | * // typeof state.records: 17 | * // { 18 | * // foo: string | undefined, // actual: undefined 19 | * // bar: number[], // actual: [] 20 | * // baz: number | undefined, // actual: 1 21 | * // } 22 | * ``` 23 | */ 24 | export class ImperativeState { 25 | public records: S; 26 | 27 | /** 28 | * @param init - Function that creates the default state. 29 | */ 30 | constructor(private init: () => S) { 31 | this.records = this.init(); 32 | } 33 | 34 | reset() { 35 | this.records = this.init(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /.github/workflows/update-browserlist.yml: -------------------------------------------------------------------------------- 1 | name: Update Browserslist 2 | on: 3 | schedule: 4 | - cron: '0 7 * * 1' 5 | workflow_dispatch: 6 | 7 | jobs: 8 | update-browser-list: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 12 | - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 13 | - run: npx update-browserslist-db@latest 14 | - name: Commit changes 15 | uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4 16 | with: 17 | author_name: ${{ github.actor }} 18 | author_email: ${{ github.actor }}@users.noreply.github.com 19 | message: 'chore: update browsers list' 20 | push: false 21 | - name: Create Pull Request 22 | uses: peter-evans/create-pull-request@84ae59a2cdc2258d6fa0732dd66352dddae2a412 # v7.0.9 23 | with: 24 | branch: update-browserslist 25 | title: Update Browserslist 26 | -------------------------------------------------------------------------------- /docs/config/setup/config/functions/updateCurrentConfig.md: -------------------------------------------------------------------------------- 1 | > **Warning** 2 | > 3 | > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. 4 | > 5 | > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/config/functions/updateCurrentConfig.md](../../../../../packages/mermaid/src/docs/config/setup/config/functions/updateCurrentConfig.md). 6 | 7 | [**mermaid**](../../README.md) 8 | 9 | --- 10 | 11 | # Function: updateCurrentConfig() 12 | 13 | > **updateCurrentConfig**(`siteCfg`, `_directives`): [`MermaidConfig`](../../mermaid/interfaces/MermaidConfig.md) 14 | 15 | Defined in: [packages/mermaid/src/config.ts:15](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L15) 16 | 17 | ## Parameters 18 | 19 | ### siteCfg 20 | 21 | [`MermaidConfig`](../../mermaid/interfaces/MermaidConfig.md) 22 | 23 | ### \_directives 24 | 25 | [`MermaidConfig`](../../mermaid/interfaces/MermaidConfig.md)\[] 26 | 27 | ## Returns 28 | 29 | [`MermaidConfig`](../../mermaid/interfaces/MermaidConfig.md) 30 | -------------------------------------------------------------------------------- /packages/mermaid/src/docs/.vitepress/theme/mermaid.ts: -------------------------------------------------------------------------------- 1 | import mermaid, { type MermaidConfig } from 'mermaid'; 2 | import zenuml from '../../../../../mermaid-zenuml/dist/mermaid-zenuml.core.mjs'; 3 | import tidyTreeLayout from '../../../../../mermaid-layout-tidy-tree/dist/mermaid-layout-tidy-tree.core.mjs'; 4 | import layouts from '../../../../../mermaid-layout-elk/dist/mermaid-layout-elk.core.mjs'; 5 | 6 | const init = Promise.all([ 7 | mermaid.registerExternalDiagrams([zenuml]), 8 | mermaid.registerLayoutLoaders(layouts), 9 | mermaid.registerLayoutLoaders(tidyTreeLayout), 10 | ]); 11 | mermaid.registerIconPacks([ 12 | { 13 | name: 'logos', 14 | loader: () => 15 | fetch('https://unpkg.com/@iconify-json/logos/icons.json').then((res) => res.json()), 16 | }, 17 | ]); 18 | 19 | export const render = async (id: string, code: string, config: MermaidConfig): Promise => { 20 | await init; 21 | mermaid.initialize(config); 22 | const { svg } = await mermaid.render(id, code); 23 | return svg; 24 | }; 25 | -------------------------------------------------------------------------------- /docs/public/icons/whiteboard.svg: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /packages/mermaid/src/diagrams/common/commonDb.ts: -------------------------------------------------------------------------------- 1 | import { sanitizeText as _sanitizeText } from './common.js'; 2 | import { getConfig } from '../../config.js'; 3 | 4 | let accTitle = ''; 5 | let diagramTitle = ''; 6 | let accDescription = ''; 7 | 8 | const sanitizeText = (txt: string): string => _sanitizeText(txt, getConfig()); 9 | 10 | export const clear = (): void => { 11 | accTitle = ''; 12 | accDescription = ''; 13 | diagramTitle = ''; 14 | }; 15 | 16 | export const setAccTitle = (txt: string): void => { 17 | accTitle = sanitizeText(txt).replace(/^\s+/g, ''); 18 | }; 19 | 20 | export const getAccTitle = (): string => accTitle; 21 | 22 | export const setAccDescription = (txt: string): void => { 23 | accDescription = sanitizeText(txt).replace(/\n\s+/g, '\n'); 24 | }; 25 | 26 | export const getAccDescription = (): string => accDescription; 27 | 28 | export const setDiagramTitle = (txt: string): void => { 29 | diagramTitle = sanitizeText(txt); 30 | }; 31 | 32 | export const getDiagramTitle = (): string => diagramTitle; 33 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 14 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - Retained 8 | # Label to use when marking an issue as stale 9 | staleLabel: Inactive 10 | # Comment to post when marking an issue as stale. Set to `false` to disable 11 | markComment: > 12 | This issue has been automatically marked as stale because it has not had 13 | recent activity. It will be closed if no further activity occurs. Thank you 14 | for your contributions. 15 | If you are still interested in this issue and it is still relevant you can comment to revive it. 16 | # Comment to post when closing a stale issue. Set to `false` to disable 17 | closeComment: > 18 | This issue has been automatically closed due to a lack of activity. 19 | This is done to maintain a clean list of issues that the community is interested in developing. 20 | --------------------------------------------------------------------------------