mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-11-11 16:24:12 +01:00
Compare commits
9 Commits
fix/sequen
...
tooltip-po
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8d89db397 | ||
|
|
9448aec481 | ||
|
|
fcd2791b2d | ||
|
|
feed9d75bb | ||
|
|
f356836f71 | ||
|
|
ff15e51d2e | ||
|
|
ddd4763db2 | ||
|
|
6670ad7229 | ||
|
|
b4a5fe6c45 |
5
.changeset/tricky-lions-behave.md
Normal file
5
.changeset/tricky-lions-behave.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: Correct tooltip placement to appear near hovered element
|
||||
@@ -776,664 +776,5 @@ describe('Sequence Diagram Special Cases', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('Sequence Diagram Rendering with Autonumber and All Arrow Types', () => {
|
||||
describe('Autonumber with All Arrow Types', () => {
|
||||
it('should render all arrow types with autonumbering', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
Alice->>Bob: Solid arrow (->>)
|
||||
Bob-->>Alice: Dotted arrow (-->>)
|
||||
Alice->Charlie: Solid open arrow (->)
|
||||
Charlie-->Dave: Dotted open arrow (-->)
|
||||
Alice-xBob: Solid cross (-x)
|
||||
Bob--xAlice: Dotted cross (--x)
|
||||
Alice-)Charlie: Solid point async (-)
|
||||
Charlie--)Dave: Dotted point async (--)
|
||||
Alice<<->>Bob: Bidirectional solid (<<->>)
|
||||
Charlie<<-->>Dave: Bidirectional dotted (<<-->>)
|
||||
Alice-|\\Bob: Solid top half (-|\\)
|
||||
Bob-|/Alice: Solid bottom half (-|/)
|
||||
Alice-\\\\Charlie: Stick top half (-\\\\)
|
||||
Charlie-//Dave: Stick bottom half (-//)
|
||||
Dave/|-Charlie: Solid top reverse (/|-)
|
||||
Charlie\\|-Bob: Solid bottom reverse (\\|-)
|
||||
Bob//-Alice: Stick top reverse (//-)
|
||||
Alice\\\\-Bob: Stick bottom reverse (\\\\-)
|
||||
Alice--|\\Bob: Dotted solid top (--|\\)
|
||||
Bob--|/Alice: Dotted solid bottom (--|/)
|
||||
Alice--\\\\Charlie: Dotted stick top (--\\\\)
|
||||
Charlie--//Dave: Dotted stick bottom (--//)
|
||||
Dave/|--Charlie: Dotted solid top reverse (/|--)
|
||||
Charlie\\|--Bob: Dotted solid bottom reverse (\\|--)
|
||||
Bob//--Alice: Dotted stick top reverse (//--)
|
||||
Alice\\\\--Bob: Dotted stick bottom reverse (\\\\--)
|
||||
Alice->>()Bob: Solid with central connection
|
||||
Bob()-->>Alice: Dotted with reverse central
|
||||
Alice()->>()Charlie: Dual central connections`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render all arrow types with autonumbering - left to right only', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
Alice->>Bob: Solid arrow (->>)
|
||||
Alice-->>Bob: Dotted arrow (-->>)
|
||||
Alice->Bob: Solid open arrow (->)
|
||||
Alice-->Bob: Dotted open arrow (-->)
|
||||
Alice-xBob: Solid cross (-x)
|
||||
Alice--xBob: Dotted cross (--x)
|
||||
Alice-)Bob: Solid point async (-)
|
||||
Alice--)Bob: Dotted point async (--)
|
||||
Alice<<->>Bob: Bidirectional solid (<<->>)
|
||||
Alice<<-->>Bob: Bidirectional dotted (<<-->>)
|
||||
Alice-|\\Bob: Solid top half (-|\\)
|
||||
Alice-|/Bob: Solid bottom half (-|/)
|
||||
Alice-\\\\Bob: Stick top half (-\\\\)
|
||||
Alice-//Bob: Stick bottom half (-//)
|
||||
Bob/|-Alice: Solid top reverse (/|-)
|
||||
Bob\\|-Alice: Solid bottom reverse (\\|-)
|
||||
Bob//-Alice: Stick top reverse (//-)
|
||||
Bob\\\\-Alice: Stick bottom reverse (\\\\-)
|
||||
Alice--|\\Bob: Dotted solid top (--|\\)
|
||||
Alice--|/Bob: Dotted solid bottom (--|/)
|
||||
Alice--\\\\Bob: Dotted stick top (--\\\\)
|
||||
Alice--//Bob: Dotted stick bottom (--//)
|
||||
Bob/|--Alice: Dotted solid top reverse (/|--)
|
||||
Bob\\|--Alice: Dotted solid bottom reverse (\\|--)
|
||||
Bob//--Alice: Dotted stick top reverse (//--)
|
||||
Bob\\\\--Alice: Dotted stick bottom reverse (\\\\--)
|
||||
Alice->>()Bob: Solid with central connection
|
||||
Alice()-->>Bob: Dotted with reverse central
|
||||
Alice()->>()Bob: Dual central connections`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render central connections with autonumbering', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
Alice->>()Bob: Central connection at destination
|
||||
Bob()->>Alice: Reverse central at source
|
||||
Alice()->>()Bob: Dual central connections
|
||||
Bob->>()Charlie: Another central connection
|
||||
Charlie()-->>Alice: Reverse central dotted
|
||||
Alice()<<-->>()Bob: Dual central bidirectional`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render bidirectional arrows with autonumbering', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
Alice<<->>Bob: Bidirectional solid left to right
|
||||
Bob<<->>Alice: Bidirectional solid right to left
|
||||
Alice<<-->>Charlie: Bidirectional dotted left to right
|
||||
Charlie<<-->>Alice: Bidirectional dotted right to left
|
||||
Bob<<->>Charlie: Bidirectional solid
|
||||
Charlie<<-->>Bob: Bidirectional dotted`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render reverse arrows with autonumbering', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
Bob/|-Alice: Solid top reverse left to right
|
||||
Alice/|-Bob: Solid top reverse right to left
|
||||
Bob\\|-Alice: Solid bottom reverse left to right
|
||||
Alice\\|-Bob: Solid bottom reverse right to left
|
||||
Bob//-Alice: Stick top reverse left to right
|
||||
Alice//-Bob: Stick top reverse right to left
|
||||
Bob\\\\-Alice: Stick bottom reverse left to right
|
||||
Alice\\\\-Bob: Stick bottom reverse right to left
|
||||
Bob/|--Alice: Dotted solid top reverse
|
||||
Alice\\|--Bob: Dotted solid bottom reverse
|
||||
Bob//--Alice: Dotted stick top reverse
|
||||
Alice\\\\--Bob: Dotted stick bottom reverse`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Central Connections with Autonumber - Comprehensive Coverage', () => {
|
||||
it('should render CENTRAL_CONNECTION with normal arrows - left to right', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
Alice->>()Bob: Solid arrow with circle at destination
|
||||
Alice-->>()Bob: Dotted arrow with circle at destination
|
||||
Alice->()Bob: Open arrow with circle at destination
|
||||
Alice--x()Bob: Cross arrow with circle at destination
|
||||
Alice--)()Bob: Close arrow with circle at destination`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render CENTRAL_CONNECTION with normal arrows - right to left', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
Bob->>()Alice: Solid arrow with circle at destination (RTL)
|
||||
Charlie-->>()Bob: Dotted arrow with circle at destination (RTL)
|
||||
Bob->()Alice: Open arrow with circle at destination (RTL)
|
||||
Charlie--x()Alice: Cross arrow with circle at destination (RTL)
|
||||
Bob--)()Alice: Close arrow with circle at destination (RTL)`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render CENTRAL_CONNECTION with reverse arrows - left to right', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
Bob/|-()Alice: Solid top reverse with circle (LTR)
|
||||
Bob\\|-()Alice: Solid bottom reverse with circle (LTR)
|
||||
Bob//-()Alice: Stick top reverse with circle (LTR)
|
||||
Bob\\\\-()Alice: Stick bottom reverse with circle (LTR)
|
||||
Bob/|--()Alice: Dotted solid top reverse with circle (LTR)
|
||||
Bob\\|--()Alice: Dotted solid bottom reverse with circle (LTR)
|
||||
Bob//--()Alice: Dotted stick top reverse with circle (LTR)
|
||||
Bob\\\\--()Alice: Dotted stick bottom reverse with circle (LTR)`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render CENTRAL_CONNECTION with reverse arrows - right to left', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
Alice/|-()Bob: Solid top reverse with circle (RTL)
|
||||
Alice\\|-()Bob: Solid bottom reverse with circle (RTL)
|
||||
Alice//-()Bob: Stick top reverse with circle (RTL)
|
||||
Alice\\\\-()Bob: Stick bottom reverse with circle (RTL)
|
||||
Alice/|--()Bob: Dotted solid top reverse with circle (RTL)
|
||||
Alice\\|--()Bob: Dotted solid bottom reverse with circle (RTL)
|
||||
Alice//--()Bob: Dotted stick top reverse with circle (RTL)
|
||||
Alice\\\\--()Bob: Dotted stick bottom reverse with circle (RTL)`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render Central_Connection_REVERSE ()->> normal LTR', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
Alice()->>Bob: Circle at source with solid arrow
|
||||
Alice()-->>Bob: Circle at source with dotted arrow
|
||||
Alice()->Bob: Circle at source with open arrow
|
||||
Alice()--xBob: Circle at source with cross arrow
|
||||
Alice()--)Bob: Circle at source with close arrow`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render Central_Connection_REVERSE ()->> normal RTL', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
Bob()->>Alice: Circle at source with solid arrow (RTL)
|
||||
Charlie()-->>Bob: Circle at source with dotted arrow (RTL)
|
||||
Bob()->Alice: Circle at source with open arrow (RTL)
|
||||
Charlie()--xAlice: Circle at source with cross arrow (RTL)
|
||||
Bob()--)Alice: Circle at source with close arrow (RTL)`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render Central_Connection_REVERSE ()->> reverse LTR', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
Bob()/|-Alice: Circle at source with solid top reverse (LTR)
|
||||
Bob()\\|-Alice: Circle at source with solid bottom reverse (LTR)
|
||||
Bob()//-Alice: Circle at source with stick top reverse (LTR)
|
||||
Bob()\\\\-Alice: Circle at source with stick bottom reverse (LTR)
|
||||
Bob()/|--Alice: Circle at source with dotted solid top reverse (LTR)
|
||||
Bob()\\|--Alice: Circle at source with dotted solid bottom reverse (LTR)
|
||||
Bob()//--Alice: Circle at source with dotted stick top reverse (LTR)
|
||||
Bob()\\\\--Alice: Circle at source with dotted stick bottom reverse (LTR)`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render Central_Connection_REVERSE ()->> reverse RTL', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
Alice()/|-Bob: Circle at source with solid top reverse (RTL)
|
||||
Alice()\\|-Bob: Circle at source with solid bottom reverse (RTL)
|
||||
Alice()//-Bob: Circle at source with stick top reverse (RTL)
|
||||
Alice()\\\\-Bob: Circle at source with stick bottom reverse (RTL)
|
||||
Alice()/|--Bob: Circle at source with dotted solid top reverse (RTL)
|
||||
Alice()\\|--Bob: Circle at source with dotted solid bottom reverse (RTL)
|
||||
Alice()//--Bob: Circle at source with dotted stick top reverse (RTL)
|
||||
Alice()\\\\--Bob: Circle at source with dotted stick bottom reverse (RTL)`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render Central_Connection_DUAL ()->>() normal LTR', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
Alice()->>()Bob: Circles at both ends with solid arrow
|
||||
Alice()-->>()Bob: Circles at both ends with dotted arrow
|
||||
Alice()->()Bob: Circles at both ends with open arrow
|
||||
Alice()--x()Bob: Circles at both ends with cross arrow
|
||||
Alice()--)()Bob: Circles at both ends with close arrow`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render Central_Connection_DUAL ()->>() normal RTL', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
Bob()->>()Alice: Circles at both ends with solid arrow (RTL)
|
||||
Charlie()-->>()Bob: Circles at both ends with dotted arrow (RTL)
|
||||
Bob()->()Alice: Circles at both ends with open arrow (RTL)
|
||||
Charlie()--x()Alice: Circles at both ends with cross arrow (RTL)
|
||||
Bob()--)()Alice: Circles at both ends with close arrow (RTL)`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render Central_Connection_DUAL ()->>() reverse LTR', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
Bob()/|-()Alice: Circles at both ends with solid top reverse (LTR)
|
||||
Bob()\\|-()Alice: Circles at both ends with solid bottom reverse (LTR)
|
||||
Bob()//-()Alice: Circles at both ends with stick top reverse (LTR)
|
||||
Bob()\\\\-()Alice: Circles at both ends with stick bottom reverse (LTR)
|
||||
Bob()/|--()Alice: Circles at both ends with dotted solid top reverse (LTR)
|
||||
Bob()\\|--()Alice: Circles at both ends with dotted solid bottom reverse (LTR)
|
||||
Bob()//--()Alice: Circles at both ends with dotted stick top reverse (LTR)
|
||||
Bob()\\\\--()Alice: Circles at both ends with dotted stick bottom reverse (LTR)`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render Central_Connection_DUAL ()->>() reverse RTL', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
Alice()/|-()Bob: Circles at both ends with solid top reverse (RTL)
|
||||
Alice()\\|-()Bob: Circles at both ends with solid bottom reverse (RTL)
|
||||
Alice()//-()Bob: Circles at both ends with stick top reverse (RTL)
|
||||
Alice()\\\\-()Bob: Circles at both ends with stick bottom reverse (RTL)
|
||||
Alice()/|--()Bob: Circles at both ends with dotted solid top reverse (RTL)
|
||||
Alice()\\|--()Bob: Circles at both ends with dotted solid bottom reverse (RTL)
|
||||
Alice()//--()Bob: Circles at both ends with dotted stick top reverse (RTL)
|
||||
Alice()\\\\--()Bob: Circles at both ends with dotted stick bottom reverse (RTL)`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render mixed central connections with autonumber', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
participant David
|
||||
|
||||
Note over Alice,David: Normal arrows with central connections
|
||||
Alice->>()Bob: CENTRAL_CONNECTION LTR
|
||||
Bob->>()Alice: CENTRAL_CONNECTION RTL
|
||||
Alice()->>Bob: CENTRAL_CONNECTION_REVERSE LTR
|
||||
Bob()->>Alice: CENTRAL_CONNECTION_REVERSE RTL
|
||||
Alice()->>()Bob: CENTRAL_CONNECTION_DUAL LTR
|
||||
Bob()->>()Alice: CENTRAL_CONNECTION_DUAL RTL
|
||||
|
||||
Note over Alice,David: Reverse arrows with central connections
|
||||
Bob/|-()Alice: Reverse with CENTRAL_CONNECTION LTR
|
||||
Alice/|-()Bob: Reverse with CENTRAL_CONNECTION RTL
|
||||
Bob()/|-Alice: Reverse with CENTRAL_CONNECTION_REVERSE LTR
|
||||
Alice()/|-Bob: Reverse with CENTRAL_CONNECTION_REVERSE RTL
|
||||
Bob()/|-()Alice: Reverse with CENTRAL_CONNECTION_DUAL LTR
|
||||
Alice()/|-()Bob: Reverse with CENTRAL_CONNECTION_DUAL RTL
|
||||
|
||||
Note over Alice,David: Mixed with different participants
|
||||
Alice->>()Charlie: Skip participant
|
||||
Charlie()->>Alice: Back skip
|
||||
Bob()->>()David: Another skip
|
||||
David()->>()Bob: Return skip`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render central connections with bidirectional arrows and autonumber', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
Alice()<<->>()Bob: Dual central with bidirectional solid LTR
|
||||
Bob()<<->>()Alice: Dual central with bidirectional solid RTL
|
||||
Alice()<<-->>()Bob: Dual central with bidirectional dotted LTR
|
||||
Bob()<<-->>()Alice: Dual central with bidirectional dotted RTL
|
||||
Alice<<->>()Bob: Central at end with bidirectional LTR
|
||||
Bob()<<->>Alice: Central at start with bidirectional RTL`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Self-Reference Arrows - Comprehensive Coverage', () => {
|
||||
it('should render self-reference with normal arrows - without autonumber', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
Alice->>Alice: Solid arrow self-reference
|
||||
Bob-->>Bob: Dotted arrow self-reference
|
||||
Charlie->Charlie: Open arrow self-reference
|
||||
Alice-->Alice: Dotted open arrow self-reference
|
||||
Bob-xBob: Cross arrow self-reference
|
||||
Charlie--xCharlie: Dotted cross self-reference`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render self-reference with normal arrows - with autonumber', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
Alice->>Alice: Solid arrow self-reference
|
||||
Bob-->>Bob: Dotted arrow self-reference
|
||||
Charlie->Charlie: Open arrow self-reference
|
||||
Alice-->Alice: Dotted open arrow self-reference
|
||||
Bob-xBob: Cross arrow self-reference
|
||||
Charlie--xCharlie: Dotted cross self-reference`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render self-reference with reverse arrows - without autonumber', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
Alice/|-Alice: Solid top reverse self-reference
|
||||
Bob\\|-Bob: Solid bottom reverse self-reference
|
||||
Charlie//-Charlie: Stick top reverse self-reference
|
||||
Alice\\\\-Alice: Stick bottom reverse self-reference
|
||||
Bob/|--Bob: Dotted solid top reverse self-reference
|
||||
Charlie\\|--Charlie: Dotted solid bottom reverse self-reference
|
||||
Alice//--Alice: Dotted stick top reverse self-reference
|
||||
Bob\\\\--Bob: Dotted stick bottom reverse self-reference`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render self-reference with reverse arrows - with autonumber', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
Alice/|-Alice: Solid top reverse self-reference
|
||||
Bob\\|-Bob: Solid bottom reverse self-reference
|
||||
Charlie//-Charlie: Stick top reverse self-reference
|
||||
Alice\\\\-Alice: Stick bottom reverse self-reference
|
||||
Bob/|--Bob: Dotted solid top reverse self-reference
|
||||
Charlie\\|--Charlie: Dotted solid bottom reverse self-reference
|
||||
Alice//--Alice: Dotted stick top reverse self-reference
|
||||
Bob\\\\--Bob: Dotted stick bottom reverse self-reference`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render self-reference with bidirectional arrows - without autonumber', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
Alice<<->>Alice: Bidirectional solid self-reference
|
||||
Bob<<-->>Bob: Bidirectional dotted self-reference
|
||||
Charlie<<->>Charlie: Another bidirectional solid
|
||||
Alice<<-->>Alice: Another bidirectional dotted`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render self-reference with bidirectional arrows - with autonumber', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
Alice<<->>Alice: Bidirectional solid self-reference
|
||||
Bob<<-->>Bob: Bidirectional dotted self-reference
|
||||
Charlie<<->>Charlie: Another bidirectional solid
|
||||
Alice<<-->>Alice: Another bidirectional dotted`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render comprehensive self-reference scenario - all arrow types mixed', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
|
||||
Note over Alice,Charlie: Normal arrows
|
||||
Alice->>Alice: Normal solid
|
||||
Bob-->>Bob: Normal dotted
|
||||
Charlie->Charlie: Normal open
|
||||
|
||||
Note over Alice,Charlie: Reverse arrows
|
||||
Alice/|-Alice: Reverse solid top
|
||||
Bob\\|-Bob: Reverse solid bottom
|
||||
|
||||
Note over Alice,Charlie: Bidirectional arrows
|
||||
Charlie<<->>Charlie: Bidirectional solid
|
||||
Alice<<-->>Alice: Bidirectional dotted`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render self-reference mixed with regular messages and autonumber', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
|
||||
Alice->>Bob: Regular message
|
||||
Bob->>Bob: Self-reference solid
|
||||
Bob-->>Charlie: Regular dotted
|
||||
Charlie->>Alice: Regular back
|
||||
Alice<<->>Alice: Self-ref bidirectional
|
||||
Alice()->>Bob: Regular with central
|
||||
Bob-->>Alice: Regular dotted back`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Comprehensive Test - All Message Types and Arrow Types', () => {
|
||||
it('should render all message types and arrow types in a single comprehensive test', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {'theme':'base'}}%%
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Alice
|
||||
participant Bob
|
||||
participant Charlie
|
||||
participant David
|
||||
|
||||
Note over Alice,David: SOLID ARROWS (Filled arrowhead)
|
||||
Alice->>Bob: Solid arrow (->>)
|
||||
Alice->Charlie: Solid open arrow (->)
|
||||
Alice-xDavid: Solid cross (-x)
|
||||
Alice-)Bob: Solid point async (-)
|
||||
|
||||
Note over Alice,David: DOTTED ARROWS (Dashed line)
|
||||
Bob-->>Alice: Dotted arrow (-->>)
|
||||
Bob-->Charlie: Dotted open arrow (-->)
|
||||
Bob--xDavid: Dotted cross (--x)
|
||||
Bob--)Alice: Dotted point async (--)
|
||||
|
||||
Note over Alice,David: BIDIRECTIONAL ARROWS
|
||||
Alice<<->>Bob: Bidirectional solid (<<->>)
|
||||
Charlie<<-->>David: Bidirectional dotted (<<-->>)
|
||||
|
||||
Note over Alice,David: REVERSE ARROWS (Half arrows)
|
||||
Bob/|-Alice: Solid top reverse (/|-)
|
||||
Charlie\\|-Bob: Solid bottom reverse (\\|-)
|
||||
David//-Alice: Stick top reverse (//)
|
||||
Alice\\\\-Bob: Stick bottom reverse (\\\\-)
|
||||
|
||||
Note over Alice,David: DOTTED REVERSE ARROWS
|
||||
Bob/|--Alice: Dotted solid top reverse (/|--)
|
||||
Charlie\\|--Bob: Dotted solid bottom reverse (\\|--)
|
||||
David//--Alice: Dotted stick top reverse (//--)
|
||||
Alice\\\\--Bob: Dotted stick bottom reverse (\\\\--)
|
||||
|
||||
Note over Alice,David: CENTRAL CONNECTIONS (Circle at destination)
|
||||
Alice->>()Bob: Solid with circle at destination
|
||||
Alice-->>()Charlie: Dotted with circle at destination
|
||||
Alice->()David: Open with circle at destination
|
||||
Alice--x()Bob: Cross with circle at destination
|
||||
|
||||
Note over Alice,David: CENTRAL CONNECTIONS REVERSE (Circle at source)
|
||||
Bob()->>Alice: Circle at source with solid
|
||||
Charlie()-->>Bob: Circle at source with dotted
|
||||
David()->Alice: Circle at source with open
|
||||
Bob()--xAlice: Circle at source with cross
|
||||
|
||||
Note over Alice,David: CENTRAL CONNECTIONS DUAL (Circles at both ends)
|
||||
Alice()->>()Bob: Dual circles with solid
|
||||
Alice()-->>()Charlie: Dual circles with dotted
|
||||
Alice()->()David: Dual circles with open
|
||||
Alice()--x()Bob: Dual circles with cross
|
||||
|
||||
Note over Alice,David: BIDIRECTIONAL WITH CENTRAL CONNECTIONS
|
||||
Alice()<<->>()Bob: Dual circles with bidirectional solid
|
||||
Charlie()<<-->>()David: Dual circles with bidirectional dotted
|
||||
|
||||
Note over Alice,David: SELF-REFERENCES (Same participant)
|
||||
Alice->>Alice: Self-reference solid
|
||||
Bob-->>Bob: Self-reference dotted
|
||||
Charlie->Charlie: Self-reference open
|
||||
David-xDavid: Self-reference cross
|
||||
|
||||
Note over Alice,David: SELF-REFERENCES WITH REVERSE ARROWS
|
||||
Alice/|-Alice: Self-ref reverse solid top
|
||||
Bob\\|-Bob: Self-ref reverse solid bottom
|
||||
Charlie//-Charlie: Self-ref reverse stick top
|
||||
David\\\\-David: Self-ref reverse stick bottom
|
||||
|
||||
Note over Alice,David: SELF-REFERENCES BIDIRECTIONAL
|
||||
Alice<<->>Alice: Self-ref bidirectional solid
|
||||
Bob<<-->>Bob: Self-ref bidirectional dotted
|
||||
|
||||
Note over Alice,David: MIXED COMPLEX SCENARIO
|
||||
Alice->>Bob: Regular message
|
||||
Bob()->>()Charlie: Central dual connection
|
||||
Charlie-->>David: Dotted response
|
||||
David/|-Alice: Reverse arrow
|
||||
Alice<<->>Bob: Bidirectional back
|
||||
Bob-xCharlie: Cross message
|
||||
Charlie()->>David: Central reverse
|
||||
David-->>()Alice: Dotted with circle`,
|
||||
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { select, type Selection } from 'd3';
|
||||
import { select } from 'd3';
|
||||
import { log } from '../../logger.js';
|
||||
import { getConfig } from '../../diagram-api/diagramAPI.js';
|
||||
import common from '../common/common.js';
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
setDiagramTitle,
|
||||
getDiagramTitle,
|
||||
} from '../common/commonDb.js';
|
||||
import { createTooltip } from '../common/svgDrawCommon.js';
|
||||
import { ClassMember } from './classTypes.js';
|
||||
import type {
|
||||
ClassRelation,
|
||||
@@ -26,6 +27,7 @@ import type {
|
||||
} from './classTypes.js';
|
||||
import type { Node, Edge } from '../../rendering-util/types.js';
|
||||
import type { DiagramDB } from '../../diagram-api/types.js';
|
||||
import DOMPurify from 'dompurify';
|
||||
|
||||
const MERMAID_DOM_ID_PREFIX = 'classId-';
|
||||
let classCounter = 0;
|
||||
@@ -483,43 +485,45 @@ export class ClassDB implements DiagramDB {
|
||||
LOLLIPOP: 4,
|
||||
};
|
||||
|
||||
// Utility function to escape HTML meta-characters
|
||||
private escapeHtml(str: string): string {
|
||||
return str
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
private readonly setupToolTips = (element: Element) => {
|
||||
let tooltipElem: Selection<HTMLDivElement, unknown, HTMLElement, unknown> =
|
||||
select('.mermaidTooltip');
|
||||
// @ts-expect-error - Incorrect types
|
||||
if ((tooltipElem._groups || tooltipElem)[0][0] === null) {
|
||||
tooltipElem = select('body')
|
||||
.append('div')
|
||||
.attr('class', 'mermaidTooltip')
|
||||
.style('opacity', 0);
|
||||
}
|
||||
const tooltipElem = createTooltip();
|
||||
|
||||
const svg = select(element).select('svg');
|
||||
|
||||
const nodes = svg.selectAll('g.node');
|
||||
const nodes = svg.selectAll('g').filter(function () {
|
||||
return select(this).attr('title') !== null;
|
||||
});
|
||||
|
||||
nodes
|
||||
.on('mouseover', (event: MouseEvent) => {
|
||||
const el = select(event.currentTarget as HTMLElement);
|
||||
const title = el.attr('title');
|
||||
// Don't try to draw a tooltip if no data is provided
|
||||
if (title === null) {
|
||||
if (!title) {
|
||||
return;
|
||||
}
|
||||
// @ts-ignore - getBoundingClientRect is not part of the d3 type definition
|
||||
const rect = this.getBoundingClientRect();
|
||||
|
||||
const rect = (event.currentTarget as Element).getBoundingClientRect();
|
||||
tooltipElem.transition().duration(200).style('opacity', '.9');
|
||||
tooltipElem
|
||||
.text(el.attr('title'))
|
||||
.style('left', window.scrollX + rect.left + (rect.right - rect.left) / 2 + 'px')
|
||||
.style('top', window.scrollY + rect.top - 14 + document.body.scrollTop + 'px');
|
||||
tooltipElem.html(tooltipElem.html().replace(/<br\/>/g, '<br/>'));
|
||||
.html(DOMPurify.sanitize(title))
|
||||
.style('left', `${window.scrollX + rect.left + rect.width / 2}px`)
|
||||
.style('top', `${window.scrollY + rect.bottom + 4}px`);
|
||||
|
||||
el.classed('hover', true);
|
||||
})
|
||||
.on('mouseout', (event: MouseEvent) => {
|
||||
tooltipElem.transition().duration(500).style('opacity', 0);
|
||||
const el = select(event.currentTarget as HTMLElement);
|
||||
el.classed('hover', false);
|
||||
select(event.currentTarget as HTMLElement).classed('hover', false);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { sanitizeUrl } from '@braintree/sanitize-url';
|
||||
import { select } from 'd3';
|
||||
import type { SVG, SVGGroup } from '../../diagram-api/types.js';
|
||||
import { lineBreakRegex } from './common.js';
|
||||
import type {
|
||||
@@ -135,3 +136,24 @@ export const getTextObj = (): TextObject => {
|
||||
};
|
||||
return testObject;
|
||||
};
|
||||
|
||||
export const createTooltip = () => {
|
||||
let tooltipElem = select<HTMLDivElement, unknown>('.mermaidTooltip');
|
||||
if (tooltipElem.empty()) {
|
||||
tooltipElem = select('body')
|
||||
.append('div')
|
||||
.attr('class', 'mermaidTooltip')
|
||||
.style('opacity', 0)
|
||||
.style('position', 'absolute')
|
||||
.style('text-align', 'center')
|
||||
.style('max-width', '200px')
|
||||
.style('padding', '2px')
|
||||
.style('font-size', '12px')
|
||||
.style('background', '#ffffde')
|
||||
.style('border', '1px solid #333')
|
||||
.style('border-radius', '2px')
|
||||
.style('pointer-events', 'none')
|
||||
.style('z-index', '100');
|
||||
}
|
||||
return tooltipElem;
|
||||
};
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
setDiagramTitle,
|
||||
getDiagramTitle,
|
||||
} from '../common/commonDb.js';
|
||||
import { createTooltip } from '../common/svgDrawCommon.js';
|
||||
import type {
|
||||
FlowClass,
|
||||
FlowEdge,
|
||||
@@ -26,7 +27,7 @@ import type {
|
||||
FlowVertex,
|
||||
FlowVertexTypeParam,
|
||||
} from './types.js';
|
||||
|
||||
import DOMPurify from 'dompurify';
|
||||
interface LinkData {
|
||||
id: string;
|
||||
}
|
||||
@@ -574,15 +575,7 @@ You have to call mermaid.initialize.`
|
||||
}
|
||||
|
||||
private setupToolTips(element: Element) {
|
||||
let tooltipElem = select('.mermaidTooltip');
|
||||
// @ts-ignore TODO: fix this
|
||||
if ((tooltipElem._groups || tooltipElem)[0][0] === null) {
|
||||
// @ts-ignore TODO: fix this
|
||||
tooltipElem = select('body')
|
||||
.append('div')
|
||||
.attr('class', 'mermaidTooltip')
|
||||
.style('opacity', 0);
|
||||
}
|
||||
const tooltipElem = createTooltip();
|
||||
|
||||
const svg = select(element).select('svg');
|
||||
|
||||
@@ -603,7 +596,7 @@ You have to call mermaid.initialize.`
|
||||
.text(el.attr('title'))
|
||||
.style('left', window.scrollX + rect.left + (rect.right - rect.left) / 2 + 'px')
|
||||
.style('top', window.scrollY + rect.bottom + 'px');
|
||||
tooltipElem.html(tooltipElem.html().replace(/<br\/>/g, '<br/>'));
|
||||
tooltipElem.html(DOMPurify.sanitize(title));
|
||||
el.classed('hover', true);
|
||||
})
|
||||
.on('mouseout', (e: MouseEvent) => {
|
||||
|
||||
@@ -294,25 +294,11 @@ const drawCentralConnection = function (
|
||||
const actors = diagObj.db.getActors();
|
||||
const fromActor = actors.get(msg.from);
|
||||
const toActor = actors.get(msg.to);
|
||||
const isAutoNumberOn = msgModel.sequenceVisible;
|
||||
let fromCenter = fromActor.x + fromActor.width / 2;
|
||||
let toCenter = toActor.x + toActor.width / 2;
|
||||
|
||||
// Determine arrow direction: left-to-right or right-to-left
|
||||
const isLeftToRight = fromCenter <= toCenter;
|
||||
const isReverse = isReverseArrowType(msg, diagObj);
|
||||
const fromCenter = fromActor.x + fromActor.width / 2;
|
||||
const toCenter = toActor.x + toActor.width / 2;
|
||||
|
||||
const g = elem.append('g');
|
||||
|
||||
const CENTRAL_CONNECTION_CIRCLE_OFFSET = 16.5;
|
||||
|
||||
const getCircleOffset = (isLeftToRight: boolean, isReverse: boolean) => {
|
||||
const baseOffset = isLeftToRight
|
||||
? CENTRAL_CONNECTION_CIRCLE_OFFSET
|
||||
: -CENTRAL_CONNECTION_CIRCLE_OFFSET;
|
||||
return isReverse ? -baseOffset : baseOffset;
|
||||
};
|
||||
|
||||
const drawCircle = (cx: number) => {
|
||||
g.append('circle')
|
||||
.attr('cx', cx)
|
||||
@@ -325,37 +311,6 @@ const drawCentralConnection = function (
|
||||
const { CENTRAL_CONNECTION, CENTRAL_CONNECTION_REVERSE, CENTRAL_CONNECTION_DUAL } =
|
||||
diagObj.db.LINETYPE;
|
||||
|
||||
// Calculate circle position adjustments when autonumber is enabled
|
||||
if (isAutoNumberOn) {
|
||||
switch (msg.centralConnection) {
|
||||
case CENTRAL_CONNECTION:
|
||||
// Pattern: actor ->>() actor - circle at destination
|
||||
if (isReverse) {
|
||||
toCenter += getCircleOffset(isLeftToRight, true);
|
||||
}
|
||||
// No adjustment for normal arrows
|
||||
break;
|
||||
|
||||
case CENTRAL_CONNECTION_REVERSE:
|
||||
// Pattern: actor ()->> actor - circle at source
|
||||
if (!isReverse) {
|
||||
fromCenter += getCircleOffset(isLeftToRight, false);
|
||||
}
|
||||
// No adjustment for reverse arrows
|
||||
break;
|
||||
|
||||
case CENTRAL_CONNECTION_DUAL:
|
||||
// Pattern: actor ()->>() actor - circles at both ends
|
||||
if (isReverse) {
|
||||
toCenter += getCircleOffset(isLeftToRight, true);
|
||||
} else {
|
||||
fromCenter += getCircleOffset(isLeftToRight, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw circles based on central connection type
|
||||
switch (msg.centralConnection) {
|
||||
case CENTRAL_CONNECTION:
|
||||
drawCircle(toCenter);
|
||||
@@ -483,17 +438,12 @@ const drawMessage = async function (diagram, msgModel, lineStartY: number, diagO
|
||||
|
||||
let line;
|
||||
if (startx === stopx) {
|
||||
const isAutoNumberOn = sequenceVisible || conf.showSequenceNumbers;
|
||||
const isReverse = isReverseArrowType(msg, diagObj);
|
||||
const isBidirectional = isBidirectionalArrowType(msg, diagObj);
|
||||
const lineStartX = startx + (isAutoNumberOn && (isReverse || isBidirectional) ? 10 : 0);
|
||||
|
||||
if (conf.rightAngles) {
|
||||
line = diagram
|
||||
.append('path')
|
||||
.attr(
|
||||
'd',
|
||||
`M ${lineStartX},${lineStartY} H ${
|
||||
`M ${startx},${lineStartY} H ${
|
||||
startx + common.getMax(conf.width / 2, textWidth / 2)
|
||||
} V ${lineStartY + 25} H ${startx}`
|
||||
);
|
||||
@@ -503,11 +453,11 @@ const drawMessage = async function (diagram, msgModel, lineStartY: number, diagO
|
||||
.attr(
|
||||
'd',
|
||||
'M ' +
|
||||
lineStartX +
|
||||
startx +
|
||||
',' +
|
||||
lineStartY +
|
||||
' C ' +
|
||||
(lineStartX + 60) +
|
||||
(startx + 60) +
|
||||
',' +
|
||||
(lineStartY - 10) +
|
||||
' ' +
|
||||
@@ -640,75 +590,38 @@ const drawMessage = async function (diagram, msgModel, lineStartY: number, diagO
|
||||
type === diagObj.db.LINETYPE.STICK_ARROW_BOTTOM_REVERSE ||
|
||||
type === diagObj.db.LINETYPE.STICK_ARROW_BOTTOM_REVERSE_DOTTED;
|
||||
|
||||
const SEQUENCE_NUMBER_RADIUS = 6;
|
||||
const hasCentralConn = hasCentralConnection(msg, diagObj);
|
||||
let lineStartX = startx;
|
||||
let lineStopX = stopx;
|
||||
let x = 0;
|
||||
if (isBidirectional || isReverseArrowType) {
|
||||
const SEQUENCE_NUMBER_RADIUS = 6;
|
||||
|
||||
if (isBidirectional) {
|
||||
// For bidirectional arrows, adjust the start position
|
||||
if (startx < stopx) {
|
||||
lineStartX = startx + SEQUENCE_NUMBER_RADIUS * 2;
|
||||
line.attr('x1', startx + 2 * SEQUENCE_NUMBER_RADIUS);
|
||||
} else {
|
||||
lineStartX = startx - SEQUENCE_NUMBER_RADIUS + (hasCentralConn ? -5 : 0);
|
||||
lineStartX +=
|
||||
msg?.centralConnection === diagObj.db.LINETYPE.CENTRAL_CONNECTION_DUAL ||
|
||||
msg?.centralConnection === diagObj.db.LINETYPE.CENTRAL_CONNECTION_REVERSE
|
||||
? -7.5
|
||||
: 0;
|
||||
line.attr('x1', startx + SEQUENCE_NUMBER_RADIUS);
|
||||
}
|
||||
line.attr('x1', lineStartX);
|
||||
} else if (isReverseArrowType) {
|
||||
// For reverse arrows, adjust the stop position (where the arrowhead is)
|
||||
if (stopx > startx) {
|
||||
lineStopX = stopx - 2 * SEQUENCE_NUMBER_RADIUS;
|
||||
} else {
|
||||
lineStopX = stopx - SEQUENCE_NUMBER_RADIUS;
|
||||
lineStartX +=
|
||||
msg?.centralConnection === diagObj.db.LINETYPE.CENTRAL_CONNECTION_DUAL ||
|
||||
msg?.centralConnection === diagObj.db.LINETYPE.CENTRAL_CONNECTION_REVERSE
|
||||
? -7.5
|
||||
: 0;
|
||||
}
|
||||
lineStopX += hasCentralConn ? 15 : 0;
|
||||
|
||||
line.attr('x2', lineStopX);
|
||||
line.attr('x1', lineStartX);
|
||||
} else {
|
||||
line.attr('x1', startx + SEQUENCE_NUMBER_RADIUS);
|
||||
}
|
||||
|
||||
// Calculate autonumber X position
|
||||
let autonumberX = 0;
|
||||
const isSelfMessage = startx === stopx;
|
||||
const isLeftToRight = startx <= stopx;
|
||||
|
||||
if (isSelfMessage) {
|
||||
autonumberX = msgModel.fromBounds + 1;
|
||||
} else if (isReverseArrowType) {
|
||||
autonumberX = isLeftToRight ? msgModel.toBounds - 1 : msgModel.fromBounds + 1;
|
||||
} else {
|
||||
autonumberX = isLeftToRight ? msgModel.fromBounds + 1 : msgModel.toBounds - 1;
|
||||
x = 3.5;
|
||||
}
|
||||
|
||||
diagram
|
||||
.append('line')
|
||||
.attr('x1', autonumberX)
|
||||
.attr('x1', startx)
|
||||
.attr('y1', lineStartY)
|
||||
.attr('x2', autonumberX)
|
||||
.attr('x2', startx)
|
||||
.attr('y2', lineStartY)
|
||||
.attr('stroke-width', 0)
|
||||
.attr('marker-start', 'url(' + url + '#sequencenumber)');
|
||||
.attr('marker-start', 'url(' + url + '#sequencenumber)')
|
||||
.attr('transform', `translate(-${x}, 0)`);
|
||||
|
||||
diagram
|
||||
.append('text')
|
||||
.attr('x', autonumberX)
|
||||
.attr('x', startx)
|
||||
.attr('y', lineStartY + 4)
|
||||
.attr('font-family', 'sans-serif')
|
||||
.attr('font-size', '12px')
|
||||
.attr('text-anchor', 'middle')
|
||||
.attr('class', 'sequenceNumber')
|
||||
.text(sequenceIndex);
|
||||
.text(sequenceIndex)
|
||||
.attr('transform', `translate(-${x}, 0)`);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1735,8 +1648,7 @@ const calculateCentralConnectionOffset = function (msg, diagObj, isArrowToRight)
|
||||
}
|
||||
|
||||
if (
|
||||
(msg.centralConnection === CENTRAL_CONNECTION_REVERSE ||
|
||||
msg.centralConnection === CENTRAL_CONNECTION_DUAL) &&
|
||||
msg.centralConnection === CENTRAL_CONNECTION_DUAL &&
|
||||
(msg.type === BIDIRECTIONAL_SOLID || msg.type === BIDIRECTIONAL_DOTTED)
|
||||
) {
|
||||
offset += isArrowToRight ? 0 : -CENTRAL_CONNECTION_BIDIRECTIONAL_OFFSET;
|
||||
@@ -1745,47 +1657,6 @@ const calculateCentralConnectionOffset = function (msg, diagObj, isArrowToRight)
|
||||
return offset;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if a message is a reverse arrow type
|
||||
* @param msg - The message object
|
||||
* @param diagObj - The diagram object containing LINETYPE constants
|
||||
* @returns True if the message is a reverse arrow type
|
||||
*/
|
||||
const isReverseArrowType = function (msg, diagObj) {
|
||||
const {
|
||||
SOLID_ARROW_TOP_REVERSE,
|
||||
SOLID_ARROW_TOP_REVERSE_DOTTED,
|
||||
SOLID_ARROW_BOTTOM_REVERSE,
|
||||
SOLID_ARROW_BOTTOM_REVERSE_DOTTED,
|
||||
STICK_ARROW_TOP_REVERSE,
|
||||
STICK_ARROW_TOP_REVERSE_DOTTED,
|
||||
STICK_ARROW_BOTTOM_REVERSE,
|
||||
STICK_ARROW_BOTTOM_REVERSE_DOTTED,
|
||||
} = diagObj.db.LINETYPE;
|
||||
|
||||
return [
|
||||
SOLID_ARROW_TOP_REVERSE,
|
||||
SOLID_ARROW_TOP_REVERSE_DOTTED,
|
||||
SOLID_ARROW_BOTTOM_REVERSE,
|
||||
SOLID_ARROW_BOTTOM_REVERSE_DOTTED,
|
||||
STICK_ARROW_TOP_REVERSE,
|
||||
STICK_ARROW_TOP_REVERSE_DOTTED,
|
||||
STICK_ARROW_BOTTOM_REVERSE,
|
||||
STICK_ARROW_BOTTOM_REVERSE_DOTTED,
|
||||
].includes(msg.type);
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if a message is a bidirectional arrow type
|
||||
* @param msg - The message object
|
||||
* @param diagObj - The diagram object containing LINETYPE constants
|
||||
* @returns True if the message is a bidirectional arrow type
|
||||
*/
|
||||
const isBidirectionalArrowType = function (msg, diagObj) {
|
||||
const { BIDIRECTIONAL_SOLID, BIDIRECTIONAL_DOTTED } = diagObj.db.LINETYPE;
|
||||
return [BIDIRECTIONAL_SOLID, BIDIRECTIONAL_DOTTED].includes(msg.type);
|
||||
};
|
||||
|
||||
const buildMessageModel = function (msg, actors, diagObj) {
|
||||
if (
|
||||
![
|
||||
|
||||
@@ -681,8 +681,8 @@ const drawActorTypeControl = function (elem, actor, conf, isFooter) {
|
||||
rect.class = 'actor';
|
||||
|
||||
const cx = actor.x + actor.width / 2;
|
||||
const cy = actorY + 32;
|
||||
const r = 22;
|
||||
const cy = actorY + 30;
|
||||
const r = 18;
|
||||
|
||||
actElem
|
||||
.append('defs')
|
||||
@@ -719,7 +719,7 @@ const drawActorTypeControl = function (elem, actor, conf, isFooter) {
|
||||
actor.description,
|
||||
actElem,
|
||||
rect.x,
|
||||
rect.y + r + (!isFooter ? 12 : 5),
|
||||
rect.y + r + (isFooter ? 5 : 10),
|
||||
rect.width,
|
||||
rect.height,
|
||||
{ class: `actor ${ACTOR_MAN_FIGURE_CLASS}` },
|
||||
@@ -737,7 +737,7 @@ const drawActorTypeEntity = function (elem, actor, conf, isFooter) {
|
||||
const line = elem.append('g').lower();
|
||||
|
||||
const actElem = elem.append('g');
|
||||
let cssClass = 'actor';
|
||||
let cssClass = ACTOR_MAN_FIGURE_CLASS;
|
||||
if (isFooter) {
|
||||
cssClass += ` ${BOTTOM_ACTOR_CLASS}`;
|
||||
} else {
|
||||
@@ -756,7 +756,7 @@ const drawActorTypeEntity = function (elem, actor, conf, isFooter) {
|
||||
|
||||
const cx = actor.x + actor.width / 2;
|
||||
const cy = actorY + (!isFooter ? 25 : 10);
|
||||
const r = 22;
|
||||
const r = 18;
|
||||
|
||||
actElem
|
||||
.append('circle')
|
||||
@@ -772,6 +772,7 @@ const drawActorTypeEntity = function (elem, actor, conf, isFooter) {
|
||||
.attr('x2', cx + r)
|
||||
.attr('y1', cy + r)
|
||||
.attr('y2', cy + r)
|
||||
.attr('stroke', '#333')
|
||||
.attr('stroke-width', 2);
|
||||
|
||||
const bounds = actElem.node().getBBox();
|
||||
@@ -798,7 +799,7 @@ const drawActorTypeEntity = function (elem, actor, conf, isFooter) {
|
||||
actor.description,
|
||||
actElem,
|
||||
rect.x,
|
||||
rect.y + (!isFooter ? 30 : 15),
|
||||
rect.y + (!isFooter ? (cy + r - actorY) / 2 : (cy - actorY + r - 5) / 2),
|
||||
rect.width,
|
||||
rect.height,
|
||||
{ class: `actor ${ACTOR_MAN_FIGURE_CLASS}` },
|
||||
@@ -806,9 +807,9 @@ const drawActorTypeEntity = function (elem, actor, conf, isFooter) {
|
||||
);
|
||||
|
||||
if (!isFooter) {
|
||||
actElem.attr('transform', `translate(${0}, ${r / 2 - 5})`);
|
||||
actElem.attr('transform', `translate(${0}, ${r / 2})`);
|
||||
} else {
|
||||
actElem.attr('transform', `translate(${0}, ${r})`);
|
||||
actElem.attr('transform', `translate(${0}, ${r / 2})`);
|
||||
}
|
||||
|
||||
return actor.height;
|
||||
@@ -871,8 +872,8 @@ const drawActorTypeDatabase = function (elem, actor, conf, isFooter) {
|
||||
// Cylinder dimensions
|
||||
rect.x = actor.x;
|
||||
rect.y = actorY;
|
||||
const w = rect.width / 3;
|
||||
const h = rect.width / 3;
|
||||
const w = rect.width / 4;
|
||||
const h = rect.width / 4;
|
||||
const rx = w / 2;
|
||||
const ry = rx / (2.5 + w / 50);
|
||||
|
||||
@@ -896,14 +897,17 @@ const drawActorTypeDatabase = function (elem, actor, conf, isFooter) {
|
||||
.attr('stroke-width', 1)
|
||||
.attr('class', cssclass);
|
||||
|
||||
cylinderGroup.attr('transform', `translate(${w}, ${ry})`);
|
||||
|
||||
if (!isFooter) {
|
||||
cylinderGroup.attr('transform', `translate(${w * 1.5}, ${(rect.height + ry) / 4})`);
|
||||
} else {
|
||||
cylinderGroup.attr('transform', `translate(${w * 1.5}, ${rect.height / 4 - 2 * ry})`);
|
||||
}
|
||||
actor.rectData = rect;
|
||||
_drawTextCandidateFunc(conf, hasKatex(actor.description))(
|
||||
actor.description,
|
||||
g,
|
||||
rect.x,
|
||||
rect.y + 35,
|
||||
rect.y + (!isFooter ? (rect.height + ry) / 2 : (rect.height + h) / 4),
|
||||
rect.width,
|
||||
rect.height,
|
||||
{ class: `actor ${ACTOR_BOX_CLASS}` },
|
||||
@@ -923,7 +927,7 @@ const drawActorTypeBoundary = function (elem, actor, conf, isFooter) {
|
||||
const actorY = isFooter ? actor.stopy : actor.starty;
|
||||
const center = actor.x + actor.width / 2;
|
||||
const centerY = actorY + 80;
|
||||
const radius = 22;
|
||||
const radius = 30;
|
||||
const line = elem.append('g').lower();
|
||||
|
||||
if (!isFooter) {
|
||||
@@ -964,22 +968,22 @@ const drawActorTypeBoundary = function (elem, actor, conf, isFooter) {
|
||||
.append('line')
|
||||
.attr('id', 'actor-man-torso' + actorCnt)
|
||||
.attr('x1', actor.x + actor.width / 2 - radius * 2.5)
|
||||
.attr('y1', actorY + 12)
|
||||
.attr('y1', actorY + 10)
|
||||
.attr('x2', actor.x + actor.width / 2 - 15)
|
||||
.attr('y2', actorY + 12);
|
||||
.attr('y2', actorY + 10);
|
||||
|
||||
actElem
|
||||
.append('line')
|
||||
.attr('id', 'actor-man-arms' + actorCnt)
|
||||
.attr('x1', actor.x + actor.width / 2 - radius * 2.5)
|
||||
.attr('y1', actorY + 2) // starting Y
|
||||
.attr('y1', actorY + 0) // starting Y
|
||||
.attr('x2', actor.x + actor.width / 2 - radius * 2.5)
|
||||
.attr('y2', actorY + 22); // ending Y (26px long, adjust as needed)
|
||||
.attr('y2', actorY + 20); // ending Y (26px long, adjust as needed)
|
||||
|
||||
actElem
|
||||
.append('circle')
|
||||
.attr('cx', actor.x + actor.width / 2)
|
||||
.attr('cy', actorY + 12)
|
||||
.attr('cy', actorY + 10)
|
||||
.attr('r', radius);
|
||||
|
||||
const bounds = actElem.node().getBBox();
|
||||
@@ -989,7 +993,7 @@ const drawActorTypeBoundary = function (elem, actor, conf, isFooter) {
|
||||
actor.description,
|
||||
actElem,
|
||||
rect.x,
|
||||
rect.y + 15,
|
||||
rect.y + (!isFooter ? radius / 2 + 3 : radius / 2 - 4),
|
||||
rect.width,
|
||||
rect.height,
|
||||
{ class: `actor ${ACTOR_MAN_FIGURE_CLASS}` },
|
||||
@@ -997,9 +1001,9 @@ const drawActorTypeBoundary = function (elem, actor, conf, isFooter) {
|
||||
);
|
||||
|
||||
if (!isFooter) {
|
||||
actElem.attr('transform', `translate(0,${radius / 2 + 10})`);
|
||||
actElem.attr('transform', `translate(0,${radius / 2 + 7})`);
|
||||
} else {
|
||||
actElem.attr('transform', `translate(0,${radius / 2 + 10})`);
|
||||
actElem.attr('transform', `translate(0,${radius / 2 + 7})`);
|
||||
}
|
||||
|
||||
return actor.height;
|
||||
|
||||
Reference in New Issue
Block a user