Skip to content

Commit 665cb90

Browse files
authored
Merge branch 'mermaid-js:develop' into develop
2 parents c6b13f1 + a3a5040 commit 665cb90

30 files changed

+1705
-933
lines changed

.changeset/chatty-insects-dream.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'mermaid': patch
3+
---
4+
5+
fix(treemap): Fixed treemap classDef style application to properly apply user-defined styles

.changeset/lazy-brooms-battle.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'mermaid': patch
3+
---
4+
5+
feat: add alias support for new participant syntax of sequence diagrams

.changeset/tricky-rivers-stand.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'mermaid': patch
3+
---
4+
5+
fix: validate dates and tick interval to prevent UI freeze/crash in gantt diagramtype

.github/workflows/e2e-timings.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ jobs:
5858
echo "EOF" >> $GITHUB_OUTPUT
5959
6060
- name: Commit and create pull request
61-
uses: peter-evans/create-pull-request@0edc001d28a2959cd7a6b505629f1d82f0a6e67d
61+
uses: peter-evans/create-pull-request@84ae59a2cdc2258d6fa0732dd66352dddae2a412
6262
with:
6363
add-paths: |
6464
cypress/timings.json

.github/workflows/update-browserlist.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
message: 'chore: update browsers list'
2020
push: false
2121
- name: Create Pull Request
22-
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
22+
uses: peter-evans/create-pull-request@84ae59a2cdc2258d6fa0732dd66352dddae2a412 # v7.0.9
2323
with:
2424
branch: update-browserslist
2525
title: Update Browserslist

cypress/integration/rendering/gantt.spec.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -833,4 +833,34 @@ describe('Gantt diagram', () => {
833833
{}
834834
);
835835
});
836+
it('should handle seconds-only format with tickInterval (issue #5496)', () => {
837+
imgSnapshotTest(
838+
`
839+
gantt
840+
tickInterval 1second
841+
dateFormat ss
842+
axisFormat %s
843+
844+
section Network Request
845+
RTT : rtt, 0, 20
846+
`,
847+
{}
848+
);
849+
});
850+
it('should handle dates with year typo like 202 instead of 2024 (issue #5496)', () => {
851+
imgSnapshotTest(
852+
`
853+
gantt
854+
title Schedule
855+
dateFormat YYYY-MM-DD
856+
tickInterval 1week
857+
axisFormat %m-%d
858+
859+
section Vacation
860+
London : 2024-12-01, 7d
861+
London : 202-12-01, 7d
862+
`,
863+
{}
864+
);
865+
});
836866
});

