Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 7 additions & 15 deletions d2compiler/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func compileIR(ast *d2ast.Map, m *d2ir.Map) (*d2graph.Graph, error) {

func (c *compiler) compileBoard(g *d2graph.Graph, ir *d2ir.Map) *d2graph.Graph {
ir = ir.Copy(nil).(*d2ir.Map)
// c.preprocessSeqDiagrams(ir)
c.preprocessSeqDiagrams(ir)
c.compileMap(g.Root, ir)
c.setDefaultShapes(g)
if len(c.err.Errors) == 0 {
Expand Down Expand Up @@ -1483,23 +1483,15 @@ func isCrossEdgeGroupEdge(m *d2ir.Map, e *d2ir.Edge) bool {
return false
}

func isEdgeGroup(n d2ir.Node) bool {
return n.Map().EdgeCountRecursive() > 0
}

func parentSeqDiagram(n d2ir.Node) *d2ir.Map {
for {
m := d2ir.ParentMap(n)
if m == nil {
return nil
}
for _, f := range m.Fields {
if f.Name.ScalarString() == "shape" && f.Name.IsUnquoted() && f.Primary_.Value.ScalarString() == d2target.ShapeSequenceDiagram {
return m
func isEdgeGroup(f *d2ir.Field) bool {
if f.Map() != nil {
for _, f := range f.Map().Fields {
if f.Name.ScalarString() == "shape" && f.Name.IsUnquoted() && f.Primary_.Value.ScalarString() == d2target.ShapeSequenceDiagramEdgeGroup {
return true
}
}
n = m
}
return false
}

func compileConfig(ir *d2ir.Map) (*d2target.Config, error) {
Expand Down
63 changes: 63 additions & 0 deletions d2layouts/d2sequence2/sequencediagram.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package sequencediagram

import (
"context"

"oss.terrastruct.com/d2/d2graph"
)

/*
Concepts:

- Actor
- A top-level entity.
- Every other entity must be associated with an actor.
- Actor Group
- A top level entity.
- If an actor is defined in an actor group, it must also be referenced as such, e.g. group.actor -> actor2
- Message
- A connection between two actors.
- vertical-gap can be defined to specify the NEXT spacing
- Span
- A child of an actor whose shape == nil.
- Messages may be attached directly onto a span.
- Spans can nest, e.g. actor.span1.span2
- Labels are default not shown. Must be explicitly defined to show.
- Note
- A child of an actor whose shape == page.
- Messages are not allowed on Notes.
- Event
- A child of an actor whose shape != nil && shape != page.
- Messages are not allowed on Events.
- Edge Group
- A child of an actor whose shape == edge-group.
- Message inside an edge group are visually grouped together under one label.


- configs:
- vars.mirror: true
- vars.numbered: true
*/

type SequenceDiagram struct {
*builder
}

// Traverse top-down vertically.
// At each vertical step, traverse left-right horizontally
type builder struct {
y int
x int
}

func Layout(ctx context.Context, g *d2graph.Graph) (*SequenceDiagram, error) {
return newSequenceDiagram(g), nil
}

func newSequenceDiagram(g *d2graph.Graph) *SequenceDiagram {
return &SequenceDiagram{builder: newBuilder()}
}

func newBuilder() *builder {
return &builder{}
}
86 changes: 86 additions & 0 deletions d2layouts/d2sequence2/sequencediagram_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package sequencediagram_test

import (
"context"
"strings"
"testing"

"oss.terrastruct.com/d2/d2compiler"
sequencediagram "oss.terrastruct.com/d2/d2layouts/d2sequence2"
"oss.terrastruct.com/d2/d2lib"
"oss.terrastruct.com/d2/lib/log"
"oss.terrastruct.com/d2/lib/textmeasure"
"oss.terrastruct.com/util-go/assert"
"oss.terrastruct.com/util-go/mapfs"
)

func TestSequenceDiagrams(t *testing.T) {
t.Parallel()

t.Run("basic", testBasic)
}

func testBasic(t *testing.T) {
t.Parallel()

tca := []testCase{
{
name: "escaped",
assert: func(t testing.TB, sd *sequencediagram.SequenceDiagram) {
assert.True(t, 1 == 1)
},
},
}

runa(t, tca)
}

type testCase struct {
name string
fs map[string]string
assert func(testing.TB, *sequencediagram.SequenceDiagram)
expErr string
}

func runa(t *testing.T, tca []testCase) {
for _, tc := range tca {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()

ctx := context.Background()
ctx = log.WithTB(ctx, t)
ruler, _ := textmeasure.NewRuler()
fs, _ := mapfs.New(tc.fs)
compileOpts := &d2lib.CompileOptions{
Ruler: ruler,
FS: fs,
}
g, config, err := d2compiler.Compile(compileOpts.InputPath, strings.NewReader(tc.fs["index.d2"]), &d2compiler.CompileOptions{
UTF16Pos: compileOpts.UTF16Pos,
FS: compileOpts.FS,
})
if tc.expErr != "" {
assert.Error(t, err)
} else {
assert.Success(t, err)
}
if config != nil {
g.Data = config.Data
}
err = g.SetDimensions(nil, compileOpts.Ruler, compileOpts.FontFamily, compileOpts.MonoFontFamily)
if tc.expErr != "" {
assert.Error(t, err)
} else {
assert.Success(t, err)
}

sd, err := sequencediagram.Layout(ctx, g)
if tc.expErr != "" {
assert.Error(t, err)
} else {
assert.Success(t, err)
}
tc.assert(t, sd)
})
}
}
51 changes: 26 additions & 25 deletions d2target/d2target.go
Original file line number Diff line number Diff line change
Expand Up @@ -1048,31 +1048,32 @@ func NewPoint(x, y int) Point {
}

const (
ShapeRectangle = "rectangle"
ShapeSquare = "square"
ShapePage = "page"
ShapeParallelogram = "parallelogram"
ShapeDocument = "document"
ShapeCylinder = "cylinder"
ShapeQueue = "queue"
ShapePackage = "package"
ShapeStep = "step"
ShapeCallout = "callout"
ShapeStoredData = "stored_data"
ShapePerson = "person"
ShapeC4Person = "c4-person"
ShapeDiamond = "diamond"
ShapeOval = "oval"
ShapeCircle = "circle"
ShapeHexagon = "hexagon"
ShapeCloud = "cloud"
ShapeText = "text"
ShapeCode = "code"
ShapeClass = "class"
ShapeSQLTable = "sql_table"
ShapeImage = "image"
ShapeSequenceDiagram = "sequence_diagram"
ShapeHierarchy = "hierarchy"
ShapeRectangle = "rectangle"
ShapeSquare = "square"
ShapePage = "page"
ShapeParallelogram = "parallelogram"
ShapeDocument = "document"
ShapeCylinder = "cylinder"
ShapeQueue = "queue"
ShapePackage = "package"
ShapeStep = "step"
ShapeCallout = "callout"
ShapeStoredData = "stored_data"
ShapePerson = "person"
ShapeC4Person = "c4-person"
ShapeDiamond = "diamond"
ShapeOval = "oval"
ShapeCircle = "circle"
ShapeHexagon = "hexagon"
ShapeCloud = "cloud"
ShapeText = "text"
ShapeCode = "code"
ShapeClass = "class"
ShapeSQLTable = "sql_table"
ShapeImage = "image"
ShapeSequenceDiagram = "sequence_diagram"
ShapeSequenceDiagramEdgeGroup = "edge-group"
ShapeHierarchy = "hierarchy"
)

var Shapes = []string{
Expand Down
Loading
Loading