From 9776d856fa92c20e679609c9f17d293cf47fb7ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BAlio=20C=C3=A9sar=20Batista?= Date: Fri, 2 Dec 2022 21:49:51 -0800 Subject: [PATCH 1/5] Handle self edges --- d2layouts/d2sequence/layout_test.go | 36 ++++++++++++++++++++++++ d2layouts/d2sequence/sequence_diagram.go | 29 ++++++++++++++----- 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/d2layouts/d2sequence/layout_test.go b/d2layouts/d2sequence/layout_test.go index 83892aada..e2b9c5ecc 100644 --- a/d2layouts/d2sequence/layout_test.go +++ b/d2layouts/d2sequence/layout_test.go @@ -383,3 +383,39 @@ func TestNestedSequenceDiagrams(t *testing.T) { } } } + +func TestSelfEdges(t *testing.T) { + g := d2graph.NewGraph(nil) + g.Root.Attributes.Shape = d2graph.Scalar{Value: d2target.ShapeSequenceDiagram} + n1 := g.Root.EnsureChild([]string{"n1"}) + n1.Box = geo.NewBox(nil, 100, 100) + + g.Edges = []*d2graph.Edge{ + { + Src: n1, + Dst: n1, + Index: 0, + Attributes: d2graph.Attributes{ + Label: d2graph.Scalar{Value: "left to right"}, + }, + }, + } + + ctx := log.WithTB(context.Background(), t, nil) + Layout(ctx, g, func(ctx context.Context, g *d2graph.Graph) error { + return nil + }) + + route := g.Edges[0].Route + if len(route) != 4 { + t.Fatalf("expected route to have 4 points, got %d", len(route)) + } + + if route[0].X != route[3].X { + t.Fatalf("route does not end at the same actor, start at %.5f, end at %.5f", route[0].X, route[3].X) + } + + if route[3].Y-route[0].Y != MIN_MESSAGE_DISTANCE { + t.Fatalf("expected route height to be %.f5, got %.5f", MIN_MESSAGE_DISTANCE, route[3].Y-route[0].Y) + } +} diff --git a/d2layouts/d2sequence/sequence_diagram.go b/d2layouts/d2sequence/sequence_diagram.go index b08a89a6f..ca51a6243 100644 --- a/d2layouts/d2sequence/sequence_diagram.go +++ b/d2layouts/d2sequence/sequence_diagram.go @@ -142,7 +142,8 @@ func (sd *sequenceDiagram) placeActors() { // │ // │ func (sd *sequenceDiagram) addLifelineEdges() { - endY := sd.getMessageY(len(sd.messages)) + lastRoute := sd.messages[len(sd.messages)-1].Route + endY := lastRoute[len(lastRoute)-1].Y + MIN_MESSAGE_DISTANCE for _, actor := range sd.actors { actorBottom := actor.Center() actorBottom.Y = actor.TopLeft.Y + actor.Height @@ -241,6 +242,7 @@ func (sd *sequenceDiagram) routeMessages() { for rank, message := range sd.messages { message.ZIndex = 2 isLeftToRight := message.Src.TopLeft.X < message.Dst.TopLeft.X + isSelfMessage := message.Src == message.Dst // finds the proper anchor point based on the message direction var startX, endX float64 @@ -252,7 +254,9 @@ func (sd *sequenceDiagram) routeMessages() { startX = message.Src.TopLeft.X } - if sd.isActor(message.Dst) { + if isSelfMessage { + endX = startX + } else if sd.isActor(message.Dst) { endX = message.Dst.Center().X } else if isLeftToRight { endX = message.Dst.TopLeft.X @@ -260,14 +264,25 @@ func (sd *sequenceDiagram) routeMessages() { endX = message.Dst.TopLeft.X + message.Dst.Width } - messageY := sd.getMessageY(rank) - message.Route = []*geo.Point{ - geo.NewPoint(startX, messageY), - geo.NewPoint(endX, messageY), + startY := sd.getMessageY(rank) + if isSelfMessage { + message.Route = []*geo.Point{ + geo.NewPoint(startX, startY), + geo.NewPoint(startX+MIN_MESSAGE_DISTANCE, startY), + geo.NewPoint(startX+MIN_MESSAGE_DISTANCE, startY+MIN_MESSAGE_DISTANCE), + geo.NewPoint(startX, startY+MIN_MESSAGE_DISTANCE), + } + } else { + message.Route = []*geo.Point{ + geo.NewPoint(startX, startY), + geo.NewPoint(endX, startY), + } } if message.Attributes.Label.Value != "" { - if isLeftToRight { + if isSelfMessage { + message.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter)) + } else if isLeftToRight { message.LabelPosition = go2.Pointer(string(label.OutsideTopCenter)) } else { // the label will be placed above the message because the orientation is based on the edge normal vector From e53c97ebec04bcd07192543ffd8c2ad6e3153e1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BAlio=20C=C3=A9sar=20Batista?= Date: Sat, 3 Dec 2022 09:38:08 -0800 Subject: [PATCH 2/5] Handle edges to/from descendants --- d2layouts/d2sequence/layout.go | 11 +- d2layouts/d2sequence/layout_test.go | 56 ++ d2layouts/d2sequence/sequence_diagram.go | 161 +++-- e2etests/stable_test.go | 10 + .../dagre/board.exp.json | 40 +- .../dagre/sketch.exp.svg | 4 +- .../elk/board.exp.json | 40 +- .../elk/sketch.exp.svg | 4 +- .../dagre/board.exp.json | 12 +- .../dagre/sketch.exp.svg | 4 +- .../elk/board.exp.json | 12 +- .../elk/sketch.exp.svg | 4 +- .../dagre/board.exp.json | 658 ++++++++++++++++++ .../dagre/sketch.exp.svg | 43 ++ .../elk/board.exp.json | 658 ++++++++++++++++++ .../elk/sketch.exp.svg | 43 ++ .../dagre/board.exp.json | 10 +- .../dagre/sketch.exp.svg | 4 +- .../elk/board.exp.json | 10 +- .../elk/sketch.exp.svg | 4 +- .../dagre/board.exp.json | 12 +- .../dagre/sketch.exp.svg | 4 +- .../sequence_diagram_span/elk/board.exp.json | 12 +- .../sequence_diagram_span/elk/sketch.exp.svg | 4 +- .../sequence_diagrams/dagre/board.exp.json | 206 +++--- .../sequence_diagrams/dagre/sketch.exp.svg | 4 +- .../sequence_diagrams/elk/board.exp.json | 156 ++--- .../sequence_diagrams/elk/sketch.exp.svg | 4 +- 28 files changed, 1849 insertions(+), 341 deletions(-) create mode 100644 e2etests/testdata/stable/sequence_diagram_self_edges/dagre/board.exp.json create mode 100644 e2etests/testdata/stable/sequence_diagram_self_edges/dagre/sketch.exp.svg create mode 100644 e2etests/testdata/stable/sequence_diagram_self_edges/elk/board.exp.json create mode 100644 e2etests/testdata/stable/sequence_diagram_self_edges/elk/sketch.exp.svg diff --git a/d2layouts/d2sequence/layout.go b/d2layouts/d2sequence/layout.go index 5078c1634..1caabf230 100644 --- a/d2layouts/d2sequence/layout.go +++ b/d2layouts/d2sequence/layout.go @@ -37,7 +37,10 @@ func Layout(ctx context.Context, g *d2graph.Graph, layout func(ctx context.Conte continue } - sd := layoutSequenceDiagram(g, obj) + sd, err := layoutSequenceDiagram(g, obj) + if err != nil { + return err + } obj.Children = make(map[string]*d2graph.Object) obj.ChildrenArray = nil obj.Box = geo.NewBox(nil, sd.getWidth(), sd.getHeight()) @@ -73,7 +76,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, layout func(ctx context.Conte } // layoutSequenceDiagram finds the edges inside the sequence diagram and performs the layout on the object descendants -func layoutSequenceDiagram(g *d2graph.Graph, obj *d2graph.Object) *sequenceDiagram { +func layoutSequenceDiagram(g *d2graph.Graph, obj *d2graph.Object) (*sequenceDiagram, error) { var edges []*d2graph.Edge for _, edge := range g.Edges { // both Src and Dst must be inside the sequence diagram @@ -83,8 +86,8 @@ func layoutSequenceDiagram(g *d2graph.Graph, obj *d2graph.Object) *sequenceDiagr } sd := newSequenceDiagram(obj.ChildrenArray, edges) - sd.layout() - return sd + err := sd.layout() + return sd, err } func getLayoutEdges(g *d2graph.Graph, toRemove map[*d2graph.Edge]struct{}) ([]*d2graph.Edge, map[string]int) { diff --git a/d2layouts/d2sequence/layout_test.go b/d2layouts/d2sequence/layout_test.go index e2b9c5ecc..31f2365f7 100644 --- a/d2layouts/d2sequence/layout_test.go +++ b/d2layouts/d2sequence/layout_test.go @@ -180,14 +180,17 @@ func TestSpansSequenceDiagram(t *testing.T) { Shape: d2graph.Scalar{Value: shape.PERSON_TYPE}, } a_t1 := a.EnsureChild([]string{"t1"}) + a_t1.Box = geo.NewBox(nil, 100, 100) a_t1.Attributes = d2graph.Attributes{ Shape: d2graph.Scalar{Value: shape.DIAMOND_TYPE}, Label: d2graph.Scalar{Value: "label"}, } a_t2 := a.EnsureChild([]string{"t2"}) + a_t2.Box = geo.NewBox(nil, 100, 100) b := g.Root.EnsureChild([]string{"b"}) b.Box = geo.NewBox(nil, 30, 30) b_t1 := b.EnsureChild([]string{"t1"}) + b_t1.Box = geo.NewBox(nil, 100, 100) g.Edges = []*d2graph.Edge{ { @@ -303,9 +306,11 @@ func TestNestedSequenceDiagrams(t *testing.T) { a.Box = geo.NewBox(nil, 100, 100) a.Attributes.Shape = d2graph.Scalar{Value: shape.PERSON_TYPE} a_t1 := a.EnsureChild([]string{"t1"}) + a_t1.Box = geo.NewBox(nil, 100, 100) b := container.EnsureChild([]string{"b"}) b.Box = geo.NewBox(nil, 30, 30) b_t1 := b.EnsureChild([]string{"t1"}) + b_t1.Box = geo.NewBox(nil, 100, 100) c := g.Root.EnsureChild([]string{"c"}) c.Box = geo.NewBox(nil, 100, 100) @@ -419,3 +424,54 @@ func TestSelfEdges(t *testing.T) { t.Fatalf("expected route height to be %.f5, got %.5f", MIN_MESSAGE_DISTANCE, route[3].Y-route[0].Y) } } + +func TestSequenceToDescendant(t *testing.T) { + g := d2graph.NewGraph(nil) + g.Root.Attributes.Shape = d2graph.Scalar{Value: d2target.ShapeSequenceDiagram} + a := g.Root.EnsureChild([]string{"a"}) + a.Box = geo.NewBox(nil, 100, 100) + a.Attributes = d2graph.Attributes{ + Shape: d2graph.Scalar{Value: shape.PERSON_TYPE}, + } + a_t1 := a.EnsureChild([]string{"t1"}) + a_t1.Box = geo.NewBox(nil, 16, 80) + + g.Edges = []*d2graph.Edge{ + { + Src: a, + Dst: a_t1, + Index: 0, + }, { + Src: a_t1, + Dst: a, + Index: 0, + }, + } + + ctx := log.WithTB(context.Background(), t, nil) + Layout(ctx, g, func(ctx context.Context, g *d2graph.Graph) error { + return nil + }) + + route1 := g.Edges[0].Route + if len(route1) != 4 { + t.Fatal("expected route with 4 points") + } + if route1[0].X != a.Center().X { + t.Fatal("expected route to start at `a` lifeline") + } + if route1[3].X != a_t1.TopLeft.X+a_t1.Width { + t.Fatal("expected route to end at `a.t1` right side") + } + + route2 := g.Edges[1].Route + if len(route2) != 4 { + t.Fatal("expected route with 4 points") + } + if route2[0].X != a_t1.TopLeft.X+a_t1.Width { + t.Fatal("expected route to start at `a.t1` right side") + } + if route2[3].X != a.Center().X { + t.Fatal("expected route to end at `a` lifeline") + } +} diff --git a/d2layouts/d2sequence/sequence_diagram.go b/d2layouts/d2sequence/sequence_diagram.go index ca51a6243..ba40d6bfa 100644 --- a/d2layouts/d2sequence/sequence_diagram.go +++ b/d2layouts/d2sequence/sequence_diagram.go @@ -4,6 +4,7 @@ import ( "fmt" "math" "sort" + "strings" "oss.terrastruct.com/util-go/go2" @@ -26,9 +27,8 @@ type sequenceDiagram struct { objectRank map[*d2graph.Object]int // keep track of the first and last message of a given actor/span - // the message rank is the order in which it appears from top to bottom - minMessageRank map[*d2graph.Object]int - maxMessageRank map[*d2graph.Object]int + firstMessage map[*d2graph.Object]*d2graph.Edge + lastMessage map[*d2graph.Object]*d2graph.Edge messageYStep float64 actorXStep float64 @@ -42,8 +42,8 @@ func newSequenceDiagram(actors []*d2graph.Object, messages []*d2graph.Edge) *seq spans: nil, lifelines: nil, objectRank: make(map[*d2graph.Object]int), - minMessageRank: make(map[*d2graph.Object]int), - maxMessageRank: make(map[*d2graph.Object]int), + firstMessage: make(map[*d2graph.Object]*d2graph.Edge), + lastMessage: make(map[*d2graph.Object]*d2graph.Edge), messageYStep: MIN_MESSAGE_DISTANCE, actorXStep: MIN_ACTOR_DISTANCE, maxActorHeight: 0., @@ -76,17 +76,27 @@ func newSequenceDiagram(actors []*d2graph.Object, messages []*d2graph.Edge) *seq } } - for rank, message := range sd.messages { + for _, message := range sd.messages { sd.messageYStep = math.Max(sd.messageYStep, float64(message.LabelDimensions.Height)) - sd.setMinMaxMessageRank(message.Src, rank) - sd.setMinMaxMessageRank(message.Dst, rank) - // ensures that long labels, spanning over multiple actors, don't make for large gaps between actors // by distributing the label length across the actors rank difference rankDiff := math.Abs(float64(sd.objectRank[message.Src]) - float64(sd.objectRank[message.Dst])) - distributedLabelWidth := float64(message.LabelDimensions.Width) / rankDiff - sd.actorXStep = math.Max(sd.actorXStep, distributedLabelWidth+HORIZONTAL_PAD) + if rankDiff != 0 { + // rankDiff = 0 for self edges + distributedLabelWidth := float64(message.LabelDimensions.Width) / rankDiff + sd.actorXStep = math.Max(sd.actorXStep, distributedLabelWidth+HORIZONTAL_PAD) + + } + sd.lastMessage[message.Src] = message + if _, exists := sd.firstMessage[message.Src]; !exists { + sd.firstMessage[message.Src] = message + } + sd.lastMessage[message.Dst] = message + if _, exists := sd.firstMessage[message.Dst]; !exists { + sd.firstMessage[message.Dst] = message + } + } sd.messageYStep += VERTICAL_PAD @@ -98,21 +108,15 @@ func newSequenceDiagram(actors []*d2graph.Object, messages []*d2graph.Edge) *seq return sd } -func (sd *sequenceDiagram) setMinMaxMessageRank(actor *d2graph.Object, rank int) { - if minRank, exists := sd.minMessageRank[actor]; exists { - sd.minMessageRank[actor] = go2.IntMin(minRank, rank) - } else { - sd.minMessageRank[actor] = rank - } - - sd.maxMessageRank[actor] = go2.IntMax(sd.maxMessageRank[actor], rank) -} - -func (sd *sequenceDiagram) layout() { +func (sd *sequenceDiagram) layout() error { sd.placeActors() + if err := sd.routeMessages(); err != nil { + return err + } sd.placeSpans() - sd.routeMessages() + sd.adjustRouteEndpoints() sd.addLifelineEdges() + return nil } // placeActors places actors bottom aligned, side by side @@ -210,12 +214,21 @@ func (sd *sequenceDiagram) placeSpans() { // finds the position if there are messages to this span minMessageY := math.Inf(1) - if minRank, exists := sd.minMessageRank[span]; exists { - minMessageY = sd.getMessageY(minRank) + if firstMessage, exists := sd.firstMessage[span]; exists { + // needs to check Src/Dst because of self-edges or edges to/from descendants + if span == firstMessage.Src { + minMessageY = firstMessage.Route[0].Y + } else { + minMessageY = firstMessage.Route[len(firstMessage.Route)-1].Y + } } maxMessageY := math.Inf(-1) - if maxRank, exists := sd.maxMessageRank[span]; exists { - maxMessageY = sd.getMessageY(maxRank) + if lastMessage, exists := sd.lastMessage[span]; exists { + if span == lastMessage.Src { + maxMessageY = lastMessage.Route[0].Y + } else { + maxMessageY = lastMessage.Route[len(lastMessage.Route)-1].Y + } } // if it is the same as the child top left, add some padding @@ -237,40 +250,36 @@ func (sd *sequenceDiagram) placeSpans() { } } -// routeMessages routes horizontal edges (messages) from Src to Dst -func (sd *sequenceDiagram) routeMessages() { - for rank, message := range sd.messages { +// routeMessages routes horizontal edges (messages) from Src to Dst lifeline (actor/span center) +// in another step, routes are adjusted to spans borders when necessary +func (sd *sequenceDiagram) routeMessages() error { + startY := sd.maxActorHeight + sd.messageYStep + for _, message := range sd.messages { message.ZIndex = 2 - isLeftToRight := message.Src.TopLeft.X < message.Dst.TopLeft.X + var startX, endX float64 + if startCenter := getCenter(message.Src); startCenter != nil { + startX = startCenter.X + } else { + return fmt.Errorf("could not find center of %s", message.Src.AbsID()) + } + if endCenter := getCenter(message.Dst); endCenter != nil { + endX = endCenter.X + } else { + return fmt.Errorf("could not find center of %s", message.Dst.AbsID()) + } + isLeftToRight := startX < endX + isToDescendant := strings.HasPrefix(message.Dst.AbsID(), message.Src.AbsID()) + isFromDescendant := strings.HasPrefix(message.Src.AbsID(), message.Dst.AbsID()) isSelfMessage := message.Src == message.Dst - // finds the proper anchor point based on the message direction - var startX, endX float64 - if sd.isActor(message.Src) { - startX = message.Src.Center().X - } else if isLeftToRight { - startX = message.Src.TopLeft.X + message.Src.Width - } else { - startX = message.Src.TopLeft.X - } - - if isSelfMessage { - endX = startX - } else if sd.isActor(message.Dst) { - endX = message.Dst.Center().X - } else if isLeftToRight { - endX = message.Dst.TopLeft.X - } else { - endX = message.Dst.TopLeft.X + message.Dst.Width - } - - startY := sd.getMessageY(rank) - if isSelfMessage { + if isSelfMessage || isToDescendant || isFromDescendant { + midX := startX + MIN_MESSAGE_DISTANCE + endY := startY + MIN_MESSAGE_DISTANCE message.Route = []*geo.Point{ geo.NewPoint(startX, startY), - geo.NewPoint(startX+MIN_MESSAGE_DISTANCE, startY), - geo.NewPoint(startX+MIN_MESSAGE_DISTANCE, startY+MIN_MESSAGE_DISTANCE), - geo.NewPoint(startX, startY+MIN_MESSAGE_DISTANCE), + geo.NewPoint(midX, startY), + geo.NewPoint(midX, endY), + geo.NewPoint(endX, endY), } } else { message.Route = []*geo.Point{ @@ -278,9 +287,10 @@ func (sd *sequenceDiagram) routeMessages() { geo.NewPoint(endX, startY), } } + startY += sd.messageYStep if message.Attributes.Label.Value != "" { - if isSelfMessage { + if isSelfMessage || isFromDescendant || isToDescendant { message.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter)) } else if isLeftToRight { message.LabelPosition = go2.Pointer(string(label.OutsideTopCenter)) @@ -290,11 +300,39 @@ func (sd *sequenceDiagram) routeMessages() { } } } + return nil } -func (sd *sequenceDiagram) getMessageY(rank int) float64 { - // +1 so that the first message has the top padding for its label - return ((float64(rank) + 1.) * sd.messageYStep) + sd.maxActorHeight +func getCenter(obj *d2graph.Object) *geo.Point { + if obj == nil { + return nil + } else if obj.TopLeft != nil { + return obj.Center() + } + return getCenter(obj.Parent) +} + +// adjustRouteEndpoints adjust the first and last points of message routes when they are spans +// routeMessages() will route to the actor lifelife as a reference point and this function +// adjust to span width when necessary +func (sd *sequenceDiagram) adjustRouteEndpoints() { + for _, message := range sd.messages { + route := message.Route + if !sd.isActor(message.Src) { + if sd.objectRank[message.Src] <= sd.objectRank[message.Dst] { + route[0].X += message.Src.Width / 2. + } else { + route[0].X -= message.Src.Width / 2. + } + } + if !sd.isActor(message.Dst) { + if sd.objectRank[message.Src] < sd.objectRank[message.Dst] { + route[len(route)-1].X -= message.Dst.Width / 2. + } else { + route[len(route)-1].X += message.Dst.Width / 2. + } + } + } } func (sd *sequenceDiagram) isActor(obj *d2graph.Object) bool { @@ -308,8 +346,7 @@ func (sd *sequenceDiagram) getWidth() float64 { } func (sd *sequenceDiagram) getHeight() float64 { - // the layout is always placed starting at 0, so the height is just the last message - return sd.getMessageY(len(sd.messages)) + return sd.lifelines[0].Route[1].Y } func (sd *sequenceDiagram) shift(tl *geo.Point) { diff --git a/e2etests/stable_test.go b/e2etests/stable_test.go index 2b3451fb9..20ca74e95 100644 --- a/e2etests/stable_test.go +++ b/e2etests/stable_test.go @@ -1325,6 +1325,16 @@ s -> t`, z -> y z -> z: hello `, + }, { + name: "sequence_diagram_self_edges", + script: `shape: sequence_diagram +a -> a: a self edge here +a -> b: between actors +b -> b.1: to descendant +b.1 -> b.1.2: to deeper descendant +b.1.2 -> b: to parent +b -> a.1.2: actor +a.1 -> b.3`, }, } diff --git a/e2etests/testdata/stable/sequence_diagram_all_shapes/dagre/board.exp.json b/e2etests/testdata/stable/sequence_diagram_all_shapes/dagre/board.exp.json index f89bceb6a..abe4ac5c5 100644 --- a/e2etests/testdata/stable/sequence_diagram_all_shapes/dagre/board.exp.json +++ b/e2etests/testdata/stable/sequence_diagram_all_shapes/dagre/board.exp.json @@ -1590,7 +1590,7 @@ }, { "x": 76.5, - "y": 2834 + "y": 2784 } ], "animated": false, @@ -1629,7 +1629,7 @@ }, { "x": 485, - "y": 2834 + "y": 2784 } ], "animated": false, @@ -1668,7 +1668,7 @@ }, { "x": 937.5, - "y": 2834 + "y": 2784 } ], "animated": false, @@ -1707,7 +1707,7 @@ }, { "x": 1404.5, - "y": 2834 + "y": 2784 } ], "animated": false, @@ -1746,7 +1746,7 @@ }, { "x": 1849, - "y": 2834 + "y": 2784 } ], "animated": false, @@ -1785,7 +1785,7 @@ }, { "x": 2279, - "y": 2834 + "y": 2784 } ], "animated": false, @@ -1824,7 +1824,7 @@ }, { "x": 2686, - "y": 2834 + "y": 2784 } ], "animated": false, @@ -1863,7 +1863,7 @@ }, { "x": 3093, - "y": 2834 + "y": 2784 } ], "animated": false, @@ -1902,7 +1902,7 @@ }, { "x": 3516, - "y": 2834 + "y": 2784 } ], "animated": false, @@ -1941,7 +1941,7 @@ }, { "x": 3939, - "y": 2834 + "y": 2784 } ], "animated": false, @@ -1980,7 +1980,7 @@ }, { "x": 4346, - "y": 2834 + "y": 2784 } ], "animated": false, @@ -2019,7 +2019,7 @@ }, { "x": 4753, - "y": 2834 + "y": 2784 } ], "animated": false, @@ -2058,7 +2058,7 @@ }, { "x": 5172.5, - "y": 2834 + "y": 2784 } ], "animated": false, @@ -2097,7 +2097,7 @@ }, { "x": 5608.5, - "y": 2834 + "y": 2784 } ], "animated": false, @@ -2136,7 +2136,7 @@ }, { "x": 6034, - "y": 2834 + "y": 2784 } ], "animated": false, @@ -2175,7 +2175,7 @@ }, { "x": 6448.5, - "y": 2834 + "y": 2784 } ], "animated": false, @@ -2214,7 +2214,7 @@ }, { "x": 6868.5, - "y": 2834 + "y": 2784 } ], "animated": false, @@ -2253,7 +2253,7 @@ }, { "x": 7314.5, - "y": 2834 + "y": 2784 } ], "animated": false, @@ -2292,7 +2292,7 @@ }, { "x": 7753, - "y": 2834 + "y": 2784 } ], "animated": false, @@ -2331,7 +2331,7 @@ }, { "x": 8190, - "y": 2834 + "y": 2784 } ], "animated": false, diff --git a/e2etests/testdata/stable/sequence_diagram_all_shapes/dagre/sketch.exp.svg b/e2etests/testdata/stable/sequence_diagram_all_shapes/dagre/sketch.exp.svg index 75d906f0b..527393611 100644 --- a/e2etests/testdata/stable/sequence_diagram_all_shapes/dagre/sketch.exp.svg +++ b/e2etests/testdata/stable/sequence_diagram_all_shapes/dagre/sketch.exp.svg @@ -2,7 +2,7 @@ \ No newline at end of file diff --git a/e2etests/testdata/stable/sequence_diagram_self_edges/elk/board.exp.json b/e2etests/testdata/stable/sequence_diagram_self_edges/elk/board.exp.json new file mode 100644 index 000000000..d600d6f76 --- /dev/null +++ b/e2etests/testdata/stable/sequence_diagram_self_edges/elk/board.exp.json @@ -0,0 +1,658 @@ +{ + "name": "", + "shapes": [ + { + "id": "a", + "type": "", + "pos": { + "x": 0, + "y": 50 + }, + "width": 150, + "height": 169, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#E3E9FD", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 12, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "b", + "type": "", + "pos": { + "x": 400, + "y": 52 + }, + "width": 150, + "height": 167, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#E3E9FD", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 13, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "b.1", + "type": "rectangle", + "pos": { + "x": 469, + "y": 673 + }, + "width": 12, + "height": 228, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#EDF0FD", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 24, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 15, + "labelHeight": 36, + "zIndex": 1, + "level": 2 + }, + { + "id": "b.1.2", + "type": "rectangle", + "pos": { + "x": 465, + "y": 803 + }, + "width": 20, + "height": 82, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 13, + "labelHeight": 26, + "zIndex": 1, + "level": 3 + }, + { + "id": "a.1", + "type": "rectangle", + "pos": { + "x": 69, + "y": 967 + }, + "width": 12, + "height": 178, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#EDF0FD", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 24, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 15, + "labelHeight": 36, + "zIndex": 1, + "level": 2 + }, + { + "id": "a.1.2", + "type": "rectangle", + "pos": { + "x": 65, + "y": 983 + }, + "width": 20, + "height": 80, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 13, + "labelHeight": 26, + "zIndex": 1, + "level": 3 + }, + { + "id": "b.3", + "type": "rectangle", + "pos": { + "x": 469, + "y": 1113 + }, + "width": 12, + "height": 80, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#EDF0FD", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 13, + "labelHeight": 26, + "zIndex": 1, + "level": 2 + } + ], + "connections": [ + { + "id": "(a -> a)[0]", + "src": "a", + "srcArrow": "none", + "srcLabel": "", + "dst": "a", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "a self edge here", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 103, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "labelPercentage": 0, + "route": [ + { + "x": 75, + "y": 349 + }, + { + "x": 155, + "y": 349 + }, + { + "x": 155, + "y": 429 + }, + { + "x": 75, + "y": 429 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 2 + }, + { + "id": "(a -> b)[0]", + "src": "a", + "srcArrow": "none", + "srcLabel": "", + "dst": "b", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "between actors", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 102, + "labelHeight": 21, + "labelPosition": "OUTSIDE_TOP_CENTER", + "labelPercentage": 0, + "route": [ + { + "x": 75, + "y": 479 + }, + { + "x": 475, + "y": 479 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 2 + }, + { + "id": "(b -> b.1)[0]", + "src": "b", + "srcArrow": "none", + "srcLabel": "", + "dst": "b.1", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "to descendant", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 94, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "labelPercentage": 0, + "route": [ + { + "x": 475, + "y": 609 + }, + { + "x": 555, + "y": 609 + }, + { + "x": 555, + "y": 689 + }, + { + "x": 481, + "y": 689 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 2 + }, + { + "id": "b.(1 -> 1.2)[0]", + "src": "b.1", + "srcArrow": "none", + "srcLabel": "", + "dst": "b.1.2", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "to deeper descendant", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 143, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "labelPercentage": 0, + "route": [ + { + "x": 481, + "y": 739 + }, + { + "x": 555, + "y": 739 + }, + { + "x": 555, + "y": 819 + }, + { + "x": 485, + "y": 819 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 2 + }, + { + "id": "(b.1.2 -> b)[0]", + "src": "b.1.2", + "srcArrow": "none", + "srcLabel": "", + "dst": "b", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "to parent", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 62, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "labelPercentage": 0, + "route": [ + { + "x": 485, + "y": 869 + }, + { + "x": 555, + "y": 869 + }, + { + "x": 555, + "y": 949 + }, + { + "x": 475, + "y": 949 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 2 + }, + { + "id": "(b -> a.1.2)[0]", + "src": "b", + "srcArrow": "none", + "srcLabel": "", + "dst": "a.1.2", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "actor", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 36, + "labelHeight": 21, + "labelPosition": "OUTSIDE_BOTTOM_CENTER", + "labelPercentage": 0, + "route": [ + { + "x": 475, + "y": 999 + }, + { + "x": 85, + "y": 999 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 2 + }, + { + "id": "(a.1 -> b.3)[0]", + "src": "a.1", + "srcArrow": "none", + "srcLabel": "", + "dst": "b.3", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 81, + "y": 1129 + }, + { + "x": 469, + "y": 1129 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 2 + }, + { + "id": "(a -- )[0]", + "src": "a", + "srcArrow": "none", + "srcLabel": "", + "dst": "a-lifeline-end-2251863791", + "dstArrow": "none", + "dstLabel": "", + "opacity": 1, + "strokeDash": 8, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 75, + "y": 219 + }, + { + "x": 75, + "y": 1209 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(b -- )[0]", + "src": "b", + "srcArrow": "none", + "srcLabel": "", + "dst": "b-lifeline-end-668380428", + "dstArrow": "none", + "dstLabel": "", + "opacity": 1, + "strokeDash": 8, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 475, + "y": 219 + }, + { + "x": 475, + "y": 1209 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + } + ] +} diff --git a/e2etests/testdata/stable/sequence_diagram_self_edges/elk/sketch.exp.svg b/e2etests/testdata/stable/sequence_diagram_self_edges/elk/sketch.exp.svg new file mode 100644 index 000000000..8f85d0bfe --- /dev/null +++ b/e2etests/testdata/stable/sequence_diagram_self_edges/elk/sketch.exp.svg @@ -0,0 +1,43 @@ + +ab + + +a self edge herebetween actors + + +to descendant + + +to deeper descendant + + +to parentactor \ No newline at end of file diff --git a/e2etests/testdata/stable/sequence_diagram_simple/dagre/board.exp.json b/e2etests/testdata/stable/sequence_diagram_simple/dagre/board.exp.json index 853836cc5..e70040d54 100644 --- a/e2etests/testdata/stable/sequence_diagram_simple/dagre/board.exp.json +++ b/e2etests/testdata/stable/sequence_diagram_simple/dagre/board.exp.json @@ -619,7 +619,7 @@ }, { "x": 81.5, - "y": 1718 + "y": 1668 } ], "animated": false, @@ -658,7 +658,7 @@ }, { "x": 555, - "y": 1718 + "y": 1668 } ], "animated": false, @@ -697,7 +697,7 @@ }, { "x": 1022, - "y": 1718 + "y": 1668 } ], "animated": false, @@ -736,7 +736,7 @@ }, { "x": 1489, - "y": 1718 + "y": 1668 } ], "animated": false, @@ -775,7 +775,7 @@ }, { "x": 1982, - "y": 1718 + "y": 1668 } ], "animated": false, diff --git a/e2etests/testdata/stable/sequence_diagram_simple/dagre/sketch.exp.svg b/e2etests/testdata/stable/sequence_diagram_simple/dagre/sketch.exp.svg index ff091510a..ec6450ceb 100644 --- a/e2etests/testdata/stable/sequence_diagram_simple/dagre/sketch.exp.svg +++ b/e2etests/testdata/stable/sequence_diagram_simple/dagre/sketch.exp.svg @@ -2,7 +2,7 @@ abcdggggroup 1group bchoonested guywhat would arnold saythis note lalaeyokayokay - + abcdggggroup 1group bchoonested guywhat would arnold saythis note lalaeyokayokay +abcdggggroup 1group bchoonested guywhat would arnold saythis note lalaeyokayokay - + abcdexplanationanother explanationSome one who believes imaginary things appear right before your i's.The earth is like a tiny grain of sand, only much, much heavier okay - - +abcdexplanationanother explanationSome one who believes imaginary things appear right before your i's.The earth is like a tiny grain of sand, only much, much heavier okay + + abcdexplanationanother explanationSome one who believes imaginary things appear right before your i's.The earth is like a tiny grain of sand, only much, much heavier okay - - +abcdexplanationanother explanationSome one who believes imaginary things appear right before your i's.The earth is like a tiny grain of sand, only much, much heavier okay + + How this is renderedCLId2astd2compilerd2layoutd2exporterd2themesd2rendererd2sequencelayoutd2dagrelayoutmeasurements also take place 'How this is rendered: {...}'tokenized ASTcompile ASTobjects and edgesrun layout enginesrun engine on shape: sequence_diagram, temporarily removerun core engine on rest add back in sequence diagramsdiagram with correct positions and dimensionsexport diagram with chosen theme and rendererget theme stylesrender to SVGresulting SVG - +How this is renderedCLId2astd2compilerd2layoutd2exporterd2themesd2rendererd2sequencelayoutd2dagrelayoutmeasurements also take place 'How this is rendered: {...}'tokenized ASTcompile ASTobjects and edgesrun layout enginesrun engine on shape: sequence_diagram, temporarily removerun core engine on rest add back in sequence diagramsdiagram with correct positions and dimensionsexport diagram with chosen theme and rendererget theme stylesrender to SVGresulting SVG + - - - - - - - - - - + + + + + + + + + + How this is renderedCLId2astd2compilerd2layoutd2exporterd2themesd2rendererd2sequencelayoutd2dagrelayoutmeasurements also take place 'How this is rendered: {...}'tokenized ASTcompile ASTobjects and edgesrun layout enginesrun engine on shape: sequence_diagram, temporarily removerun core engine on rest add back in sequence diagramsdiagram with correct positions and dimensionsexport diagram with chosen theme and rendererget theme stylesrender to SVGresulting SVG - +How this is renderedCLId2astd2compilerd2layoutd2exporterd2themesd2rendererd2sequencelayoutd2dagrelayoutmeasurements also take place 'How this is rendered: {...}'tokenized ASTcompile ASTobjects and edgesrun layout enginesrun engine on shape: sequence_diagram, temporarily removerun core engine on rest add back in sequence diagramsdiagram with correct positions and dimensionsexport diagram with chosen theme and rendererget theme stylesrender to SVGresulting SVG + - - - - - - - - - - + + + + + + + + + + abcdggggroup 1group bchoonested guywhat would arnold saythis note lalaeyokayokay +abcdggggroup 1group bchoonested guywhat would arnold saythis note lalaeyokayokay diff --git a/e2etests/testdata/stable/sequence_diagram_groups/elk/board.exp.json b/e2etests/testdata/stable/sequence_diagram_groups/elk/board.exp.json index 340ba41fc..4c97039b0 100644 --- a/e2etests/testdata/stable/sequence_diagram_groups/elk/board.exp.json +++ b/e2etests/testdata/stable/sequence_diagram_groups/elk/board.exp.json @@ -762,11 +762,11 @@ "labelPercentage": 0, "route": [ { - "x": 475, + "x": 481, "y": 999 }, { - "x": 875, + "x": 869, "y": 999 } ], @@ -801,11 +801,11 @@ "labelPercentage": 0, "route": [ { - "x": 475, + "x": 485, "y": 1129 }, { - "x": 875, + "x": 869, "y": 1129 } ], @@ -840,11 +840,11 @@ "labelPercentage": 0, "route": [ { - "x": 875, + "x": 869, "y": 1259 }, { - "x": 475, + "x": 481, "y": 1259 } ], diff --git a/e2etests/testdata/stable/sequence_diagram_groups/elk/sketch.exp.svg b/e2etests/testdata/stable/sequence_diagram_groups/elk/sketch.exp.svg index a87b67540..71742568e 100644 --- a/e2etests/testdata/stable/sequence_diagram_groups/elk/sketch.exp.svg +++ b/e2etests/testdata/stable/sequence_diagram_groups/elk/sketch.exp.svg @@ -14,7 +14,7 @@ width="1609" height="2311" viewBox="-100 -50 1609 2311">abcdggggroup 1group bchoonested guywhat would arnold saythis note lalaeyokayokay +abcdggggroup 1group bchoonested guywhat would arnold saythis note lalaeyokayokay diff --git a/e2etests/testdata/stable/sequence_diagram_nested_span/dagre/board.exp.json b/e2etests/testdata/stable/sequence_diagram_nested_span/dagre/board.exp.json index 23986a0ad..a99b8fa61 100644 --- a/e2etests/testdata/stable/sequence_diagram_nested_span/dagre/board.exp.json +++ b/e2etests/testdata/stable/sequence_diagram_nested_span/dagre/board.exp.json @@ -913,7 +913,7 @@ "y": 320 }, { - "x": 500, + "x": 494, "y": 320 } ], @@ -948,11 +948,11 @@ "labelPercentage": 0, "route": [ { - "x": 500, + "x": 506, "y": 450 }, { - "x": 925, + "x": 915, "y": 450 } ], @@ -987,11 +987,11 @@ "labelPercentage": 0, "route": [ { - "x": 925, + "x": 935, "y": 580 }, { - "x": 1343, + "x": 1329, "y": 580 } ], @@ -1026,11 +1026,11 @@ "labelPercentage": 0, "route": [ { - "x": 1343, + "x": 1357, "y": 710 }, { - "x": 1766, + "x": 1748, "y": 710 } ], @@ -1065,11 +1065,11 @@ "labelPercentage": 0, "route": [ { - "x": 925, + "x": 931, "y": 840 }, { - "x": 1343, + "x": 1333, "y": 840 } ], @@ -1104,11 +1104,11 @@ "labelPercentage": 0, "route": [ { - "x": 1766, + "x": 1784, "y": 970 }, { - "x": 2194.5, + "x": 2172.5, "y": 970 } ], @@ -1143,11 +1143,11 @@ "labelPercentage": 0, "route": [ { - "x": 75, + "x": 81, "y": 1100 }, { - "x": 925, + "x": 919, "y": 1100 } ], @@ -1182,7 +1182,7 @@ "labelPercentage": 0, "route": [ { - "x": 2194.5, + "x": 2172.5, "y": 1230 }, { @@ -1225,7 +1225,7 @@ "y": 1360 }, { - "x": 500, + "x": 494, "y": 1360 } ], diff --git a/e2etests/testdata/stable/sequence_diagram_nested_span/dagre/sketch.exp.svg b/e2etests/testdata/stable/sequence_diagram_nested_span/dagre/sketch.exp.svg index 674dc436e..26d4f47aa 100644 --- a/e2etests/testdata/stable/sequence_diagram_nested_span/dagre/sketch.exp.svg +++ b/e2etests/testdata/stable/sequence_diagram_nested_span/dagre/sketch.exp.svg @@ -14,7 +14,7 @@ width="2493" height="1640" viewBox="-100 -50 2493 1640">scoreritemResponseitemessayRubricconceptitemOutcome scoreritemResponseitemessayRubricconceptitemOutcome How this is renderedCLId2astd2compilerd2layoutd2exporterd2themesd2rendererd2sequencelayoutd2dagrelayoutmeasurements also take place 'How this is rendered: {...}'tokenized ASTcompile ASTobjects and edgesrun layout enginesrun engine on shape: sequence_diagram, temporarily removerun core engine on rest add back in sequence diagramsdiagram with correct positions and dimensionsexport diagram with chosen theme and rendererget theme stylesrender to SVGresulting SVG +How this is renderedCLId2astd2compilerd2layoutd2exporterd2themesd2rendererd2sequencelayoutd2dagrelayoutmeasurements also take place 'How this is rendered: {...}'tokenized ASTcompile ASTobjects and edgesrun layout enginesrun engine on shape: sequence_diagram, temporarily removerun core engine on rest add back in sequence diagramsdiagram with correct positions and dimensionsexport diagram with chosen theme and rendererget theme stylesrender to SVGresulting SVG - - - - + + + + - - - + + + How this is renderedCLId2astd2compilerd2layoutd2exporterd2themesd2rendererd2sequencelayoutd2dagrelayoutmeasurements also take place 'How this is rendered: {...}'tokenized ASTcompile ASTobjects and edgesrun layout enginesrun engine on shape: sequence_diagram, temporarily removerun core engine on rest add back in sequence diagramsdiagram with correct positions and dimensionsexport diagram with chosen theme and rendererget theme stylesrender to SVGresulting SVG +How this is renderedCLId2astd2compilerd2layoutd2exporterd2themesd2rendererd2sequencelayoutd2dagrelayoutmeasurements also take place 'How this is rendered: {...}'tokenized ASTcompile ASTobjects and edgesrun layout enginesrun engine on shape: sequence_diagram, temporarily removerun core engine on rest add back in sequence diagramsdiagram with correct positions and dimensionsexport diagram with chosen theme and rendererget theme stylesrender to SVGresulting SVG - - - - + + + + - - - + + + ab a self edge herebetween actorsto descendantto deeper descendantto parentactor +ab a self edge herebetween actorsto descendantto deeper descendantto parentactor - - - - + + + + ab a self edge herebetween actorsto descendantto deeper descendantto parentactor +ab a self edge herebetween actorsto descendantto deeper descendantto parentactor - - - - + + + + scoreritemResponseitemessayRubricconceptitemOutcome getItem() itemgetRubric()rubricapplyTo(essayResp)match(essayResponse)scorenewgetNormalMinimum()getNormalMaximum()setScore(score)setFeedback(missingConcepts) +scoreritemResponseitemessayRubricconceptitemOutcome getItem() itemgetRubric()rubricapplyTo(essayResp)match(essayResponse)scorenewgetNormalMinimum()getNormalMaximum()setScore(score)setFeedback(missingConcepts) - - + + diff --git a/e2etests/testdata/stable/sequence_diagram_span/elk/board.exp.json b/e2etests/testdata/stable/sequence_diagram_span/elk/board.exp.json index 3525465d4..6d2c55f61 100644 --- a/e2etests/testdata/stable/sequence_diagram_span/elk/board.exp.json +++ b/e2etests/testdata/stable/sequence_diagram_span/elk/board.exp.json @@ -681,11 +681,11 @@ "labelPercentage": 0, "route": [ { - "x": 75, + "x": 81, "y": 320 }, { - "x": 500, + "x": 494, "y": 320 } ], @@ -720,11 +720,11 @@ "labelPercentage": 0, "route": [ { - "x": 75, + "x": 81, "y": 450 }, { - "x": 500, + "x": 494, "y": 450 } ], @@ -759,11 +759,11 @@ "labelPercentage": 0, "route": [ { - "x": 75, + "x": 81, "y": 580 }, { - "x": 925, + "x": 919, "y": 580 } ], @@ -798,11 +798,11 @@ "labelPercentage": 0, "route": [ { - "x": 75, + "x": 81, "y": 710 }, { - "x": 925, + "x": 919, "y": 710 } ], @@ -837,11 +837,11 @@ "labelPercentage": 0, "route": [ { - "x": 75, + "x": 81, "y": 840 }, { - "x": 1343, + "x": 1337, "y": 840 } ], @@ -880,7 +880,7 @@ "y": 970 }, { - "x": 1343, + "x": 1333, "y": 970 } ], @@ -915,11 +915,11 @@ "labelPercentage": 0, "route": [ { - "x": 1343, + "x": 1353, "y": 1100 }, { - "x": 1766, + "x": 1760, "y": 1100 } ], @@ -958,7 +958,7 @@ "y": 1230 }, { - "x": 1343, + "x": 1337, "y": 1230 } ], @@ -993,11 +993,11 @@ "labelPercentage": 0, "route": [ { - "x": 75, + "x": 81, "y": 1360 }, { - "x": 2194.5, + "x": 2188.5, "y": 1360 } ], @@ -1032,11 +1032,11 @@ "labelPercentage": 0, "route": [ { - "x": 75, + "x": 81, "y": 1490 }, { - "x": 925, + "x": 919, "y": 1490 } ], @@ -1071,11 +1071,11 @@ "labelPercentage": 0, "route": [ { - "x": 75, + "x": 81, "y": 1620 }, { - "x": 925, + "x": 919, "y": 1620 } ], @@ -1110,11 +1110,11 @@ "labelPercentage": 0, "route": [ { - "x": 75, + "x": 81, "y": 1750 }, { - "x": 2194.5, + "x": 2188.5, "y": 1750 } ], @@ -1149,11 +1149,11 @@ "labelPercentage": 0, "route": [ { - "x": 75, + "x": 81, "y": 1880 }, { - "x": 2194.5, + "x": 2188.5, "y": 1880 } ], diff --git a/e2etests/testdata/stable/sequence_diagram_span/elk/sketch.exp.svg b/e2etests/testdata/stable/sequence_diagram_span/elk/sketch.exp.svg index 9cbe8881f..edb12da43 100644 --- a/e2etests/testdata/stable/sequence_diagram_span/elk/sketch.exp.svg +++ b/e2etests/testdata/stable/sequence_diagram_span/elk/sketch.exp.svg @@ -14,15 +14,15 @@ width="2493" height="2160" viewBox="-100 -50 2493 2160">scoreritemResponseitemessayRubricconceptitemOutcome getItem() itemgetRubric()rubricapplyTo(essayResp)match(essayResponse)scorenewgetNormalMinimum()getNormalMaximum()setScore(score)setFeedback(missingConcepts) +scoreritemResponseitemessayRubricconceptitemOutcome getItem() itemgetRubric()rubricapplyTo(essayResp)match(essayResponse)scorenewgetNormalMinimum()getNormalMaximum()setScore(score)setFeedback(missingConcepts) - - + + diff --git a/e2etests/testdata/stable/sequence_diagrams/dagre/board.exp.json b/e2etests/testdata/stable/sequence_diagrams/dagre/board.exp.json index 3c1fd3340..5d18bf4a4 100644 --- a/e2etests/testdata/stable/sequence_diagrams/dagre/board.exp.json +++ b/e2etests/testdata/stable/sequence_diagrams/dagre/board.exp.json @@ -2486,11 +2486,11 @@ "labelPercentage": 0, "route": [ { - "x": 2626, + "x": 2636, "y": 670 }, { - "x": 3051, + "x": 3041, "y": 670 } ], @@ -2525,11 +2525,11 @@ "labelPercentage": 0, "route": [ { - "x": 2626, + "x": 2636, "y": 800 }, { - "x": 3051, + "x": 3041, "y": 800 } ], @@ -2564,11 +2564,11 @@ "labelPercentage": 0, "route": [ { - "x": 2626, + "x": 2636, "y": 930 }, { - "x": 3476, + "x": 3466, "y": 930 } ], @@ -2603,11 +2603,11 @@ "labelPercentage": 0, "route": [ { - "x": 2626, + "x": 2636, "y": 1060 }, { - "x": 3476, + "x": 3466, "y": 1060 } ], @@ -2642,11 +2642,11 @@ "labelPercentage": 0, "route": [ { - "x": 2626, + "x": 2636, "y": 1190 }, { - "x": 3894, + "x": 3884, "y": 1190 } ], @@ -2685,7 +2685,7 @@ "y": 1320 }, { - "x": 3894, + "x": 3880, "y": 1320 } ], @@ -2720,11 +2720,11 @@ "labelPercentage": 0, "route": [ { - "x": 3894, + "x": 3908, "y": 1450 }, { - "x": 4317, + "x": 4307, "y": 1450 } ], @@ -2763,7 +2763,7 @@ "y": 1580 }, { - "x": 3894, + "x": 3884, "y": 1580 } ], @@ -2798,11 +2798,11 @@ "labelPercentage": 0, "route": [ { - "x": 2626, + "x": 2636, "y": 1710 }, { - "x": 4745.5, + "x": 4735.5, "y": 1710 } ], @@ -2837,11 +2837,11 @@ "labelPercentage": 0, "route": [ { - "x": 2626, + "x": 2636, "y": 1840 }, { - "x": 3476, + "x": 3466, "y": 1840 } ], @@ -2876,11 +2876,11 @@ "labelPercentage": 0, "route": [ { - "x": 2626, + "x": 2636, "y": 1970 }, { - "x": 3476, + "x": 3466, "y": 1970 } ], @@ -2915,11 +2915,11 @@ "labelPercentage": 0, "route": [ { - "x": 2626, + "x": 2636, "y": 2100 }, { - "x": 4745.5, + "x": 4735.5, "y": 2100 } ], @@ -2954,11 +2954,11 @@ "labelPercentage": 0, "route": [ { - "x": 2626, + "x": 2636, "y": 2230 }, { - "x": 4745.5, + "x": 4735.5, "y": 2230 } ], @@ -2993,11 +2993,11 @@ "labelPercentage": 0, "route": [ { - "x": 125, + "x": 139, "y": 668 }, { - "x": 550, + "x": 536, "y": 668 } ], @@ -3032,11 +3032,11 @@ "labelPercentage": 0, "route": [ { - "x": 125, + "x": 139, "y": 798 }, { - "x": 550, + "x": 536, "y": 798 } ], @@ -3071,11 +3071,11 @@ "labelPercentage": 0, "route": [ { - "x": 125, + "x": 139, "y": 928 }, { - "x": 975, + "x": 961, "y": 928 } ], @@ -3110,11 +3110,11 @@ "labelPercentage": 0, "route": [ { - "x": 125, + "x": 139, "y": 1058 }, { - "x": 975, + "x": 961, "y": 1058 } ], @@ -3149,11 +3149,11 @@ "labelPercentage": 0, "route": [ { - "x": 125, + "x": 139, "y": 1188 }, { - "x": 1393, + "x": 1379, "y": 1188 } ], @@ -3192,7 +3192,7 @@ "y": 1318 }, { - "x": 1393, + "x": 1375, "y": 1318 } ], @@ -3227,11 +3227,11 @@ "labelPercentage": 0, "route": [ { - "x": 1393, + "x": 1411, "y": 1448 }, { - "x": 1816, + "x": 1802, "y": 1448 } ], @@ -3270,7 +3270,7 @@ "y": 1578 }, { - "x": 1393, + "x": 1379, "y": 1578 } ], @@ -3305,11 +3305,11 @@ "labelPercentage": 0, "route": [ { - "x": 125, + "x": 139, "y": 1708 }, { - "x": 2244.5, + "x": 2230.5, "y": 1708 } ], @@ -3344,11 +3344,11 @@ "labelPercentage": 0, "route": [ { - "x": 125, + "x": 139, "y": 1838 }, { - "x": 975, + "x": 961, "y": 1838 } ], @@ -3383,11 +3383,11 @@ "labelPercentage": 0, "route": [ { - "x": 125, + "x": 139, "y": 1968 }, { - "x": 975, + "x": 961, "y": 1968 } ], @@ -3422,11 +3422,11 @@ "labelPercentage": 0, "route": [ { - "x": 125, + "x": 139, "y": 2098 }, { - "x": 2244.5, + "x": 2230.5, "y": 2098 } ], @@ -3461,11 +3461,11 @@ "labelPercentage": 0, "route": [ { - "x": 125, + "x": 139, "y": 2228 }, { - "x": 2244.5, + "x": 2230.5, "y": 2228 } ], @@ -3800,11 +3800,11 @@ "labelPercentage": 0, "route": [ { - "x": 2861, + "x": 2847, "y": 2911 }, { - "x": 1989, + "x": 2007, "y": 2911 } ], @@ -3839,11 +3839,11 @@ "labelPercentage": 0, "route": [ { - "x": 1989, + "x": 1971, "y": 3041 }, { - "x": 1571, + "x": 1593, "y": 3041 } ], @@ -3878,11 +3878,11 @@ "labelPercentage": 0, "route": [ { - "x": 1571, + "x": 1549, "y": 3171 }, { - "x": 1148, + "x": 1174, "y": 3171 } ], @@ -3917,11 +3917,11 @@ "labelPercentage": 0, "route": [ { - "x": 1989, + "x": 1975, "y": 3301 }, { - "x": 1571, + "x": 1589, "y": 3301 } ], @@ -3956,11 +3956,11 @@ "labelPercentage": 0, "route": [ { - "x": 1148, + "x": 1174, "y": 3431 }, { - "x": 2412.5, + "x": 2382.5, "y": 3431 } ], @@ -3995,11 +3995,11 @@ "labelPercentage": 0, "route": [ { - "x": 743, + "x": 757, "y": 3561 }, { - "x": 1989, + "x": 1975, "y": 3561 } ], @@ -4034,7 +4034,7 @@ "labelPercentage": 0, "route": [ { - "x": 2412.5, + "x": 2382.5, "y": 3691 }, { @@ -4077,7 +4077,7 @@ "y": 3821 }, { - "x": 2861, + "x": 2847, "y": 3821 } ], diff --git a/e2etests/testdata/stable/sequence_diagrams/dagre/sketch.exp.svg b/e2etests/testdata/stable/sequence_diagrams/dagre/sketch.exp.svg index f5e9861f5..86332068e 100644 --- a/e2etests/testdata/stable/sequence_diagrams/dagre/sketch.exp.svg +++ b/e2etests/testdata/stable/sequence_diagrams/dagre/sketch.exp.svg @@ -14,15 +14,15 @@ width="5044" height="4201" viewBox="-100 -100 5044 4201">a_shapea_sequenceanotherfinallysequencesequencesequencescoreritemResponseitemessayRubricconceptitemOutcomescorerconceptessayRubricitemitemOutcomeitemResponsescoreritemResponseitemessayRubricconceptitemOutcome getItem()itemgetRubric()rubricapplyTo(essayResp)match(essayResponse)scorenewgetNormalMinimum()getNormalMaximum()setScore(score)setFeedback(missingConcepts)getItem()itemgetRubric()rubricapplyTo(essayResp)match(essayResponse)scorenewgetNormalMinimum()getNormalMaximum()setScore(score)setFeedback(missingConcepts) +a_shapea_sequenceanotherfinallysequencesequencesequencescoreritemResponseitemessayRubricconceptitemOutcomescorerconceptessayRubricitemitemOutcomeitemResponsescoreritemResponseitemessayRubricconceptitemOutcome getItem()itemgetRubric()rubricapplyTo(essayResp)match(essayResponse)scorenewgetNormalMinimum()getNormalMaximum()setScore(score)setFeedback(missingConcepts)getItem()itemgetRubric()rubricapplyTo(essayResp)match(essayResponse)scorenewgetNormalMinimum()getNormalMaximum()setScore(score)setFeedback(missingConcepts) - - + + @@ -33,8 +33,8 @@ width="5044" height="4201" viewBox="-100 -100 5044 4201">a_shapea_sequenceanotherfinallysequencesequencesequencescoreritemResponseitemessayRubricconceptitemOutcomescorerconceptessayRubricitemitemOutcomeitemResponsescoreritemResponseitemessayRubricconceptitemOutcome getItem()itemgetRubric()rubricapplyTo(essayResp)match(essayResponse)scorenewgetNormalMinimum()getNormalMaximum()setScore(score)setFeedback(missingConcepts)getItem()itemgetRubric()rubricapplyTo(essayResp)match(essayResponse)scorenewgetNormalMinimum()getNormalMaximum()setScore(score)setFeedback(missingConcepts) - - + + @@ -33,8 +33,8 @@ width="4966" height="4321" viewBox="-88 -88 4966 4321">abcdexplanationanother explanationSome one who believes imaginary things appear right before your i's.The earth is like a tiny grain of sand, only much, much heavier okay + + How this is renderedCLId2astd2compilerd2layoutd2exporterd2themesd2rendererd2sequencelayoutd2dagrelayoutmeasurements also take place 'How this is rendered: {...}'tokenized ASTcompile ASTobjects and edgesrun layout enginesrun engine on shape: sequence_diagram, temporarily removerun core engine on rest add back in sequence diagramsdiagram with correct positions and dimensionsexport diagram with chosen theme and rendererget theme stylesrender to SVGresulting SVG - +How this is renderedCLId2astd2compilerd2layoutd2exporterd2themesd2rendererd2sequencelayoutd2dagrelayoutmeasurements also take place 'How this is rendered: {...}'tokenized ASTcompile ASTobjects and edgesrun layout enginesrun engine on shape: sequence_diagram, temporarily removerun core engine on rest add back in sequence diagramsdiagram with correct positions and dimensionsexport diagram with chosen theme and rendererget theme stylesrender to SVGresulting SVG + - - - - - - - - - + + + + + + + + + How this is renderedCLId2astd2compilerd2layoutd2exporterd2themesd2rendererd2sequencelayoutd2dagrelayoutmeasurements also take place 'How this is rendered: {...}'tokenized ASTcompile ASTobjects and edgesrun layout enginesrun engine on shape: sequence_diagram, temporarily removerun core engine on rest add back in sequence diagramsdiagram with correct positions and dimensionsexport diagram with chosen theme and rendererget theme stylesrender to SVGresulting SVG - +How this is renderedCLId2astd2compilerd2layoutd2exporterd2themesd2rendererd2sequencelayoutd2dagrelayoutmeasurements also take place 'How this is rendered: {...}'tokenized ASTcompile ASTobjects and edgesrun layout enginesrun engine on shape: sequence_diagram, temporarily removerun core engine on rest add back in sequence diagramsdiagram with correct positions and dimensionsexport diagram with chosen theme and rendererget theme stylesrender to SVGresulting SVG + - - - - - - - - - + + + + + + + + +