cypress/integration/rendering/sequencediagram-v2.spec.js

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,5 +776,194 @@ describe('Sequence Diagram Special Cases', () => {
776776
);
777777
});
778778
});
779+
780+
describe('Participant Stereotypes with Aliases', () => {
781+
it('should render participants with stereotypes and aliases', () => {
782+
imgSnapshotTest(
783+
`sequenceDiagram
784+
participant API@{ "type" : "boundary" } as Public API
785+
participant Auth@{ "type" : "control" } as Auth Controller
786+
participant DB@{ "type" : "database" } as User Database
787+
participant Cache@{ "type" : "entity" } as Cache Layer
788+
API ->> Auth: Authenticate request
789+
Auth ->> DB: Query user
790+
DB -->> Auth: User data
791+
Auth ->> Cache: Store session
792+
Cache -->> Auth: Confirmed
793+
Auth -->> API: Token`,
794+
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
795+
);
796+
});
797+
798+
it('should render actors with stereotypes and aliases', () => {
799+
imgSnapshotTest(
800+
`sequenceDiagram
801+
actor U@{ "type" : "actor" } as End User
802+
actor A@{ "type" : "boundary" } as API Gateway
803+
actor S@{ "type" : "control" } as Service Layer
804+
actor D@{ "type" : "database" } as Data Store
805+
U ->> A: Send request
806+
A ->> S: Process
807+
S ->> D: Persist
808+
D -->> S: Success
809+
S -->> A: Response
810+
A -->> U: Result`,
811+
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
812+
);
813+
});
814+
815+
it('should render mixed participants and actors with stereotypes and aliases', () => {
816+
imgSnapshotTest(
817+
`sequenceDiagram
818+
actor Client@{ "type" : "actor" } AS Mobile Client
819+
participant Gateway@{ "type" : "boundary" } as API Gateway
820+
participant OrderSvc@{ "type" : "control" } as Order Service
821+
participant Queue@{ "type" : "queue" } as Message Queue
822+
participant DB@{ "type" : "database" } as Order Database
823+
participant Logs@{ "type" : "collections" } as Audit Logs
824+
Client ->> Gateway: Place order
825+
Gateway ->> OrderSvc: Validate order
826+
OrderSvc ->> Queue: Queue for processing as well
827+
OrderSvc ->> DB: Save order
828+
OrderSvc ->> Logs: Log transaction
829+
Queue -->> OrderSvc: Processing started AS Well
830+
DB -->> OrderSvc: Order saved
831+
Logs -->> OrderSvc: Logged
832+
OrderSvc -->> Gateway: Order confirmed
833+
Gateway -->> Client: Confirmation`,
834+
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
835+
);
836+
});
837+
838+
it('should render stereotypes with aliases in boxes', () => {
839+
imgSnapshotTest(
840+
`sequenceDiagram
841+
box rgb(200,220,255) Frontend Layer
842+
actor User@{ "type" : "actor" } as End User
843+
participant UI@{ "type" : "boundary" } as User Interface
844+
end
845+
box rgb(255,220,200) Backend Layer
846+
participant API@{ "type" : "boundary" } as REST API
847+
participant Svc@{ "type" : "control" } as Business Logic
848+
end
849+
box rgb(220,255,200) Data Layer
850+
participant DB@{ "type" : "database" } as Primary DB
851+
participant Cache@{ "type" : "entity" } as Cache Store
852+
end
853+
User ->> UI: Click button
854+
UI ->> API: HTTP request
855+
API ->> Svc: Process
856+
Svc ->> Cache: Check cache
857+
Cache -->> Svc: Cache miss
858+
Svc ->> DB: Query data
859+
DB -->> Svc: Data
860+
Svc ->> Cache: Update cache
861+
Svc -->> API: Response
862+
API -->> UI: Data
863+
UI -->> User: Display`,
864+
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
865+
);
866+
});
867+
868+
it('should render stereotypes with aliases and complex interactions', () => {
869+
imgSnapshotTest(
870+
`sequenceDiagram
871+
participant Web@{ "type" : "boundary" } as Web Portal
872+
participant Auth@{ "type" : "control" } as Auth Service
873+
participant UserDB@{ "type" : "database" } as User DB
874+
participant Queue@{ "type" : "queue" } as Event Queue
875+
participant Audit@{ "type" : "collections" } as Audit Trail
876+
Web ->> Auth: Login request
877+
activate Auth
878+
Auth ->> UserDB: Verify credentials
879+
activate UserDB
880+
UserDB -->> Auth: User found
881+
deactivate UserDB
882+
alt Valid credentials
883+
Auth ->> Queue: Publish login event
884+
Auth ->> Audit: Log success
885+
par Parallel processing
886+
Queue -->> Auth: Event queued
887+
and
888+
Audit -->> Auth: Logged
889+
end
890+
Auth -->> Web: Success token
891+
else Invalid credentials
892+
Auth ->> Audit: Log failure
893+
Audit -->> Auth: Logged
894+
Auth --x Web: Access denied
895+
end
896+
deactivate Auth
897+
Note over Web,Audit: All interactions logged`,
898+
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
899+
);
900+
});
901+
});
902+
903+
describe('Participant Inline Alias in Config', () => {
904+
it('should render participants with inline alias in config object', () => {
905+
imgSnapshotTest(
906+
`sequenceDiagram
907+
participant API@{ "type" : "boundary", "alias": "Public API" }
908+
participant Auth@{ "type" : "control", "alias": "Auth Service" }
909+
participant DB@{ "type" : "database", "alias": "User DB" }
910+
API ->> Auth: Login request
911+
Auth ->> DB: Query user
912+
DB -->> Auth: User data
913+
Auth -->> API: Token`,
914+
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
915+
);
916+
});
917+
918+
it('should render actors with inline alias in config object', () => {
919+
imgSnapshotTest(
920+
`sequenceDiagram
921+
actor U@{ "type" : "actor", "alias": "End User" }
922+
actor G@{ "type" : "boundary", "alias": "Gateway" }
923+
actor S@{ "type" : "control", "alias": "Service" }
924+
U ->> G: Request
925+
G ->> S: Process
926+
S -->> G: Response
927+
G -->> U: Result`,
928+
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
929+
);
930+
});
931+
932+
it('should handle mixed inline and external alias syntax', () => {
933+
imgSnapshotTest(
934+
`sequenceDiagram
935+
participant A@{ "type" : "boundary", "alias": "Service A" }
936+
participant B@{ "type" : "control" } as Service B
937+
participant C@{ "type" : "database" }
938+
A ->> B: Request
939+
B ->> C: Query
940+
C -->> B: Data
941+
B -->> A: Response`,
942+
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
943+
);
944+
});
945+
946+
it('should prioritize external alias over inline alias', () => {
947+
imgSnapshotTest(
948+
`sequenceDiagram
949+
participant API@{ "type" : "boundary", "alias": "Internal Name" } as External Name
950+
participant DB@{ "type" : "database", "alias": "Internal DB" } AS External DB
951+
API ->> DB: Query
952+
DB -->> API: Result`,
953+
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
954+
);
955+
});
956+
957+
it('should render inline alias with only alias field (no type)', () => {
958+
imgSnapshotTest(
959+
`sequenceDiagram
960+
participant API@{ "alias": "Public API" }
961+
participant Auth@{ "alias": "Auth Service" }
962+
API ->> Auth: Request
963+
Auth -->> API: Response`,
964+
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
965+
);
966+
});
967+
});
779968
});
780969
});

