This commit is contained in:
Alexander Wang 2023-06-08 14:25:13 -07:00
parent 8dc1d9a223
commit d1f7e23aff
No known key found for this signature in database
GPG key ID: D89FA31966BDBECE
6 changed files with 1137 additions and 21 deletions

View file

@ -544,22 +544,7 @@ func getEdgeEndpoints(g *d2graph.Graph, edge *d2graph.Edge) (*d2graph.Object, *d
} }
dst := edge.Dst dst := edge.Dst
for len(dst.Children) > 0 && dst.Class == nil && dst.SQLTable == nil { for len(dst.Children) > 0 && dst.Class == nil && dst.SQLTable == nil {
dst = dst.ChildrenArray[0] dst = getLongestEdgeChainHead(g, dst)
// We want to get the top node of destinations
for _, child := range dst.ChildrenArray {
isHead := true
for _, e := range g.Edges {
if inContainer(e.Src, child) != nil && inContainer(e.Dst, dst) != nil {
isHead = false
break
}
}
if isHead {
dst = child
break
}
}
} }
if edge.SrcArrow && !edge.DstArrow { if edge.SrcArrow && !edge.DstArrow {
// for `b <- a`, edge.Edge is `a -> b` and we expect this routing result // for `b <- a`, edge.Edge is `a -> b` and we expect this routing result
@ -607,8 +592,73 @@ func generateAddEdgeLine(fromID, toID, edgeID string, width, height int) string
return fmt.Sprintf("g.setEdge({v:`%s`, w:`%s`, name:`%s`}, { width:%d, height:%d, labelpos: `c` });\n", escapeID(fromID), escapeID(toID), escapeID(edgeID), width, height) return fmt.Sprintf("g.setEdge({v:`%s`, w:`%s`, name:`%s`}, { width:%d, height:%d, labelpos: `c` });\n", escapeID(fromID), escapeID(toID), escapeID(edgeID), width, height)
} }
// getLongestEdgeChainHead finds the longest chain in a container and gets its head
// If there are multiple chains of the same length, get the head closest to the center
func getLongestEdgeChainHead(g *d2graph.Graph, container *d2graph.Object) *d2graph.Object {
rank := make(map[*d2graph.Object]int)
chainLength := make(map[*d2graph.Object]int)
for _, obj := range container.ChildrenArray {
isHead := true
for _, e := range g.Edges {
if inContainer(e.Src, container) != nil && inContainer(e.Dst, obj) != nil {
isHead = false
break
}
}
if !isHead {
continue
}
rank[obj] = 1
chainLength[obj] = 1
// BFS
queue := []*d2graph.Object{obj}
visited := make(map[*d2graph.Object]struct{})
for len(queue) > 0 {
curr := queue[0]
queue = queue[1:]
if _, ok := visited[curr]; ok {
continue
}
visited[curr] = struct{}{}
for _, e := range g.Edges {
child := inContainer(e.Dst, container)
if child == curr {
continue
}
if child != nil && inContainer(e.Src, curr) != nil {
if rank[curr]+1 > rank[child] {
rank[child] = rank[curr] + 1
chainLength[obj] = go2.Max(chainLength[obj], rank[child])
}
queue = append(queue, child)
}
}
}
}
max := int(math.MinInt32)
for _, obj := range container.ChildrenArray {
if chainLength[obj] > max {
max = chainLength[obj]
}
}
var heads []*d2graph.Object
for i, obj := range container.ChildrenArray {
if rank[obj] == 1 && chainLength[obj] == max {
heads = append(heads, container.ChildrenArray[i])
}
}
if len(heads) > 0 {
return heads[int(math.Floor(float64(len(heads))/2.0))]
}
return container.ChildrenArray[0]
}
// getLongestEdgeChainTail gets the node at the end of the longest edge chain, because that will be the end of the container // getLongestEdgeChainTail gets the node at the end of the longest edge chain, because that will be the end of the container
// and is what external connections should connect with // and is what external connections should connect with.
// If there are multiple of same length, get the one closest to the middle
func getLongestEdgeChainTail(g *d2graph.Graph, container *d2graph.Object) *d2graph.Object { func getLongestEdgeChainTail(g *d2graph.Graph, container *d2graph.Object) *d2graph.Object {
rank := make(map[*d2graph.Object]int) rank := make(map[*d2graph.Object]int)
@ -647,14 +697,20 @@ func getLongestEdgeChainTail(g *d2graph.Graph, container *d2graph.Object) *d2gra
} }
} }
max := int(math.MinInt32) max := int(math.MinInt32)
var tail *d2graph.Object
for _, obj := range container.ChildrenArray { for _, obj := range container.ChildrenArray {
if rank[obj] >= max { if rank[obj] > max {
max = rank[obj] max = rank[obj]
tail = obj
} }
} }
return tail
var tails []*d2graph.Object
for i, obj := range container.ChildrenArray {
if rank[obj] == max {
tails = append(tails, container.ChildrenArray[i])
}
}
return tails[int(math.Floor(float64(len(tails))/2.0))]
} }
func inContainer(obj, container *d2graph.Object) *d2graph.Object { func inContainer(obj, container *d2graph.Object) *d2graph.Object {

View file

@ -2316,6 +2316,23 @@ Listen <-> Talk: {
target-arrowhead.shape: diamond target-arrowhead.shape: diamond
label: hear label: hear
} }
`,
},
{
name: "dagre-container",
script: `a: {
a
b
c
}
b: {
a
b
c
}
a -> b
`, `,
}, },
{ {

View file

@ -0,0 +1,424 @@
{
"name": "",
"isFolderOnly": false,
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "a",
"type": "rectangle",
"pos": {
"x": 0,
"y": 41
},
"width": 359,
"height": 125,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B4",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "a",
"fontSize": 28,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 12,
"labelHeight": 36,
"labelPosition": "OUTSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "a.a",
"type": "rectangle",
"pos": {
"x": 40,
"y": 70
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "a",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "a.b",
"type": "rectangle",
"pos": {
"x": 153,
"y": 70
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "b",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "a.c",
"type": "rectangle",
"pos": {
"x": 266,
"y": 70
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "c",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "b",
"type": "rectangle",
"pos": {
"x": 113,
"y": 307
},
"width": 359,
"height": 125,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B4",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "b",
"fontSize": 28,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 13,
"labelHeight": 36,
"labelPosition": "OUTSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "b.a",
"type": "rectangle",
"pos": {
"x": 153,
"y": 336
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "a",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "b.b",
"type": "rectangle",
"pos": {
"x": 266,
"y": 336
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "b",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "b.c",
"type": "rectangle",
"pos": {
"x": 379,
"y": 336
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "c",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
}
],
"connections": [
{
"id": "(a -> b)[0]",
"src": "a",
"srcArrow": "none",
"dst": "b",
"dstArrow": "triangle",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "B1",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 179.5,
"y": 166
},
{
"x": 179.5,
"y": 206
},
{
"x": 179.5,
"y": 234.1999969482422
},
{
"x": 179.5,
"y": 307
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
}
],
"root": {
"id": "",
"type": "",
"pos": {
"x": 0,
"y": 0
},
"width": 0,
"height": 0,
"opacity": 0,
"strokeDash": 0,
"strokeWidth": 0,
"borderRadius": 0,
"fill": "N7",
"stroke": "",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"zIndex": 0,
"level": 0
}
}

View file

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" d2Version="v0.4.2-HEAD" preserveAspectRatio="xMinYMin meet" viewBox="0 0 474 433"><svg id="d2-svg" class="d2-664451445" width="474" height="433" viewBox="-1 0 474 433"><rect x="-1.000000" y="0.000000" width="474.000000" height="433.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><style type="text/css"><![CDATA[
.d2-664451445 .text {
font-family: "d2-664451445-font-regular";
}
@font-face {
font-family: d2-664451445-font-regular;
src: url("data:application/font-woff;base64,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");
}
.d2-664451445 .text-bold {
font-family: "d2-664451445-font-bold";
}
@font-face {
font-family: d2-664451445-font-bold;
src: url("data:application/font-woff;base64,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");
}]]></style><style type="text/css"><![CDATA[.shape {
shape-rendering: geometricPrecision;
stroke-linejoin: round;
}
.connection {
stroke-linecap: round;
stroke-linejoin: round;
}
.blend {
mix-blend-mode: multiply;
opacity: 0.5;
}
.d2-664451445 .fill-N1{fill:#0A0F25;}
.d2-664451445 .fill-N2{fill:#676C7E;}
.d2-664451445 .fill-N3{fill:#9499AB;}
.d2-664451445 .fill-N4{fill:#CFD2DD;}
.d2-664451445 .fill-N5{fill:#DEE1EB;}
.d2-664451445 .fill-N6{fill:#EEF1F8;}
.d2-664451445 .fill-N7{fill:#FFFFFF;}
.d2-664451445 .fill-B1{fill:#0D32B2;}
.d2-664451445 .fill-B2{fill:#0D32B2;}
.d2-664451445 .fill-B3{fill:#E3E9FD;}
.d2-664451445 .fill-B4{fill:#E3E9FD;}
.d2-664451445 .fill-B5{fill:#EDF0FD;}
.d2-664451445 .fill-B6{fill:#F7F8FE;}
.d2-664451445 .fill-AA2{fill:#4A6FF3;}
.d2-664451445 .fill-AA4{fill:#EDF0FD;}
.d2-664451445 .fill-AA5{fill:#F7F8FE;}
.d2-664451445 .fill-AB4{fill:#EDF0FD;}
.d2-664451445 .fill-AB5{fill:#F7F8FE;}
.d2-664451445 .stroke-N1{stroke:#0A0F25;}
.d2-664451445 .stroke-N2{stroke:#676C7E;}
.d2-664451445 .stroke-N3{stroke:#9499AB;}
.d2-664451445 .stroke-N4{stroke:#CFD2DD;}
.d2-664451445 .stroke-N5{stroke:#DEE1EB;}
.d2-664451445 .stroke-N6{stroke:#EEF1F8;}
.d2-664451445 .stroke-N7{stroke:#FFFFFF;}
.d2-664451445 .stroke-B1{stroke:#0D32B2;}
.d2-664451445 .stroke-B2{stroke:#0D32B2;}
.d2-664451445 .stroke-B3{stroke:#E3E9FD;}
.d2-664451445 .stroke-B4{stroke:#E3E9FD;}
.d2-664451445 .stroke-B5{stroke:#EDF0FD;}
.d2-664451445 .stroke-B6{stroke:#F7F8FE;}
.d2-664451445 .stroke-AA2{stroke:#4A6FF3;}
.d2-664451445 .stroke-AA4{stroke:#EDF0FD;}
.d2-664451445 .stroke-AA5{stroke:#F7F8FE;}
.d2-664451445 .stroke-AB4{stroke:#EDF0FD;}
.d2-664451445 .stroke-AB5{stroke:#F7F8FE;}
.d2-664451445 .background-color-N1{background-color:#0A0F25;}
.d2-664451445 .background-color-N2{background-color:#676C7E;}
.d2-664451445 .background-color-N3{background-color:#9499AB;}
.d2-664451445 .background-color-N4{background-color:#CFD2DD;}
.d2-664451445 .background-color-N5{background-color:#DEE1EB;}
.d2-664451445 .background-color-N6{background-color:#EEF1F8;}
.d2-664451445 .background-color-N7{background-color:#FFFFFF;}
.d2-664451445 .background-color-B1{background-color:#0D32B2;}
.d2-664451445 .background-color-B2{background-color:#0D32B2;}
.d2-664451445 .background-color-B3{background-color:#E3E9FD;}
.d2-664451445 .background-color-B4{background-color:#E3E9FD;}
.d2-664451445 .background-color-B5{background-color:#EDF0FD;}
.d2-664451445 .background-color-B6{background-color:#F7F8FE;}
.d2-664451445 .background-color-AA2{background-color:#4A6FF3;}
.d2-664451445 .background-color-AA4{background-color:#EDF0FD;}
.d2-664451445 .background-color-AA5{background-color:#F7F8FE;}
.d2-664451445 .background-color-AB4{background-color:#EDF0FD;}
.d2-664451445 .background-color-AB5{background-color:#F7F8FE;}
.d2-664451445 .color-N1{color:#0A0F25;}
.d2-664451445 .color-N2{color:#676C7E;}
.d2-664451445 .color-N3{color:#9499AB;}
.d2-664451445 .color-N4{color:#CFD2DD;}
.d2-664451445 .color-N5{color:#DEE1EB;}
.d2-664451445 .color-N6{color:#EEF1F8;}
.d2-664451445 .color-N7{color:#FFFFFF;}
.d2-664451445 .color-B1{color:#0D32B2;}
.d2-664451445 .color-B2{color:#0D32B2;}
.d2-664451445 .color-B3{color:#E3E9FD;}
.d2-664451445 .color-B4{color:#E3E9FD;}
.d2-664451445 .color-B5{color:#EDF0FD;}
.d2-664451445 .color-B6{color:#F7F8FE;}
.d2-664451445 .color-AA2{color:#4A6FF3;}
.d2-664451445 .color-AA4{color:#EDF0FD;}
.d2-664451445 .color-AA5{color:#F7F8FE;}
.d2-664451445 .color-AB4{color:#EDF0FD;}
.d2-664451445 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]></style><g id="a"><g class="shape" ><rect x="0.000000" y="41.000000" width="359.000000" height="125.000000" class=" stroke-B1 fill-B4" style="stroke-width:2;" /></g><text x="179.500000" y="28.000000" class="text fill-N1" style="text-anchor:middle;font-size:28px">a</text></g><g id="b"><g class="shape" ><rect x="113.000000" y="307.000000" width="359.000000" height="125.000000" class=" stroke-B1 fill-B4" style="stroke-width:2;" /></g><text x="292.500000" y="294.000000" class="text fill-N1" style="text-anchor:middle;font-size:28px">b</text></g><g id="a.a"><g class="shape" ><rect x="40.000000" y="70.000000" width="53.000000" height="66.000000" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="66.500000" y="108.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">a</text></g><g id="a.b"><g class="shape" ><rect x="153.000000" y="70.000000" width="53.000000" height="66.000000" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="179.500000" y="108.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">b</text></g><g id="a.c"><g class="shape" ><rect x="266.000000" y="70.000000" width="53.000000" height="66.000000" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="292.500000" y="108.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">c</text></g><g id="b.a"><g class="shape" ><rect x="153.000000" y="336.000000" width="53.000000" height="66.000000" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="179.500000" y="374.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">a</text></g><g id="b.b"><g class="shape" ><rect x="266.000000" y="336.000000" width="53.000000" height="66.000000" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="292.500000" y="374.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">b</text></g><g id="b.c"><g class="shape" ><rect x="379.000000" y="336.000000" width="53.000000" height="66.000000" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="405.500000" y="374.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">c</text></g><g id="(a -&gt; b)[0]"><marker id="mk-3488378134" markerWidth="10.000000" markerHeight="12.000000" refX="7.000000" refY="6.000000" viewBox="0.000000 0.000000 10.000000 12.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" class="connection fill-B1" stroke-width="2" /> </marker><path d="M 179.500000 168.000000 C 179.500000 206.000000 179.500000 234.199997 179.500000 303.000000" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-664451445)" /></g><mask id="d2-664451445" maskUnits="userSpaceOnUse" x="-1" y="0" width="474" height="433">
<rect x="-1" y="0" width="474" height="433" fill="white"></rect>
</mask></svg></svg>

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -0,0 +1,415 @@
{
"name": "",
"isFolderOnly": false,
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "a",
"type": "rectangle",
"pos": {
"x": 12,
"y": 12
},
"width": 299,
"height": 166,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B4",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "a",
"fontSize": 28,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 12,
"labelHeight": 36,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "a.a",
"type": "rectangle",
"pos": {
"x": 62,
"y": 62
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "a",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "a.b",
"type": "rectangle",
"pos": {
"x": 135,
"y": 62
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "b",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "a.c",
"type": "rectangle",
"pos": {
"x": 208,
"y": 62
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "c",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "b",
"type": "rectangle",
"pos": {
"x": 12,
"y": 248
},
"width": 299,
"height": 166,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B4",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "b",
"fontSize": 28,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 13,
"labelHeight": 36,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "b.a",
"type": "rectangle",
"pos": {
"x": 62,
"y": 298
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "a",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "b.b",
"type": "rectangle",
"pos": {
"x": 135,
"y": 298
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "b",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "b.c",
"type": "rectangle",
"pos": {
"x": 208,
"y": 298
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "c",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
}
],
"connections": [
{
"id": "(a -> b)[0]",
"src": "a",
"srcArrow": "none",
"dst": "b",
"dstArrow": "triangle",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "B1",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 161.5,
"y": 178
},
{
"x": 161.5,
"y": 248
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
}
],
"root": {
"id": "",
"type": "",
"pos": {
"x": 0,
"y": 0
},
"width": 0,
"height": 0,
"opacity": 0,
"strokeDash": 0,
"strokeWidth": 0,
"borderRadius": 0,
"fill": "N7",
"stroke": "",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"zIndex": 0,
"level": 0
}
}

View file

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" d2Version="v0.4.2-HEAD" preserveAspectRatio="xMinYMin meet" viewBox="0 0 301 404"><svg id="d2-svg" class="d2-2957004972" width="301" height="404" viewBox="11 11 301 404"><rect x="11.000000" y="11.000000" width="301.000000" height="404.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><style type="text/css"><![CDATA[
.d2-2957004972 .text {
font-family: "d2-2957004972-font-regular";
}
@font-face {
font-family: d2-2957004972-font-regular;
src: url("data:application/font-woff;base64,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");
}
.d2-2957004972 .text-bold {
font-family: "d2-2957004972-font-bold";
}
@font-face {
font-family: d2-2957004972-font-bold;
src: url("data:application/font-woff;base64,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");
}]]></style><style type="text/css"><![CDATA[.shape {
shape-rendering: geometricPrecision;
stroke-linejoin: round;
}
.connection {
stroke-linecap: round;
stroke-linejoin: round;
}
.blend {
mix-blend-mode: multiply;
opacity: 0.5;
}
.d2-2957004972 .fill-N1{fill:#0A0F25;}
.d2-2957004972 .fill-N2{fill:#676C7E;}
.d2-2957004972 .fill-N3{fill:#9499AB;}
.d2-2957004972 .fill-N4{fill:#CFD2DD;}
.d2-2957004972 .fill-N5{fill:#DEE1EB;}
.d2-2957004972 .fill-N6{fill:#EEF1F8;}
.d2-2957004972 .fill-N7{fill:#FFFFFF;}
.d2-2957004972 .fill-B1{fill:#0D32B2;}
.d2-2957004972 .fill-B2{fill:#0D32B2;}
.d2-2957004972 .fill-B3{fill:#E3E9FD;}
.d2-2957004972 .fill-B4{fill:#E3E9FD;}
.d2-2957004972 .fill-B5{fill:#EDF0FD;}
.d2-2957004972 .fill-B6{fill:#F7F8FE;}
.d2-2957004972 .fill-AA2{fill:#4A6FF3;}
.d2-2957004972 .fill-AA4{fill:#EDF0FD;}
.d2-2957004972 .fill-AA5{fill:#F7F8FE;}
.d2-2957004972 .fill-AB4{fill:#EDF0FD;}
.d2-2957004972 .fill-AB5{fill:#F7F8FE;}
.d2-2957004972 .stroke-N1{stroke:#0A0F25;}
.d2-2957004972 .stroke-N2{stroke:#676C7E;}
.d2-2957004972 .stroke-N3{stroke:#9499AB;}
.d2-2957004972 .stroke-N4{stroke:#CFD2DD;}
.d2-2957004972 .stroke-N5{stroke:#DEE1EB;}
.d2-2957004972 .stroke-N6{stroke:#EEF1F8;}
.d2-2957004972 .stroke-N7{stroke:#FFFFFF;}
.d2-2957004972 .stroke-B1{stroke:#0D32B2;}
.d2-2957004972 .stroke-B2{stroke:#0D32B2;}
.d2-2957004972 .stroke-B3{stroke:#E3E9FD;}
.d2-2957004972 .stroke-B4{stroke:#E3E9FD;}
.d2-2957004972 .stroke-B5{stroke:#EDF0FD;}
.d2-2957004972 .stroke-B6{stroke:#F7F8FE;}
.d2-2957004972 .stroke-AA2{stroke:#4A6FF3;}
.d2-2957004972 .stroke-AA4{stroke:#EDF0FD;}
.d2-2957004972 .stroke-AA5{stroke:#F7F8FE;}
.d2-2957004972 .stroke-AB4{stroke:#EDF0FD;}
.d2-2957004972 .stroke-AB5{stroke:#F7F8FE;}
.d2-2957004972 .background-color-N1{background-color:#0A0F25;}
.d2-2957004972 .background-color-N2{background-color:#676C7E;}
.d2-2957004972 .background-color-N3{background-color:#9499AB;}
.d2-2957004972 .background-color-N4{background-color:#CFD2DD;}
.d2-2957004972 .background-color-N5{background-color:#DEE1EB;}
.d2-2957004972 .background-color-N6{background-color:#EEF1F8;}
.d2-2957004972 .background-color-N7{background-color:#FFFFFF;}
.d2-2957004972 .background-color-B1{background-color:#0D32B2;}
.d2-2957004972 .background-color-B2{background-color:#0D32B2;}
.d2-2957004972 .background-color-B3{background-color:#E3E9FD;}
.d2-2957004972 .background-color-B4{background-color:#E3E9FD;}
.d2-2957004972 .background-color-B5{background-color:#EDF0FD;}
.d2-2957004972 .background-color-B6{background-color:#F7F8FE;}
.d2-2957004972 .background-color-AA2{background-color:#4A6FF3;}
.d2-2957004972 .background-color-AA4{background-color:#EDF0FD;}
.d2-2957004972 .background-color-AA5{background-color:#F7F8FE;}
.d2-2957004972 .background-color-AB4{background-color:#EDF0FD;}
.d2-2957004972 .background-color-AB5{background-color:#F7F8FE;}
.d2-2957004972 .color-N1{color:#0A0F25;}
.d2-2957004972 .color-N2{color:#676C7E;}
.d2-2957004972 .color-N3{color:#9499AB;}
.d2-2957004972 .color-N4{color:#CFD2DD;}
.d2-2957004972 .color-N5{color:#DEE1EB;}
.d2-2957004972 .color-N6{color:#EEF1F8;}
.d2-2957004972 .color-N7{color:#FFFFFF;}
.d2-2957004972 .color-B1{color:#0D32B2;}
.d2-2957004972 .color-B2{color:#0D32B2;}
.d2-2957004972 .color-B3{color:#E3E9FD;}
.d2-2957004972 .color-B4{color:#E3E9FD;}
.d2-2957004972 .color-B5{color:#EDF0FD;}
.d2-2957004972 .color-B6{color:#F7F8FE;}
.d2-2957004972 .color-AA2{color:#4A6FF3;}
.d2-2957004972 .color-AA4{color:#EDF0FD;}
.d2-2957004972 .color-AA5{color:#F7F8FE;}
.d2-2957004972 .color-AB4{color:#EDF0FD;}
.d2-2957004972 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]></style><g id="a"><g class="shape" ><rect x="12.000000" y="12.000000" width="299.000000" height="166.000000" class=" stroke-B1 fill-B4" style="stroke-width:2;" /></g><text x="161.500000" y="45.000000" class="text fill-N1" style="text-anchor:middle;font-size:28px">a</text></g><g id="b"><g class="shape" ><rect x="12.000000" y="248.000000" width="299.000000" height="166.000000" class=" stroke-B1 fill-B4" style="stroke-width:2;" /></g><text x="161.500000" y="281.000000" class="text fill-N1" style="text-anchor:middle;font-size:28px">b</text></g><g id="a.a"><g class="shape" ><rect x="62.000000" y="62.000000" width="53.000000" height="66.000000" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="88.500000" y="100.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">a</text></g><g id="a.b"><g class="shape" ><rect x="135.000000" y="62.000000" width="53.000000" height="66.000000" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="161.500000" y="100.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">b</text></g><g id="a.c"><g class="shape" ><rect x="208.000000" y="62.000000" width="53.000000" height="66.000000" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="234.500000" y="100.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">c</text></g><g id="b.a"><g class="shape" ><rect x="62.000000" y="298.000000" width="53.000000" height="66.000000" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="88.500000" y="336.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">a</text></g><g id="b.b"><g class="shape" ><rect x="135.000000" y="298.000000" width="53.000000" height="66.000000" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="161.500000" y="336.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">b</text></g><g id="b.c"><g class="shape" ><rect x="208.000000" y="298.000000" width="53.000000" height="66.000000" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="234.500000" y="336.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">c</text></g><g id="(a -&gt; b)[0]"><marker id="mk-3488378134" markerWidth="10.000000" markerHeight="12.000000" refX="7.000000" refY="6.000000" viewBox="0.000000 0.000000 10.000000 12.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" class="connection fill-B1" stroke-width="2" /> </marker><path d="M 161.500000 180.000000 L 161.500000 244.000000" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-2957004972)" /></g><mask id="d2-2957004972" maskUnits="userSpaceOnUse" x="11" y="11" width="301" height="404">
<rect x="11" y="11" width="301" height="404" fill="white"></rect>
</mask></svg></svg>

After

Width:  |  Height:  |  Size: 14 KiB