diff --git a/cypress/helpers/util.ts b/cypress/helpers/util.ts
index 133a35032..74b17cf05 100644
--- a/cypress/helpers/util.ts
+++ b/cypress/helpers/util.ts
@@ -73,7 +73,7 @@ export const imgSnapshotTest = (
export const urlSnapshotTest = (
url: string,
- options: CypressMermaidConfig,
+ options: CypressMermaidConfig = {},
_api = false,
validation?: any
): void => {
diff --git a/cypress/integration/rendering/architecture.spec.ts b/cypress/integration/rendering/architecture.spec.ts
new file mode 100644
index 000000000..1deb1f7da
--- /dev/null
+++ b/cypress/integration/rendering/architecture.spec.ts
@@ -0,0 +1,180 @@
+import { imgSnapshotTest, urlSnapshotTest } from '../../helpers/util.ts';
+
+describe.skip('architecture diagram', () => {
+ it('should render a simple architecture diagram with groups', () => {
+ imgSnapshotTest(
+ `architecture-beta
+ group api(cloud)[API]
+
+ service db(database)[Database] in api
+ service disk1(disk)[Storage] in api
+ service disk2(disk)[Storage] in api
+ service server(server)[Server] in api
+ service gateway(internet)[Gateway]
+
+ db L--R server
+ disk1 T--B server
+ disk2 T--B db
+ server T--B gateway
+ `
+ );
+ });
+ it('should render an architecture diagram with groups within groups', () => {
+ imgSnapshotTest(
+ `architecture-beta
+ group api[API]
+ group public[Public API] in api
+ group private[Private API] in api
+
+ service serv1(server)[Server] in public
+
+ service serv2(server)[Server] in private
+ service db(database)[Database] in private
+
+ service gateway(internet)[Gateway] in api
+
+ serv1 B--T serv2
+ serv2 L--R db
+ serv1 L--R gateway
+ `
+ );
+ });
+ it('should render an architecture diagram with the fallback icon', () => {
+ imgSnapshotTest(
+ `architecture-beta
+ service unknown(iconnamedoesntexist)[Unknown Icon]
+ `
+ );
+ });
+ it('should render an architecture diagram with split directioning', () => {
+ imgSnapshotTest(
+ `architecture-beta
+ service db(database)[Database]
+ service s3(disk)[Storage]
+ service serv1(server)[Server 1]
+ service serv2(server)[Server 2]
+ service disk(disk)[Disk]
+
+ db L--R s3
+ serv1 L--T s3
+ serv2 L--B s3
+ serv1 T--B disk
+ `
+ );
+ });
+ it('should render an architecture diagram with directional arrows', () => {
+ imgSnapshotTest(
+ `architecture-beta
+ service servC(server)[Server 1]
+ service servL(server)[Server 2]
+ service servR(server)[Server 3]
+ service servT(server)[Server 4]
+ service servB(server)[Server 5]
+
+ servC (L--R) servL
+ servC (R--L) servR
+ servC (T--B) servT
+ servC (B--T) servB
+
+ servL (T--L) servT
+ servL (B--L) servB
+ servR (T--R) servT
+ servR (B--R) servB
+ `
+ );
+ });
+ it('should render an architecture diagram with group edges', () => {
+ imgSnapshotTest(
+ `architecture-beta
+ group left_group(cloud)[Left]
+ group right_group(cloud)[Right]
+ group top_group(cloud)[Top]
+ group bottom_group(cloud)[Bottom]
+ group center_group(cloud)[Center]
+
+ service left_disk(disk)[Disk] in left_group
+ service right_disk(disk)[Disk] in right_group
+ service top_disk(disk)[Disk] in top_group
+ service bottom_disk(disk)[Disk] in bottom_group
+ service center_disk(disk)[Disk] in center_group
+
+ left_disk{group} (R--L) center_disk{group}
+ right_disk{group} (L--R) center_disk{group}
+ top_disk{group} (B--T) center_disk{group}
+ bottom_disk{group} (T--B) center_disk{group}
+ `
+ );
+ });
+ it('should render an architecture diagram with edge labels', () => {
+ imgSnapshotTest(
+ `architecture-beta
+ service servC(server)[Server 1]
+ service servL(server)[Server 2]
+ service servR(server)[Server 3]
+ service servT(server)[Server 4]
+ service servB(server)[Server 5]
+
+ servC L-[Label]-R servL
+ servC R-[Label]-L servR
+ servC T-[Label]-B servT
+ servC B-[Label]-T servB
+
+ servL T-[Label]-L servT
+ servL B-[Label]-L servB
+ servR T-[Label]-R servT
+ servR B-[Label]-R servB
+ `
+ );
+ });
+ it('should render an architecture diagram with simple junction edges', () => {
+ imgSnapshotTest(
+ `architecture-beta
+ service left_disk(disk)[Disk]
+ service top_disk(disk)[Disk]
+ service bottom_disk(disk)[Disk]
+ service top_gateway(internet)[Gateway]
+ service bottom_gateway(internet)[Gateway]
+ junction juncC
+ junction juncR
+
+ left_disk R--L juncC
+ top_disk B--T juncC
+ bottom_disk T--B juncC
+ juncC R--L juncR
+ top_gateway B--T juncR
+ bottom_gateway T--B juncR
+ `
+ );
+ });
+ it('should render an architecture diagram with complex junction edges', () => {
+ imgSnapshotTest(
+ `architecture-beta
+ group left
+ group right
+ service left_disk(disk)[Disk] in left
+ service top_disk(disk)[Disk] in left
+ service bottom_disk(disk)[Disk] in left
+ service top_gateway(internet)[Gateway] in right
+ service bottom_gateway(internet)[Gateway] in right
+ junction juncC in left
+ junction juncR in right
+
+ left_disk R--L juncC
+ top_disk B--T juncC
+ bottom_disk T--B juncC
+
+
+ top_gateway (B--T juncR
+ bottom_gateway (T--B juncR
+
+ juncC{group} R--L) juncR{group}
+ `
+ );
+ });
+});
+
+describe('architecture - external', () => {
+ it('should allow adding external icons', () => {
+ urlSnapshotTest('http://localhost:9000/architecture-external.html');
+ });
+});
diff --git a/cypress/integration/rendering/erDiagram.spec.js b/cypress/integration/rendering/erDiagram.spec.js
index 1a2340906..aad9b1cf7 100644
--- a/cypress/integration/rendering/erDiagram.spec.js
+++ b/cypress/integration/rendering/erDiagram.spec.js
@@ -321,4 +321,37 @@ ORDER ||--|{ LINE-ITEM : contains
{ logLevel: 1 }
);
});
+
+ it('should render relationship labels with line breaks', () => {
+ imgSnapshotTest(
+ `
+ erDiagram
+ p[Person] {
+ string firstName
+ string lastName
+ }
+ a["Customer Account"] {
+ string email
+ }
+
+ b["Customer Account Secondary"] {
+ string email
+ }
+
+ c["Customer Account Tertiary"] {
+ string email
+ }
+
+ d["Customer Account Nth"] {
+ string email
+ }
+
+ p ||--o| a : "has
one"
+ p ||--o| b : "has
one
two"
+ p ||--o| c : "has
one
two
three"
+ p ||--o| d : "has
one
two
three
...
Nth"
+ `,
+ { logLevel: 1 }
+ );
+ });
});
diff --git a/cypress/integration/rendering/flowchart-v2.spec.js b/cypress/integration/rendering/flowchart-v2.spec.js
index c2fd0b011..452cdb5a0 100644
--- a/cypress/integration/rendering/flowchart-v2.spec.js
+++ b/cypress/integration/rendering/flowchart-v2.spec.js
@@ -99,7 +99,7 @@ describe('Flowchart v2', () => {
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
- expect(maxWidthValue).to.be.within(446 * 0.95 - 1, 446 * 1.05);
+ expect(maxWidthValue).to.be.within(417 * 0.95, 417 * 1.05);
});
});
it('8: should render a flowchart when useMaxWidth is false', () => {
@@ -118,7 +118,7 @@ describe('Flowchart v2', () => {
const width = parseFloat(svg.attr('width'));
// use within because the absolute value can be slightly different depending on the environment ±5%
// expect(height).to.be.within(446 * 0.95, 446 * 1.05);
- expect(width).to.be.within(446 * 0.95 - 1, 446 * 1.05);
+ expect(width).to.be.within(417 * 0.95, 417 * 1.05);
expect(svg).to.not.have.attr('style');
});
});
diff --git a/cypress/platform/architecture-external.html b/cypress/platform/architecture-external.html
new file mode 100644
index 000000000..71770425d
--- /dev/null
+++ b/cypress/platform/architecture-external.html
@@ -0,0 +1,52 @@
+
+
+
+
+
+ Architecture Mermaid Test Page
+
+
+
+
+
+ External Icons Demo
+
+ architecture-beta
+ service s3(logos:aws-s3)[Cloud Store]
+ service ec2(logos:aws-ec2)[Server]
+ service api(logos:aws-api-gateway)[Api Gateway]
+ service fa(fa:image)[Font Awesome Icon]
+
+
+
+
+
diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html
index 8808a3c9d..a3cbf60bf 100644
--- a/cypress/platform/knsv2.html
+++ b/cypress/platform/knsv2.html
@@ -73,7 +73,9 @@
font-family: monospace;
font-size: 72px;
}
-
+ pre {
+ width: 100%;
+ }
/* tspan {
font-size: 6px !important;
} */
@@ -88,17 +90,202 @@
config:
look: handDrawn
layout: elk
+ elk:
+
+
+---
+stateDiagram-v2
+ direction LR
+ accTitle: An idealized Open Source supply-chain graph
+
+ %%
+ state "š¦ Importer" as author_importer
+ state "š„ Supplier, Owner" as author_owner
+ state "šØš„ Maintainer, Author\nšØ Custodian" as author
+ state "š© Distributor" as repository_distributor
+ state "š¦ Importer" as language_importer
+ state "š¦šØ Packager" as language_packager
+ state "š¦šØ OSS Steward" as language_steward
+ state "šØ Curator" as language_curator
+ state "š© Distributor" as language_distributor
+ state "š¦ Contributor" as contributor
+ state "š¦ Importer" as package_importer
+ state "šØ Patcher" as package_patcher
+ state "šØš¦ Builder\nšØš¦ Packager\nšØš¦ Containerizer" as package_packager
+ state "šØ Curator" as package_curator
+ state "š© Distributor" as package_distributor
+ state "š¦ Importer" as integrator_importer
+ state "š„ Supplier, Manufacturer, Owner" as integrator_owner
+ state "š¦šØš„ Integrator, Developer" as integrator_developer
+ state "š©šØ SBOM Redactor\nš© Publisher" as integrator_publisher
+ state "š¦šØ Builder" as integrator_builder
+ state "šØ Deployer" as deployer
+ state "š¦ Vuln. Checker" as integrator_checker
+ state "š©šØ SBOM Redactor" as redactor
+ state "š¦ Consumer\nš¦ User" as consumer
+ state "š¦ Auditor" as auditor_internal
+ state "š¦ Auditor" as auditor_external
+
+ %%
+ classDef createsSBOM stroke:red,stroke-width:3px;
+ classDef updatesSBOM stroke:yellow,stroke-width:3px;
+ classDef assemblesSBOM stroke:yellow,stroke-width:3px;
+ classDef distributesSBOM stroke:green,stroke-width:3px;
+ classDef verifiesSBOM stroke:#07f,stroke-width:3px;
+
+ %%
+ class author_importer verifiesSBOM
+ class author_owner createsSBOM
+ class manufacturer_owner createsSBOM
+ class author assemblesSBOM
+ class package_importer verifiesSBOM
+ class package_patcher updatesSBOM
+ class package_packager assemblesSBOM
+ class package_curator distributesSBOM
+ class package_distributor distributesSBOM
+ class language_importer verifiesSBOM
+ class language_packager assemblesSBOM
+ class language_steward updatesSBOM
+ class language_curator distributesSBOM
+ class language_distributor distributesSBOM
+ class repository_distributor distributesSBOM
+ class integrator_importer verifiesSBOM
+ class integrator_owner createsSBOM
+ class integrator_developer assemblesSBOM
+ class integrator_publisher distributesSBOM
+ class integrator_builder assemblesSBOM
+ class integrator_checker verifiesSBOM
+ class deployer assemblesSBOM
+ class redactor distributesSBOM
+ class auditor_internal verifiesSBOM
+ class auditor_external verifiesSBOM
+
+ state "Maintainer Environment" as environment_maintainer {
+ [*] --> author_importer
+ [*] --> author
+ author_importer --> author
+ author_owner --> author
+ author --> language_packager
+ }
+
+ [*] --> environment_maintainer
+
+ state "Language Ecosystem" as ecosystem_lang {
+ [*] --> language_importer
+ [*] --> language_steward
+ [*] --> language_curator
+ [*] --> language_distributor
+ language_importer --> language_distributor
+ language_importer --> language_curator
+ language_steward --> language_curator
+ language_curator --> language_distributor
+ }
+
+ language_packager --> ecosystem_lang
+ ecosystem_lang --> ecosystem_lang
+
+ state "Public Collaboration Ecosystem" as ecosystem_repo {
+ [*] --> repository_distributor
+ }
+
+ author --> ecosystem_repo
+ ecosystem_repo --> author
+
+ repository_distributor --> contributor
+ contributor --> repository_distributor
+
+ state "Package Ecosystem" as ecosystem_package {
+ [*] --> package_importer
+ [*] --> package_packager
+ [*] --> package_patcher
+ package_importer --> package_patcher
+ package_importer --> package_packager
+ package_patcher --> package_packager
+ package_packager --> package_curator
+ package_packager --> package_distributor
+ package_curator --> package_distributor
+ }
+
+ repository_distributor --> ecosystem_package
+ language_distributor --> ecosystem_package
+ ecosystem_package --> ecosystem_package
+
+ state "Integrator Environment" as environment_integrator {
+ [*] --> integrator_developer
+ [*] --> integrator_importer
+ integrator_importer --> integrator_developer
+ integrator_owner --> integrator_developer
+ integrator_builder --> integrator_publisher
+ integrator_developer --> integrator_checker
+ integrator_checker --> integrator_developer
+ auditor_internal --> integrator_developer
+ integrator_developer --> integrator_builder
+ integrator_developer --> auditor_internal
+ }
+
+ repository_distributor --> environment_integrator
+ language_distributor --> environment_integrator
+ package_distributor --> environment_integrator
+
+ state "Production Environment" as environment_prod {
+ [*] --> deployer
+ deployer --> redactor
+ }
+
+ integrator_publisher --> [*]
+ integrator_developer --> environment_prod
+ integrator_builder --> environment_prod
+ integrator_publisher --> environment_prod
+
+ deployer --> auditor_external
+ deployer --> consumer
+ redactor --> consumer
+
+
+
+
+
+---
+ title: hello2
+ config:
+ look: handDrawn
+ layout: dagre
elk:
nodePlacementStrategy: BRANDES_KOEPF
---
-flowchart LR
- A[Start] --Some text--> B(Continue)
- B --> C{Evaluate}
- C -- One --> D[Option 1]
- C -- Two --> E[Option 2]
- C -- Three --> F[fa:fa-car Option 3]
+stateDiagram-v2
+ A --> A
+ state A {
+ B --> D
+ state B {
+ C
+ }
+ state D {
+ E
+ }
+ }
+
+
+---
+ title: hello2
+ config:
+ look: handDrawn
+ layout: dagre
+ elk:
+ nodePlacementStrategy: BRANDES_KOEPF
+---
+flowchart
+ A --> A
+ subgraph A
+ B --> B
+ subgraph B
+ C
+ end
+ end
+
@@ -195,7 +382,7 @@ flowchart LR
messageFontFamily: 'courier',
},
fontSize: 12,
- logLevel: 0,
+ logLevel: 3,
securityLevel: 'loose',
});
function callback() {
diff --git a/demos/architecture.html b/demos/architecture.html
new file mode 100644
index 000000000..6d978d952
--- /dev/null
+++ b/demos/architecture.html
@@ -0,0 +1,256 @@
+
+
+
+
+
+ Architecture Mermaid Quick Test Page
+
+
+
+
+
+ Architecture diagram demo
+ Simple diagram with groups
+
+ architecture-beta
+ group api(cloud)[API]
+
+ service db(database)[Database] in api
+ service disk1(disk)[Storage] in api
+ service disk2(disk)[Storage] in api
+ service server(server)[Server] in api
+ service gateway(internet)[Gateway]
+
+ db:L -- R:server
+ disk1:T -- B:server
+ disk2:T -- B:db
+ server:T -- B:gateway
+
+
+
+ Groups within groups
+
+ architecture-beta
+ group api[API]
+ group public[Public API] in api
+ group private[Private API] in api
+
+
+ service serv1(server)[Server] in public
+
+
+ service serv2(server)[Server] in private
+ service db(database)[Database] in private
+
+ service gateway(internet)[Gateway] in api
+
+ serv1:B -- T:serv2
+
+ serv2:L -- R:db
+
+ serv1:L -- R:gateway
+
+
+
+ Default icon (?) from unknown icon name
+
+ architecture-beta
+ service unknown(iconnamedoesntexist)[Unknown Icon]
+
+
+
+ Split Direction
+
+ architecture-beta
+ service db(database)[Database]
+ service s3(disk)[Storage]
+ service serv1(server)[Server 1]
+ service serv2(server)[Server 2]
+ service disk(disk)[Disk]
+
+ db:L -- R:s3
+ serv1:L -- T:s3
+ serv2:L -- B:s3
+ serv1:T -- B:disk
+
+
+
+ Arrow Tests
+
+ architecture-beta
+ service servC(server)[Server 1]
+ service servL(server)[Server 2]
+ service servR(server)[Server 3]
+ service servT(server)[Server 4]
+ service servB(server)[Server 5]
+
+ servC:L <--> R:servL
+ servC:R <--> L:servR
+ servC:T <--> B:servT
+ servC:B <--> T:servB
+
+ servL:T <--> L:servT
+ servL:B <--> L:servB
+ servR:T <--> R:servT
+ servR:B <--> R:servB
+
+
+ architecture-beta
+ service servC(server)[Server 1]
+ service servL(server)[Server 2]
+ service servR(server)[Server 3]
+ service servT(server)[Server 4]
+ service servB(server)[Server 5]
+
+ servC:L <--> R:servL
+ servC:R <--> L:servR
+ servC:T <--> B:servT
+ servC:B <--> T:servB
+
+ servT:L <--> T:servL
+ servB:L <--> B:servL
+ servT:R <--> T:servR
+ servB:R <--> B:servR
+
+
+
+ Group Edges
+
+ architecture-beta
+ group left_group(cloud)[Left]
+ group right_group(cloud)[Right]
+ group top_group(cloud)[Top]
+ group bottom_group(cloud)[Bottom]
+ group center_group(cloud)[Center]
+
+ service left_disk(disk)[Disk] in left_group
+ service right_disk(disk)[Disk] in right_group
+ service top_disk(disk)[Disk] in top_group
+ service bottom_disk(disk)[Disk] in bottom_group
+ service center_disk(disk)[Disk] in center_group
+
+ left_disk{group}:R <--> L:center_disk{group}
+ right_disk{group}:L <--> R:center_disk{group}
+ top_disk{group}:B <--> T:center_disk{group}
+ bottom_disk{group}:T <--> B:center_disk{group}
+
+
+
+ Edge Label Test
+
+ architecture-beta
+ service servC(server)[Server 1]
+ service servL(server)[Server 2]
+ service servR(server)[Server 3]
+ service servT(server)[Server 4]
+ service servB(server)[Server 5]
+
+ servC:L -[Label]- R:servL
+ servC:R -[Label]- L:servR
+ servC:T -[Label]- B:servT
+ servC:B -[Label]- T:servB
+
+ servL:T -[Label]- L:servT
+ servL:B -[Label]- L:servB
+ servR:T -[Label]- R:servT
+ servR:B -[Label]- R:servB
+
+
+ architecture-beta
+ service servC(server)[Server 1]
+ service servL(server)[Server 2]
+ service servR(server)[Server 3]
+ service servT(server)[Server 4]
+ service servB(server)[Server 5]
+
+ servC:L -[Label that is Long]- R:servL
+ servC:R -[Label that is Long]- L:servR
+ servC:T -[Label that is Long]- B:servT
+ servC:B -[Label that is Long]- T:servB
+
+ servL:T -[Label that is Long]- L:servT
+ servL:B -[Label that is Long]- L:servB
+ servR:T -[Label that is Long]- R:servT
+ servR:B -[Label that is Long]- R:servB
+
+
+
+ Junction Demo
+
+ architecture-beta
+ service left_disk(disk)[Disk]
+ service top_disk(disk)[Disk]
+ service bottom_disk(disk)[Disk]
+ service top_gateway(internet)[Gateway]
+ service bottom_gateway(internet)[Gateway]
+ junction juncC
+ junction juncR
+
+ left_disk:R -- L:juncC
+ top_disk:B -- T:juncC
+ bottom_disk:T -- B:juncC
+ juncC:R -- L:juncR
+ top_gateway:B -- T:juncR
+ bottom_gateway:T -- B:juncR
+
+
+
+ Junction Demo Groups
+
+ architecture-beta
+ group left
+ group right
+ service left_disk(disk)[Disk] in left
+ service top_disk(disk)[Disk] in left
+ service bottom_disk(disk)[Disk] in left
+ service top_gateway(internet)[Gateway] in right
+ service bottom_gateway(internet)[Gateway] in right
+ junction juncC in left
+ junction juncR in right
+
+ left_disk:R -- L:juncC
+ top_disk:B -- T:juncC
+ bottom_disk:T -- B:juncC
+
+
+ top_gateway:B <-- T:juncR
+ bottom_gateway:T <-- B:juncR
+
+ juncC{group}:R --> L:juncR{group}
+
+
+
+ External Icons Demo
+
+ architecture-beta
+ service s3(logos:aws-s3)[Cloud Store]
+ service ec2(logos:aws-ec2)[Server]
+ service api(logos:aws-api-gateway)[Api Gateway]
+ service fa(fa:image)[Font Awesome Icon]
+
+
+
+
+
diff --git a/demos/er.html b/demos/er.html
index 0b4b82bac..b6c503c2e 100644
--- a/demos/er.html
+++ b/demos/er.html
@@ -125,6 +125,35 @@
+
+ erDiagram
+ p[Person] {
+ string firstName
+ string lastName
+ }
+ a["Customer Account"] {
+ string email
+ }
+
+ b["Customer Account Secondary"] {
+ string email
+ }
+
+ c["Customer Account Tertiary"] {
+ string email
+ }
+
+ d["Customer Account Nth"] {
+ string email
+ }
+
+ p ||--o| a : "has
one"
+ p ||--o| b : "has
one
two"
+ p ||--o| c : "has
one
two
three"
+ p ||--o| d : "has
one
two
three
...
Nth"
+
+
+
erDiagram
_customer_order {
diff --git a/demos/index.html b/demos/index.html
index 61a86a2aa..07b51a313 100644
--- a/demos/index.html
+++ b/demos/index.html
@@ -88,6 +88,9 @@
+
+
+