cypress/integration/rendering/treemap.spec.ts

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,8 +327,97 @@ classDef sales fill:#c3a66b,stroke:#333;
327327
{}
328328
);
329329
});
330+
331+
it('12: should apply classDef fill color to leaf nodes', () => {
332+
imgSnapshotTest(
333+
`treemap-beta
334+
"Root"
335+
"Item A": 30:::redClass
336+
"Item B": 20
337+
"Item C": 25:::blueClass
338+
339+
classDef redClass fill:#ff0000;
340+
classDef blueClass fill:#0000ff;
341+
`,
342+
{}
343+
);
344+
});
345+
346+
it('13: should apply classDef stroke styles to sections', () => {
347+
imgSnapshotTest(
348+
`treemap-beta
349+
%% This is a comment
350+
"Category A":::thickBorder
351+
"Item A1": 10
352+
"Item A2": 20
353+
%% Another comment
354+
"Category B":::dashedBorder
355+
"Item B1": 15
356+
"Item B2": 25
357+
358+
classDef thickBorder stroke:red,stroke-width:8px;
359+
classDef dashedBorder stroke:black,stroke-dasharray:5,stroke-width:8px;
360+
`,
361+
{}
362+
);
363+
});
364+
365+
it('14: should apply classDef color to text labels', () => {
366+
imgSnapshotTest(
367+
`treemap-beta
368+
"Products"
369+
"Electronics":::whiteText
370+
"Phones": 40
371+
"Laptops": 30
372+
"Furniture":::darkText
373+
"Chairs": 25
374+
"Tables": 20
375+
376+
classDef whiteText fill:#2c3e50,color:#ffffff;
377+
classDef darkText fill:#ecf0f1,color:#000000;
378+
`,
379+
{}
380+
);
381+
});
382+
383+
it('15: should apply multiple classDef properties simultaneously', () => {
384+
imgSnapshotTest(
385+
`treemap-beta
386+
"Budget"
387+
"Critical":::critical
388+
"Server Costs": 50000
389+
"Salaries": 80000
390+
"Normal":::normal
391+
"Office Supplies": 5000
392+
"Marketing": 15000
393+
classDef critical fill:#e74c3c,color:#fff,stroke:#c0392b,stroke-width:3px;
394+
classDef normal fill:#3498db,color:#fff,stroke:#2980b9,stroke-width:1px;
395+
`,
396+
{}
397+
);
398+
});
399+
400+
it('16: should handle classDef on nested sections and leaves', () => {
401+
imgSnapshotTest(
402+
`treemap-beta
403+
"Company"
404+
"Engineering":::engSection
405+
"Frontend": 30:::highlight
406+
"Backend": 40
407+
"DevOps": 20:::highlight
408+
"Sales"
409+
"Direct": 35
410+
"Channel": 25:::highlight
411+
412+
classDef engSection fill:#9b59b6,stroke:#8e44ad,stroke-width:2px;
413+
classDef highlight fill:#f39c12,color:#000,stroke:#e67e22,stroke-width:2px;
414+
`,
415+
{}
416+
);
417+
});
418+
330419
/*
331-
it.skip('12: should render a treemap with title', () => {
420+
it.skip('17: should render a treemap with title', () => {
332421
imgSnapshotTest(
333422
`
334423
treemap-beta

docs/config/setup/mermaid/interfaces/ParseOptions.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@
1010

1111
# Interface: ParseOptions
1212

13-
Defined in: [packages/mermaid/src/types.ts:88](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L88)
13+
Defined in: [packages/mermaid/src/types.ts:89](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L89)
1414

1515
## Properties
1616

1717
### suppressErrors?
1818

1919
> `optional` **suppressErrors**: `boolean`
2020
21-
Defined in: [packages/mermaid/src/types.ts:93](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L93)
21+
Defined in: [packages/mermaid/src/types.ts:94](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L94)
2222

2323
If `true`, parse will return `false` instead of throwing error when the diagram is invalid.
2424
The `parseError` function will not be called.

0 commit comments

Comments
 (0)