Merge branch 'master' into gh-821-ppt

This commit is contained in:
Júlio César Batista 2023-04-07 18:12:50 -03:00
commit ff7438fc2a
No known key found for this signature in database
GPG key ID: 10C4B861BF314878
196 changed files with 50781 additions and 4249 deletions

View file

@ -226,6 +226,7 @@ let us know and we'll be happy to include it here!
- **CIL (C#, Visual Basic, F#, C++ CLR) to D2**: [https://github.com/HugoVG/AppDiagram](https://github.com/HugoVG/AppDiagram) - **CIL (C#, Visual Basic, F#, C++ CLR) to D2**: [https://github.com/HugoVG/AppDiagram](https://github.com/HugoVG/AppDiagram)
- **D2 Snippets (for text editors)**: [https://github.com/Paracelsus-Rose/D2-Language-Code-Snippets](https://github.com/Paracelsus-Rose/D2-Language-Code-Snippets) - **D2 Snippets (for text editors)**: [https://github.com/Paracelsus-Rose/D2-Language-Code-Snippets](https://github.com/Paracelsus-Rose/D2-Language-Code-Snippets)
- **Mongo to D2**: [https://github.com/novuhq/mongo-to-D2](https://github.com/novuhq/mongo-to-D2) - **Mongo to D2**: [https://github.com/novuhq/mongo-to-D2](https://github.com/novuhq/mongo-to-D2)
- **Pandoc filter**: [https://github.com/ram02z/d2-filter](https://github.com/ram02z/d2-filter)
### Misc ### Misc
@ -271,3 +272,5 @@ this selected list of featured projects using D2.
- Open-source money manager app for Android (1.1k stars). - Open-source money manager app for Android (1.1k stars).
- [LocalStack](https://docs.localstack.cloud/references/network-troubleshooting/) - [LocalStack](https://docs.localstack.cloud/references/network-troubleshooting/)
- Cloud service emulator (46k stars) - Cloud service emulator (46k stars)
- [Queue Library](https://github.com/golang-queue/queue/tree/master/images)
- Queue is a Golang library for spawning and managing a Goroutine pool

View file

@ -1,10 +1,25 @@
#### Features 🚀 #### Features 🚀
- Container with constant key near attribute now can have descendant objects and connections [#1071](https://github.com/terrastruct/d2/pull/1071)
- Classes are implemented. See [docs](https://d2lang.com/todo). [#772](https://github.com/terrastruct/d2/pull/772)
- Multi-board SVG outputs with internal links go to their output paths [#1116](https://github.com/terrastruct/d2/pull/1116) - Multi-board SVG outputs with internal links go to their output paths [#1116](https://github.com/terrastruct/d2/pull/1116)
- New grid layout to place nodes in rows and columns [#1122](https://github.com/terrastruct/d2/pull/1122)
#### Improvements 🧹 #### Improvements 🧹
- Labels on parallel `dagre` connections include a gap between them [#1134](https://github.com/terrastruct/d2/pull/1134)
- Sequence Diagram `Lifelines` now inherit the Actor `stroke` and `stroke-dash` [#1140](https://github.com/terrastruct/d2/pull/1140)
#### Bugfixes ⛑️ #### Bugfixes ⛑️
- Fix inheritence in scenarios/steps [#1090](https://github.com/terrastruct/d2/pull/1090)
- Fix a bug in 32bit builds [#1115](https://github.com/terrastruct/d2/issues/1115)
- Fix a bug in ID parsing [#322](https://github.com/terrastruct/d2/issues/322) - Fix a bug in ID parsing [#322](https://github.com/terrastruct/d2/issues/322)
- Fix a bug in watch mode parsing SVG [#1119](https://github.com/terrastruct/d2/issues/1119) - Fix a bug in watch mode parsing SVG [#1119](https://github.com/terrastruct/d2/issues/1119)
- Namespace transitions so that multiple animated D2 diagrams can exist on the same page [#1123](https://github.com/terrastruct/d2/issues/1123)
- Fix a bug in vertical alignment of appendix lines [#1104](https://github.com/terrastruct/d2/issues/1104)
- Fix precision difference for sketch mode running on different architectures [#921](https://github.com/terrastruct/d2/issues/921)
#### Breaking changes
- `class` and `classes` are now reserved keywords.

View file

@ -393,6 +393,8 @@ func compile(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, rende
if err != nil { if err != nil {
return nil, false, err return nil, false, err
} }
var out []byte
if len(boards) > 0 {
out := boards[0] out := boards[0]
if animateInterval > 0 { if animateInterval > 0 {
out, err = d2animate.Wrap(diagram, boards, renderOpts, int(animateInterval)) out, err = d2animate.Wrap(diagram, boards, renderOpts, int(animateInterval))
@ -409,6 +411,7 @@ func compile(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, rende
} }
ms.Log.Success.Printf("successfully compiled %s to %s in %s", ms.HumanPath(inputPath), ms.HumanPath(outputPath), time.Since(start)) ms.Log.Success.Printf("successfully compiled %s to %s in %s", ms.HumanPath(inputPath), ms.HumanPath(outputPath), time.Since(start))
} }
}
return out, true, nil return out, true, nil
} }
} }

View file

@ -73,6 +73,7 @@ func (c *compiler) compileBoard(g *d2graph.Graph, ir *d2ir.Map) *d2graph.Graph {
c.validateKeys(g.Root, ir) c.validateKeys(g.Root, ir)
} }
c.validateNear(g) c.validateNear(g)
c.validateEdges(g)
c.compileBoardsField(g, ir, "layers") c.compileBoardsField(g, ir, "layers")
c.compileBoardsField(g, ir, "scenarios") c.compileBoardsField(g, ir, "scenarios")
@ -115,7 +116,6 @@ func (c *compiler) compileBoardsField(g *d2graph.Graph, ir *d2ir.Map, fieldName
} }
type compiler struct { type compiler struct {
inEdgeGroup bool
err d2parser.ParseError err d2parser.ParseError
} }
@ -124,6 +124,18 @@ func (c *compiler) errorf(n d2ast.Node, f string, v ...interface{}) {
} }
func (c *compiler) compileMap(obj *d2graph.Object, m *d2ir.Map) { func (c *compiler) compileMap(obj *d2graph.Object, m *d2ir.Map) {
class := m.GetField("class")
if class != nil {
className := class.Primary()
if className == nil {
c.errorf(class.LastRef().AST(), "class missing value")
} else {
classMap := m.GetClassMap(className.String())
if classMap != nil {
c.compileMap(obj, classMap)
}
}
}
shape := m.GetField("shape") shape := m.GetField("shape")
if shape != nil { if shape != nil {
c.compileField(obj, shape) c.compileField(obj, shape)
@ -158,7 +170,27 @@ func (c *compiler) compileField(obj *d2graph.Object, f *d2ir.Field) {
return return
} }
_, isReserved := d2graph.SimpleReservedKeywords[keyword] _, isReserved := d2graph.SimpleReservedKeywords[keyword]
if isReserved { if f.Name == "classes" {
if f.Map() != nil {
if len(f.Map().Edges) > 0 {
c.errorf(f.Map().Edges[0].LastRef().AST(), "classes cannot contain an edge")
}
for _, classesField := range f.Map().Fields {
if classesField.Map() == nil {
continue
}
for _, cf := range classesField.Map().Fields {
if _, ok := d2graph.ReservedKeywords[cf.Name]; !ok {
c.errorf(cf.LastRef().AST(), "%s is an invalid class field, must be reserved keyword", cf.Name)
}
if cf.Name == "class" {
c.errorf(cf.LastRef().AST(), `"class" cannot appear within "classes"`)
}
}
}
}
return
} else if isReserved {
c.compileReserved(obj.Attributes, f) c.compileReserved(obj.Attributes, f)
return return
} else if f.Name == "style" { } else if f.Name == "style" {
@ -362,6 +394,35 @@ func (c *compiler) compileReserved(attrs *d2graph.Attributes, f *d2ir.Field) {
} }
attrs.Constraint.Value = scalar.ScalarString() attrs.Constraint.Value = scalar.ScalarString()
attrs.Constraint.MapKey = f.LastPrimaryKey() attrs.Constraint.MapKey = f.LastPrimaryKey()
case "grid-rows":
v, err := strconv.Atoi(scalar.ScalarString())
if err != nil {
c.errorf(scalar, "non-integer grid-rows %#v: %s", scalar.ScalarString(), err)
return
}
if v <= 0 {
c.errorf(scalar, "grid-rows must be a positive integer: %#v", scalar.ScalarString())
return
}
attrs.GridRows = &d2graph.Scalar{}
attrs.GridRows.Value = scalar.ScalarString()
attrs.GridRows.MapKey = f.LastPrimaryKey()
case "grid-columns":
v, err := strconv.Atoi(scalar.ScalarString())
if err != nil {
c.errorf(scalar, "non-integer grid-columns %#v: %s", scalar.ScalarString(), err)
return
}
if v <= 0 {
c.errorf(scalar, "grid-columns must be a positive integer: %#v", scalar.ScalarString())
return
}
attrs.GridColumns = &d2graph.Scalar{}
attrs.GridColumns.Value = scalar.ScalarString()
attrs.GridColumns.MapKey = f.LastPrimaryKey()
case "class":
attrs.Classes = append(attrs.Classes, scalar.ScalarString())
case "classes":
} }
if attrs.Link != nil && attrs.Tooltip != nil { if attrs.Link != nil && attrs.Tooltip != nil {
@ -453,14 +514,7 @@ func (c *compiler) compileEdge(obj *d2graph.Object, e *d2ir.Edge) {
c.compileLabel(edge.Attributes, e) c.compileLabel(edge.Attributes, e)
} }
if e.Map() != nil { if e.Map() != nil {
for _, f := range e.Map().Fields { c.compileEdgeMap(edge, e.Map())
_, ok := d2graph.ReservedKeywords[f.Name]
if !ok {
c.errorf(f.References[0].AST(), `edge map keys must be reserved keywords`)
continue
}
c.compileEdgeField(edge, f)
}
} }
edge.Attributes.Label.MapKey = e.LastPrimaryKey() edge.Attributes.Label.MapKey = e.LastPrimaryKey()
@ -477,6 +531,29 @@ func (c *compiler) compileEdge(obj *d2graph.Object, e *d2ir.Edge) {
} }
} }
func (c *compiler) compileEdgeMap(edge *d2graph.Edge, m *d2ir.Map) {
class := m.GetField("class")
if class != nil {
className := class.Primary()
if className == nil {
c.errorf(class.LastRef().AST(), "class missing value")
} else {
classMap := m.GetClassMap(className.String())
if classMap != nil {
c.compileEdgeMap(edge, classMap)
}
}
}
for _, f := range m.Fields {
_, ok := d2graph.ReservedKeywords[f.Name]
if !ok {
c.errorf(f.References[0].AST(), `edge map keys must be reserved keywords`)
continue
}
c.compileEdgeField(edge, f)
}
}
func (c *compiler) compileEdgeField(edge *d2graph.Edge, f *d2ir.Field) { func (c *compiler) compileEdgeField(edge *d2graph.Edge, f *d2ir.Field) {
keyword := strings.ToLower(f.Name) keyword := strings.ToLower(f.Name)
_, isStyleReserved := d2graph.StyleKeywords[keyword] _, isStyleReserved := d2graph.StyleKeywords[keyword]
@ -678,6 +755,13 @@ func (c *compiler) validateKey(obj *d2graph.Object, f *d2ir.Field) {
if !in && arrowheadIn { if !in && arrowheadIn {
c.errorf(f.LastPrimaryKey(), fmt.Sprintf(`invalid shape, can only set "%s" for arrowheads`, obj.Attributes.Shape.Value)) c.errorf(f.LastPrimaryKey(), fmt.Sprintf(`invalid shape, can only set "%s" for arrowheads`, obj.Attributes.Shape.Value))
} }
case "grid-rows", "grid-columns":
for _, child := range obj.ChildrenArray {
if child.IsContainer() {
c.errorf(f.LastPrimaryKey(),
fmt.Sprintf(`%#v can only be used on containers with one level of nesting right now. (%#v has nested %#v)`, keyword, child.AbsID(), child.ChildrenArray[0].ID))
}
}
} }
return return
} }
@ -734,31 +818,48 @@ func (c *compiler) validateNear(g *d2graph.Graph) {
} }
} }
} else if isConst { } else if isConst {
is := false
for _, e := range g.Edges {
if e.Src == obj || e.Dst == obj {
is = true
break
}
}
if is {
c.errorf(obj.Attributes.NearKey, "constant near keys cannot be set on connected shapes")
continue
}
if obj.Parent != g.Root { if obj.Parent != g.Root {
c.errorf(obj.Attributes.NearKey, "constant near keys can only be set on root level shapes") c.errorf(obj.Attributes.NearKey, "constant near keys can only be set on root level shapes")
continue continue
} }
if len(obj.ChildrenArray) > 0 {
c.errorf(obj.Attributes.NearKey, "constant near keys cannot be set on shapes with children")
continue
}
} else { } else {
c.errorf(obj.Attributes.NearKey, "near key %#v must be the absolute path to a shape or one of the following constants: %s", d2format.Format(obj.Attributes.NearKey), strings.Join(d2graph.NearConstantsArray, ", ")) c.errorf(obj.Attributes.NearKey, "near key %#v must be the absolute path to a shape or one of the following constants: %s", d2format.Format(obj.Attributes.NearKey), strings.Join(d2graph.NearConstantsArray, ", "))
continue continue
} }
} }
} }
for _, edge := range g.Edges {
srcNearContainer := edge.Src.OuterNearContainer()
dstNearContainer := edge.Dst.OuterNearContainer()
var isSrcNearConst, isDstNearConst bool
if srcNearContainer != nil {
_, isSrcNearConst = d2graph.NearConstants[d2graph.Key(srcNearContainer.Attributes.NearKey)[0]]
}
if dstNearContainer != nil {
_, isDstNearConst = d2graph.NearConstants[d2graph.Key(dstNearContainer.Attributes.NearKey)[0]]
}
if (isSrcNearConst || isDstNearConst) && srcNearContainer != dstNearContainer {
c.errorf(edge.References[0].Edge, "cannot connect objects from within a container, that has near constant set, to objects outside that container")
}
}
}
func (c *compiler) validateEdges(g *d2graph.Graph) {
for _, edge := range g.Edges {
if gd := edge.Src.Parent.ClosestGridDiagram(); gd != nil {
c.errorf(edge.GetAstEdge(), "edges in grid diagrams are not supported yet")
continue
}
if gd := edge.Dst.Parent.ClosestGridDiagram(); gd != nil {
c.errorf(edge.GetAstEdge(), "edges in grid diagrams are not supported yet")
continue
}
}
} }
func (c *compiler) validateBoardLinks(g *d2graph.Graph) { func (c *compiler) validateBoardLinks(g *d2graph.Graph) {

View file

@ -1558,25 +1558,27 @@ d2/testdata/d2compiler/TestCompile/near-invalid.d2:14:9: near keys cannot be set
`, `,
expErr: `d2/testdata/d2compiler/TestCompile/near_bad_constant.d2:1:9: near key "txop-center" must be the absolute path to a shape or one of the following constants: top-left, top-center, top-right, center-left, center-right, bottom-left, bottom-center, bottom-right`, expErr: `d2/testdata/d2compiler/TestCompile/near_bad_constant.d2:1:9: near key "txop-center" must be the absolute path to a shape or one of the following constants: top-left, top-center, top-right, center-left, center-right, bottom-left, bottom-center, bottom-right`,
}, },
{
name: "near_bad_container",
text: `x: {
near: top-center
y
}
`,
expErr: `d2/testdata/d2compiler/TestCompile/near_bad_container.d2:2:9: constant near keys cannot be set on shapes with children`,
},
{ {
name: "near_bad_connected", name: "near_bad_connected",
text: `x: { text: `
x: {
near: top-center near: top-center
} }
x -> y x -> y
`, `,
expErr: `d2/testdata/d2compiler/TestCompile/near_bad_connected.d2:2:9: constant near keys cannot be set on connected shapes`, expErr: `d2/testdata/d2compiler/TestCompile/near_bad_connected.d2:5:5: cannot connect objects from within a container, that has near constant set, to objects outside that container`,
},
{
name: "near_descendant_connect_to_outside",
text: `
x: {
near: top-left
y
}
x.y -> z
`,
expErr: "d2/testdata/d2compiler/TestCompile/near_descendant_connect_to_outside.d2:6:5: cannot connect objects from within a container, that has near constant set, to objects outside that container",
}, },
{ {
name: "nested_near_constant", name: "nested_near_constant",
@ -2268,6 +2270,150 @@ obj {
`, `,
expErr: `d2/testdata/d2compiler/TestCompile/near_near_const.d2:7:8: near keys cannot be set to an object with a constant near key`, expErr: `d2/testdata/d2compiler/TestCompile/near_near_const.d2:7:8: near keys cannot be set to an object with a constant near key`,
}, },
{
name: "grid",
text: `hey: {
grid-rows: 200
grid-columns: 230
}
`,
assertions: func(t *testing.T, g *d2graph.Graph) {
tassert.Equal(t, "200", g.Objects[0].Attributes.GridRows.Value)
},
},
{
name: "grid_negative",
text: `hey: {
grid-rows: 200
grid-columns: -200
}
`,
expErr: `d2/testdata/d2compiler/TestCompile/grid_negative.d2:3:16: grid-columns must be a positive integer: "-200"`,
},
{
name: "grid_edge",
text: `hey: {
grid-rows: 1
a -> b
}
c -> hey.b
hey.a -> c
hey -> c: ok
`,
expErr: `d2/testdata/d2compiler/TestCompile/grid_edge.d2:3:2: edges in grid diagrams are not supported yet
d2/testdata/d2compiler/TestCompile/grid_edge.d2:5:2: edges in grid diagrams are not supported yet
d2/testdata/d2compiler/TestCompile/grid_edge.d2:6:2: edges in grid diagrams are not supported yet`,
},
{
name: "grid_nested",
text: `hey: {
grid-rows: 200
grid-columns: 200
a
b
c
d.invalid descendant
}
`,
expErr: `d2/testdata/d2compiler/TestCompile/grid_nested.d2:2:2: "grid-rows" can only be used on containers with one level of nesting right now. ("hey.d" has nested "invalid descendant")
d2/testdata/d2compiler/TestCompile/grid_nested.d2:3:2: "grid-columns" can only be used on containers with one level of nesting right now. ("hey.d" has nested "invalid descendant")`,
},
{
name: "classes",
text: `classes: {
dragon_ball: {
label: ""
shape: circle
style.fill: orange
}
path: {
label: "then"
style.stroke-width: 4
}
}
nostar: { class: dragon_ball }
1star: "*" { class: dragon_ball; style.fill: red }
2star: { label: "**"; class: dragon_ball }
nostar -> 1star: { class: path }
`,
assertions: func(t *testing.T, g *d2graph.Graph) {
tassert.Equal(t, 3, len(g.Objects))
tassert.Equal(t, "dragon_ball", g.Objects[0].Attributes.Classes[0])
tassert.Equal(t, "", g.Objects[0].Attributes.Label.Value)
// Class field overrides primary
tassert.Equal(t, "", g.Objects[1].Attributes.Label.Value)
tassert.Equal(t, "**", g.Objects[2].Attributes.Label.Value)
tassert.Equal(t, "orange", g.Objects[0].Attributes.Style.Fill.Value)
tassert.Equal(t, "red", g.Objects[1].Attributes.Style.Fill.Value)
tassert.Equal(t, "4", g.Edges[0].Attributes.Style.StrokeWidth.Value)
tassert.Equal(t, "then", g.Edges[0].Attributes.Label.Value)
},
},
{
name: "reordered-classes",
text: `classes: {
x: {
shape: circle
}
}
a.class: x
classes.x.shape: diamond
`,
assertions: func(t *testing.T, g *d2graph.Graph) {
tassert.Equal(t, 1, len(g.Objects))
tassert.Equal(t, "diamond", g.Objects[0].Attributes.Shape.Value)
},
},
{
name: "no-class-primary",
text: `x.class
`,
expErr: `d2/testdata/d2compiler/TestCompile/no-class-primary.d2:1:3: class missing value`,
},
{
name: "no-class-inside-classes",
text: `classes: {
x: {
class: y
}
}
`,
expErr: `d2/testdata/d2compiler/TestCompile/no-class-inside-classes.d2:3:5: "class" cannot appear within "classes"`,
},
{
// This is okay
name: "missing-class",
text: `x.class: yo
`,
},
{
name: "classes-unreserved",
text: `classes: {
mango: {
seed
}
}
`,
expErr: `d2/testdata/d2compiler/TestCompile/classes-unreserved.d2:3:5: seed is an invalid class field, must be reserved keyword`,
},
{
name: "classes-internal-edge",
text: `classes: {
mango: {
width: 100
}
jango: {
height: 100
}
mango -> jango
}
`,
expErr: `d2/testdata/d2compiler/TestCompile/classes-internal-edge.d2:8:3: classes cannot contain an edge`,
},
} }
for _, tc := range testCases { for _, tc := range testCases {
@ -2404,6 +2550,19 @@ layers: {
assert.False(t, g.Layers[1].Scenarios[1].IsFolderOnly) assert.False(t, g.Layers[1].Scenarios[1].IsFolderOnly)
}, },
}, },
{
name: "scenarios_edge_index",
run: func(t *testing.T) {
assertCompile(t, `a -> x
scenarios: {
1: {
(a -> x)[0].style.opacity: 0.1
}
}
`, "")
},
},
{ {
name: "errs/duplicate_board", name: "errs/duplicate_board",
run: func(t *testing.T) { run: func(t *testing.T) {

View file

@ -129,6 +129,7 @@ func toShape(obj *d2graph.Object, theme *d2themes.Theme) d2target.Shape {
shape := d2target.BaseShape() shape := d2target.BaseShape()
shape.SetType(obj.Attributes.Shape.Value) shape.SetType(obj.Attributes.Shape.Value)
shape.ID = obj.AbsID() shape.ID = obj.AbsID()
shape.Classes = obj.Attributes.Classes
shape.ZIndex = obj.ZIndex shape.ZIndex = obj.ZIndex
shape.Level = int(obj.Level()) shape.Level = int(obj.Level())
shape.Pos = d2target.NewPoint(int(obj.TopLeft.X), int(obj.TopLeft.Y)) shape.Pos = d2target.NewPoint(int(obj.TopLeft.X), int(obj.TopLeft.Y))
@ -194,6 +195,7 @@ func toShape(obj *d2graph.Object, theme *d2themes.Theme) d2target.Shape {
func toConnection(edge *d2graph.Edge, theme *d2themes.Theme) d2target.Connection { func toConnection(edge *d2graph.Edge, theme *d2themes.Theme) d2target.Connection {
connection := d2target.BaseConnection() connection := d2target.BaseConnection()
connection.ID = edge.AbsID() connection.ID = edge.AbsID()
connection.Classes = edge.Attributes.Classes
connection.ZIndex = edge.ZIndex connection.ZIndex = edge.ZIndex
text := edge.Text() text := edge.Text()

View file

@ -16,6 +16,7 @@ import (
"oss.terrastruct.com/d2/d2compiler" "oss.terrastruct.com/d2/d2compiler"
"oss.terrastruct.com/d2/d2exporter" "oss.terrastruct.com/d2/d2exporter"
"oss.terrastruct.com/d2/d2layouts/d2dagrelayout" "oss.terrastruct.com/d2/d2layouts/d2dagrelayout"
"oss.terrastruct.com/d2/d2layouts/d2grid"
"oss.terrastruct.com/d2/d2layouts/d2sequence" "oss.terrastruct.com/d2/d2layouts/d2sequence"
"oss.terrastruct.com/d2/d2target" "oss.terrastruct.com/d2/d2target"
"oss.terrastruct.com/d2/lib/geo" "oss.terrastruct.com/d2/lib/geo"
@ -231,7 +232,7 @@ func run(t *testing.T, tc testCase) {
err = g.SetDimensions(nil, ruler, nil) err = g.SetDimensions(nil, ruler, nil)
assert.JSON(t, nil, err) assert.JSON(t, nil, err)
err = d2sequence.Layout(ctx, g, d2dagrelayout.DefaultLayout) err = d2sequence.Layout(ctx, g, d2grid.Layout(ctx, g, d2dagrelayout.DefaultLayout))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -1,6 +1,7 @@
package d2graph package d2graph
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"math" "math"
@ -67,6 +68,8 @@ func (g *Graph) RootBoard() *Graph {
return g return g
} }
type LayoutGraph func(context.Context, *Graph) error
// TODO consider having different Scalar types // TODO consider having different Scalar types
// Right now we'll hold any types in Value and just convert, e.g. floats // Right now we'll hold any types in Value and just convert, e.g. floats
type Scalar struct { type Scalar struct {
@ -129,6 +132,13 @@ type Attributes struct {
Direction Scalar `json:"direction"` Direction Scalar `json:"direction"`
Constraint Scalar `json:"constraint"` Constraint Scalar `json:"constraint"`
GridRows *Scalar `json:"gridRows,omitempty"`
GridColumns *Scalar `json:"gridColumns,omitempty"`
// These names are attached to the rendered elements in SVG
// so that users can target them however they like outside of D2
Classes []string `json:"classes,omitempty"`
} }
// TODO references at the root scope should have their Scope set to root graph AST // TODO references at the root scope should have their Scope set to root graph AST
@ -968,6 +978,16 @@ func (obj *Object) GetDefaultSize(mtexts []*d2target.MText, ruler *textmeasure.R
return &dims, nil return &dims, nil
} }
func (obj *Object) OuterNearContainer() *Object {
for obj != nil {
if obj.Attributes.NearKey != nil {
return obj
}
obj = obj.Parent
}
return nil
}
type Edge struct { type Edge struct {
Index int `json:"index"` Index int `json:"index"`
@ -1007,6 +1027,10 @@ type EdgeReference struct {
ScopeObj *Object `json:"-"` ScopeObj *Object `json:"-"`
} }
func (e *Edge) GetAstEdge() *d2ast.Edge {
return e.References[0].Edge
}
func (e *Edge) GetStroke(dashGapSize interface{}) string { func (e *Edge) GetStroke(dashGapSize interface{}) string {
if dashGapSize != 0.0 { if dashGapSize != 0.0 {
return color.B2 return color.B2
@ -1534,6 +1558,10 @@ var SimpleReservedKeywords = map[string]struct{}{
"direction": {}, "direction": {},
"top": {}, "top": {},
"left": {}, "left": {},
"grid-rows": {},
"grid-columns": {},
"class": {},
"classes": {},
} }
// ReservedKeywordHolders are reserved keywords that are meaningless on its own and exist solely to hold a set of reserved keywords // ReservedKeywordHolders are reserved keywords that are meaningless on its own and exist solely to hold a set of reserved keywords

16
d2graph/grid_diagram.go Normal file
View file

@ -0,0 +1,16 @@
package d2graph
func (obj *Object) IsGridDiagram() bool {
return obj != nil && obj.Attributes != nil &&
(obj.Attributes.GridRows != nil || obj.Attributes.GridColumns != nil)
}
func (obj *Object) ClosestGridDiagram() *Object {
if obj == nil {
return nil
}
if obj.IsGridDiagram() {
return obj
}
return obj.Parent.ClosestGridDiagram()
}

View file

@ -22,62 +22,58 @@ func Compile(ast *d2ast.Map) (*Map, error) {
m.initRoot() m.initRoot()
m.parent.(*Field).References[0].Context.Scope = ast m.parent.(*Field).References[0].Context.Scope = ast
c.compileMap(m, ast) c.compileMap(m, ast)
c.compileScenarios(m) c.compileClasses(m)
c.compileSteps(m)
if !c.err.Empty() { if !c.err.Empty() {
return nil, c.err return nil, c.err
} }
return m, nil return m, nil
} }
func (c *compiler) compileScenarios(m *Map) { func (c *compiler) compileClasses(m *Map) {
scenariosf := m.GetField("scenarios") classes := m.GetField("classes")
if scenariosf == nil { if classes == nil || classes.Map() == nil {
return
}
scenarios := scenariosf.Map()
if scenarios == nil {
return return
} }
for _, sf := range scenarios.Fields { layersField := m.GetField("layers")
if sf.Map() == nil || sf.Primary() != nil { if layersField == nil {
c.errorf(sf.References[0].Context.Key, "invalid scenario") return
}
layers := layersField.Map()
if layers == nil {
return
}
for _, lf := range layers.Fields {
if lf.Map() == nil || lf.Primary() != nil {
c.errorf(lf.References[0].Context.Key, "invalid layer")
continue continue
} }
base := m.CopyBase(sf) l := lf.Map()
OverlayMap(base, sf.Map()) lClasses := l.GetField("classes")
sf.Composite = base
c.compileScenarios(sf.Map()) if lClasses == nil {
c.compileSteps(sf.Map()) lClasses = classes.Copy(l).(*Field)
l.Fields = append(l.Fields, lClasses)
} else {
base := classes.Copy(l).(*Field)
OverlayMap(base.Map(), lClasses.Map())
l.DeleteField("classes")
l.Fields = append(l.Fields, base)
}
c.compileClasses(l)
} }
} }
func (c *compiler) compileSteps(m *Map) { func (c *compiler) overlay(base *Map, f *Field) {
stepsf := m.GetField("steps") if f.Map() == nil || f.Primary() != nil {
if stepsf == nil { c.errorf(f.References[0].Context.Key, "invalid %s", NodeBoardKind(f))
return return
} }
steps := stepsf.Map() base = base.CopyBase(f)
if steps == nil { OverlayMap(base, f.Map())
return f.Composite = base
}
for i, sf := range steps.Fields {
if sf.Map() == nil || sf.Primary() != nil {
c.errorf(sf.References[0].Context.Key, "invalid step")
break
}
var base *Map
if i == 0 {
base = m.CopyBase(sf)
} else {
base = steps.Fields[i-1].Map().CopyBase(sf)
}
OverlayMap(base, sf.Map())
sf.Composite = base
c.compileScenarios(sf.Map())
c.compileSteps(sf.Map())
}
} }
func (c *compiler) compileMap(dst *Map, ast *d2ast.Map) { func (c *compiler) compileMap(dst *Map, ast *d2ast.Map) {
@ -128,7 +124,27 @@ func (c *compiler) compileField(dst *Map, kp *d2ast.KeyPath, refctx *RefContext)
parent: f, parent: f,
} }
} }
switch NodeBoardKind(f) {
case BoardScenario:
c.overlay(ParentBoard(f).Map(), f)
case BoardStep:
stepsMap := ParentMap(f)
for i := range stepsMap.Fields {
if stepsMap.Fields[i] == f {
if i == 0 {
c.overlay(ParentBoard(f).Map(), f)
} else {
c.overlay(stepsMap.Fields[i-1].Map(), f)
}
break
}
}
}
c.compileMap(f.Map(), refctx.Key.Value.Map) c.compileMap(f.Map(), refctx.Key.Value.Map)
switch NodeBoardKind(f) {
case BoardScenario, BoardStep:
c.compileClasses(f.Map())
}
} else if refctx.Key.Value.ScalarBox().Unbox() != nil { } else if refctx.Key.Value.ScalarBox().Unbox() != nil {
// If the link is a board, we need to transform it into an absolute path. // If the link is a board, we need to transform it into an absolute path.
if f.Name == "link" { if f.Name == "link" {

View file

@ -19,6 +19,7 @@ func TestCompile(t *testing.T) {
t.Parallel() t.Parallel()
t.Run("fields", testCompileFields) t.Run("fields", testCompileFields)
t.Run("classes", testCompileClasses)
t.Run("edges", testCompileEdges) t.Run("edges", testCompileEdges)
t.Run("layers", testCompileLayers) t.Run("layers", testCompileLayers)
t.Run("scenarios", testCompileScenarios) t.Run("scenarios", testCompileScenarios)
@ -101,10 +102,12 @@ func makeScalar(v interface{}) *d2ir.Scalar {
bv := &big.Rat{} bv := &big.Rat{}
bv.SetFloat64(v) bv.SetFloat64(v)
s.Value = &d2ast.Number{ s.Value = &d2ast.Number{
Raw: fmt.Sprint(v),
Value: bv, Value: bv,
} }
case int: case int:
s.Value = &d2ast.Number{ s.Value = &d2ast.Number{
Raw: fmt.Sprint(v),
Value: big.NewRat(int64(v), 1), Value: big.NewRat(int64(v), 1),
} }
case string: case string:
@ -379,6 +382,20 @@ scenarios: {
assertQuery(t, m, 0, 0, nil, "scenarios.nuclear.quiche") assertQuery(t, m, 0, 0, nil, "scenarios.nuclear.quiche")
}, },
}, },
{
name: "edge",
run: func(t testing.TB) {
m, err := compile(t, `a -> b
scenarios: {
1: {
(a -> b)[0].style.opacity: 0.1
}
}`)
assert.Success(t, err)
assertQuery(t, m, 0, 0, nil, "(a -> b)[0]")
},
},
} }
runa(t, tca) runa(t, tca)
} }
@ -431,9 +448,8 @@ scenarios: {
shape: sql_table shape: sql_table
hey: int {constraint: primary_key} hey: int {constraint: primary_key}
}`) }`)
assert.ErrorString(t, err, `TestCompile/steps/steps_panic.d2:6:3: invalid scenario assert.ErrorString(t, err, `TestCompile/steps/steps_panic.d2:3:3: invalid step
TestCompile/steps/steps_panic.d2:7:3: invalid scenario TestCompile/steps/steps_panic.d2:7:3: invalid scenario`)
TestCompile/steps/steps_panic.d2:2:3: invalid step`)
}, },
}, },
{ {
@ -490,3 +506,154 @@ steps: {
} }
runa(t, tca) runa(t, tca)
} }
func testCompileClasses(t *testing.T) {
t.Parallel()
tca := []testCase{
{
name: "basic",
run: func(t testing.TB) {
_, err := compile(t, `x
classes: {
mango: {
style.fill: orange
}
}
`)
assert.Success(t, err)
},
},
{
name: "nonroot",
run: func(t testing.TB) {
_, err := compile(t, `x: {
classes: {
mango: {
style.fill: orange
}
}
}
`)
assert.ErrorString(t, err, `TestCompile/classes/nonroot.d2:2:3: classes is only allowed at a board root`)
},
},
{
name: "merge",
run: func(t testing.TB) {
m, err := compile(t, `classes: {
mango: {
style.fill: orange
width: 10
}
}
layers: {
hawaii: {
classes: {
mango: {
width: 9000
}
}
}
}
`)
assert.Success(t, err)
assertQuery(t, m, 3, 0, nil, "layers.hawaii.classes.mango")
assertQuery(t, m, 0, 0, "orange", "layers.hawaii.classes.mango.style.fill")
assertQuery(t, m, 0, 0, 9000, "layers.hawaii.classes.mango.width")
},
},
{
name: "nested",
run: func(t testing.TB) {
m, err := compile(t, `classes: {
mango: {
style.fill: orange
}
}
layers: {
hawaii: {
layers: {
maui: {
x
}
}
}
}
`)
assert.Success(t, err)
assertQuery(t, m, 3, 0, nil, "layers.hawaii.classes")
assertQuery(t, m, 3, 0, nil, "layers.hawaii.layers.maui.classes")
},
},
{
name: "inherited",
run: func(t testing.TB) {
m, err := compile(t, `classes: {
mango: {
style.fill: orange
}
}
scenarios: {
hawaii: {
steps: {
1: {
classes: {
cherry: {
style.fill: red
}
}
x
}
2: {
y
}
3: {
classes: {
cherry: {
style.fill: blue
}
}
y
}
4: {
layers: {
deep: {
x
}
}
x
}
}
}
}
`)
assert.Success(t, err)
assertQuery(t, m, 3, 0, nil, "scenarios.hawaii.classes")
assertQuery(t, m, 2, 0, nil, "scenarios.hawaii.steps.2.classes.mango")
assertQuery(t, m, 2, 0, nil, "scenarios.hawaii.steps.2.classes.cherry")
assertQuery(t, m, 0, 0, "blue", "scenarios.hawaii.steps.4.classes.cherry.style.fill")
assertQuery(t, m, 0, 0, "blue", "scenarios.hawaii.steps.4.layers.deep.classes.cherry.style.fill")
},
},
{
name: "layer-modify",
run: func(t testing.TB) {
m, err := compile(t, `classes: {
orb: {
style.fill: yellow
}
}
layers: {
x: {
classes.orb.style.stroke: red
}
}
`)
assert.Success(t, err)
assertQuery(t, m, 0, 0, "yellow", "layers.x.classes.orb.style.fill")
assertQuery(t, m, 0, 0, "red", "layers.x.classes.orb.style.stroke")
},
},
}
runa(t, tca)
}

View file

@ -601,6 +601,18 @@ func (m *Map) EdgeCountRecursive() int {
return acc return acc
} }
func (m *Map) GetClassMap(name string) *Map {
root := RootMap(m)
classes := root.Map().GetField("classes")
if classes != nil && classes.Map() != nil {
class := classes.Map().GetField(name)
if class != nil && class.Map() != nil {
return class.Map()
}
}
return nil
}
func (m *Map) GetField(ida ...string) *Field { func (m *Map) GetField(ida ...string) *Field {
for len(ida) > 0 && ida[0] == "_" { for len(ida) > 0 && ida[0] == "_" {
m = ParentMap(m) m = ParentMap(m)
@ -663,6 +675,10 @@ func (m *Map) ensureField(i int, kp *d2ast.KeyPath, refctx *RefContext) (*Field,
return nil, d2parser.Errorf(kp.Path[i].Unbox(), `parent "_" can only be used in the beginning of paths, e.g. "_.x"`) return nil, d2parser.Errorf(kp.Path[i].Unbox(), `parent "_" can only be used in the beginning of paths, e.g. "_.x"`)
} }
if head == "classes" && NodeBoardKind(m) == "" {
return nil, d2parser.Errorf(kp.Path[i].Unbox(), "%s is only allowed at a board root", head)
}
if findBoardKeyword(head) != -1 && NodeBoardKind(m) == "" { if findBoardKeyword(head) != -1 && NodeBoardKind(m) == "" {
return nil, d2parser.Errorf(kp.Path[i].Unbox(), "%s is only allowed at a board root", head) return nil, d2parser.Errorf(kp.Path[i].Unbox(), "%s is only allowed at a board root", head)
} }
@ -935,6 +951,13 @@ func (m *Map) appendFieldReferences(i int, kp *d2ast.KeyPath, refctx *RefContext
} }
} }
func RootMap(m *Map) *Map {
if m.Root() {
return m
}
return RootMap(ParentMap(m))
}
func ParentMap(n Node) *Map { func ParentMap(n Node) *Map {
for { for {
n = n.Parent() n = n.Parent()

View file

@ -33,6 +33,7 @@ var dagreJS string
const ( const (
MIN_SEGMENT_LEN = 10 MIN_SEGMENT_LEN = 10
MIN_RANK_SEP = 60 MIN_RANK_SEP = 60
EDGE_LABEL_GAP = 20
) )
type ConfigurableOpts struct { type ConfigurableOpts struct {
@ -173,37 +174,30 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err
} }
} }
for _, edge := range g.Edges { for _, edge := range g.Edges {
// dagre doesn't work with edges to containers so we connect container edges to their first child instead (going all the way down) src, dst := getEdgeEndpoints(g, edge)
// we will chop the edge where it intersects the container border so it only shows the edge from the container
src := edge.Src
for len(src.Children) > 0 && src.Class == nil && src.SQLTable == nil {
// We want to get the bottom node of sources, setting its rank higher than all children
src = getLongestEdgeChainTail(g, src)
}
dst := edge.Dst
for len(dst.Children) > 0 && dst.Class == nil && dst.SQLTable == nil {
dst = dst.ChildrenArray[0]
// We want to get the top node of destinations width := edge.LabelDimensions.Width
for _, child := range dst.ChildrenArray { height := edge.LabelDimensions.Height
isHead := true
numEdges := 0
for _, e := range g.Edges { for _, e := range g.Edges {
if inContainer(e.Src, child) != nil && inContainer(e.Dst, dst) != nil { otherSrc, otherDst := getEdgeEndpoints(g, e)
isHead = false if (otherSrc == src && otherDst == dst) || (otherSrc == dst && otherDst == src) {
break numEdges++
} }
} }
if isHead {
dst = child // We want to leave some gap between multiple edges
break if numEdges > 1 {
switch g.Root.Attributes.Direction.Value {
case "down", "up", "":
width += EDGE_LABEL_GAP
case "left", "right":
height += EDGE_LABEL_GAP
} }
} }
}
if edge.SrcArrow && !edge.DstArrow { loadScript += generateAddEdgeLine(src.AbsID(), dst.AbsID(), edge.AbsID(), width, height)
// for `b <- a`, edge.Edge is `a -> b` and we expect this routing result
src, dst = dst, src
}
loadScript += generateAddEdgeLine(src.AbsID(), dst.AbsID(), edge.AbsID(), edge.LabelDimensions.Width, edge.LabelDimensions.Height)
} }
if debugJS { if debugJS {
@ -528,6 +522,40 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err
return nil return nil
} }
func getEdgeEndpoints(g *d2graph.Graph, edge *d2graph.Edge) (*d2graph.Object, *d2graph.Object) {
// dagre doesn't work with edges to containers so we connect container edges to their first child instead (going all the way down)
// we will chop the edge where it intersects the container border so it only shows the edge from the container
src := edge.Src
for len(src.Children) > 0 && src.Class == nil && src.SQLTable == nil {
// We want to get the bottom node of sources, setting its rank higher than all children
src = getLongestEdgeChainTail(g, src)
}
dst := edge.Dst
for len(dst.Children) > 0 && dst.Class == nil && dst.SQLTable == nil {
dst = dst.ChildrenArray[0]
// 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 {
// for `b <- a`, edge.Edge is `a -> b` and we expect this routing result
src, dst = dst, src
}
return src, dst
}
func setGraphAttrs(attrs dagreOpts) string { func setGraphAttrs(attrs dagreOpts) string {
return fmt.Sprintf(`g.setGraph({ return fmt.Sprintf(`g.setGraph({
ranksep: %d, ranksep: %d,

View file

@ -0,0 +1,87 @@
package d2grid
import (
"strconv"
"strings"
"oss.terrastruct.com/d2/d2graph"
)
type gridDiagram struct {
root *d2graph.Object
objects []*d2graph.Object
rows int
columns int
// if true, place objects left to right along rows
// if false, place objects top to bottom along columns
rowDirected bool
width float64
height float64
}
func newGridDiagram(root *d2graph.Object) *gridDiagram {
gd := gridDiagram{root: root, objects: root.ChildrenArray}
if root.Attributes.GridRows != nil {
gd.rows, _ = strconv.Atoi(root.Attributes.GridRows.Value)
}
if root.Attributes.GridColumns != nil {
gd.columns, _ = strconv.Atoi(root.Attributes.GridColumns.Value)
}
if gd.rows != 0 && gd.columns != 0 {
// . row-directed column-directed
// . ┌───────┐ ┌───────┐
// . │ a b c │ │ a d g │
// . │ d e f │ │ b e h │
// . │ g h i │ │ c f i │
// . └───────┘ └───────┘
// if keyword rows is first, make it row-directed, if columns is first it is column-directed
if root.Attributes.GridRows.MapKey.Range.Before(root.Attributes.GridColumns.MapKey.Range) {
gd.rowDirected = true
}
// rows and columns specified, but we want to continue naturally if user enters more objects
// e.g. 2 rows, 3 columns specified + g added: │ with 3 columns, 2 rows:
// . original add row add column │ original add row add column
// . ┌───────┐ ┌───────┐ ┌─────────┐ │ ┌───────┐ ┌───────┐ ┌─────────┐
// . │ a b c │ │ a b c │ │ a b c d │ │ │ a c e │ │ a d g │ │ a c e g │
// . │ d e f │ │ d e f │ │ e f g │ │ │ b d f │ │ b e │ │ b d f │
// . └───────┘ │ g │ └─────────┘ │ └───────┘ │ c f │ └─────────┘
// . └───────┘ ▲ │ └───────┘ ▲
// . ▲ └─existing objects modified│ ▲ └─existing columns preserved
// . └─existing rows preserved │ └─existing objects modified
capacity := gd.rows * gd.columns
for capacity < len(gd.objects) {
if gd.rowDirected {
gd.rows++
capacity += gd.columns
} else {
gd.columns++
capacity += gd.rows
}
}
} else if gd.columns == 0 {
gd.rowDirected = true
}
return &gd
}
func (gd *gridDiagram) shift(dx, dy float64) {
for _, obj := range gd.objects {
obj.TopLeft.X += dx
obj.TopLeft.Y += dy
}
}
func (gd *gridDiagram) cleanup(obj *d2graph.Object, graph *d2graph.Graph) {
obj.Children = make(map[string]*d2graph.Object)
obj.ChildrenArray = make([]*d2graph.Object, 0)
for _, child := range gd.objects {
obj.Children[strings.ToLower(child.ID)] = child
obj.ChildrenArray = append(obj.ChildrenArray, child)
}
graph.Objects = append(graph.Objects, gd.objects...)
}

578
d2layouts/d2grid/layout.go Normal file
View file

@ -0,0 +1,578 @@
package d2grid
import (
"context"
"math"
"sort"
"oss.terrastruct.com/d2/d2graph"
"oss.terrastruct.com/d2/lib/geo"
"oss.terrastruct.com/d2/lib/label"
"oss.terrastruct.com/util-go/go2"
)
const (
CONTAINER_PADDING = 60
HORIZONTAL_PAD = 40.
VERTICAL_PAD = 40.
)
// Layout runs the grid layout on containers with rows/columns
// Note: children are not allowed edges or descendants
//
// 1. Traverse graph from root, skip objects with no rows/columns
// 2. Construct a grid with the container children
// 3. Remove the children from the main graph
// 4. Run grid layout
// 5. Set the resulting dimensions to the main graph shape
// 6. Run core layouts (without grid children)
// 7. Put grid children back in correct location
func Layout(ctx context.Context, g *d2graph.Graph, layout d2graph.LayoutGraph) d2graph.LayoutGraph {
return func(ctx context.Context, g *d2graph.Graph) error {
gridDiagrams, objectOrder, err := withoutGridDiagrams(ctx, g)
if err != nil {
return err
}
if g.Root.IsGridDiagram() && len(g.Root.ChildrenArray) != 0 {
g.Root.TopLeft = geo.NewPoint(0, 0)
} else if err := layout(ctx, g); err != nil {
return err
}
cleanup(g, gridDiagrams, objectOrder)
return nil
}
}
func withoutGridDiagrams(ctx context.Context, g *d2graph.Graph) (gridDiagrams map[string]*gridDiagram, objectOrder map[string]int, err error) {
toRemove := make(map[*d2graph.Object]struct{})
gridDiagrams = make(map[string]*gridDiagram)
if len(g.Objects) > 0 {
queue := make([]*d2graph.Object, 1, len(g.Objects))
queue[0] = g.Root
for len(queue) > 0 {
obj := queue[0]
queue = queue[1:]
if len(obj.ChildrenArray) == 0 {
continue
}
if !obj.IsGridDiagram() {
queue = append(queue, obj.ChildrenArray...)
continue
}
gd, err := layoutGrid(g, obj)
if err != nil {
return nil, nil, err
}
obj.Children = make(map[string]*d2graph.Object)
obj.ChildrenArray = nil
var dx, dy float64
width := gd.width + 2*CONTAINER_PADDING
labelWidth := float64(obj.LabelDimensions.Width) + 2*label.PADDING
if labelWidth > width {
dx = (labelWidth - width) / 2
width = labelWidth
}
height := gd.height + 2*CONTAINER_PADDING
labelHeight := float64(obj.LabelDimensions.Height) + 2*label.PADDING
if labelHeight > CONTAINER_PADDING {
// if the label doesn't fit within the padding, we need to add more
grow := labelHeight - CONTAINER_PADDING
dy = grow / 2
height += grow
}
// we need to center children if we have to expand to fit the container label
if dx != 0 || dy != 0 {
gd.shift(dx, dy)
}
obj.Box = geo.NewBox(nil, width, height)
obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter))
gridDiagrams[obj.AbsID()] = gd
for _, o := range gd.objects {
toRemove[o] = struct{}{}
}
}
}
objectOrder = make(map[string]int)
layoutObjects := make([]*d2graph.Object, 0, len(toRemove))
for i, obj := range g.Objects {
objectOrder[obj.AbsID()] = i
if _, exists := toRemove[obj]; !exists {
layoutObjects = append(layoutObjects, obj)
}
}
g.Objects = layoutObjects
return gridDiagrams, objectOrder, nil
}
func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*gridDiagram, error) {
gd := newGridDiagram(obj)
if gd.rows != 0 && gd.columns != 0 {
gd.layoutEvenly(g, obj)
} else {
gd.layoutDynamic(g, obj)
}
// position labels and icons
for _, o := range gd.objects {
if o.Attributes.Icon != nil {
o.LabelPosition = go2.Pointer(string(label.InsideTopCenter))
o.IconPosition = go2.Pointer(string(label.InsideMiddleCenter))
} else {
o.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter))
}
}
return gd, nil
}
func (gd *gridDiagram) layoutEvenly(g *d2graph.Graph, obj *d2graph.Object) {
// layout objects in a grid with these 2 properties:
// all objects in the same row should have the same height
// all objects in the same column should have the same width
getObject := func(rowIndex, columnIndex int) *d2graph.Object {
var index int
if gd.rowDirected {
index = rowIndex*gd.columns + columnIndex
} else {
index = columnIndex*gd.rows + rowIndex
}
if index < len(gd.objects) {
return gd.objects[index]
}
return nil
}
rowHeights := make([]float64, 0, gd.rows)
colWidths := make([]float64, 0, gd.columns)
for i := 0; i < gd.rows; i++ {
rowHeight := 0.
for j := 0; j < gd.columns; j++ {
o := getObject(i, j)
if o == nil {
break
}
rowHeight = math.Max(rowHeight, o.Height)
}
rowHeights = append(rowHeights, rowHeight)
}
for j := 0; j < gd.columns; j++ {
columnWidth := 0.
for i := 0; i < gd.rows; i++ {
o := getObject(i, j)
if o == nil {
break
}
columnWidth = math.Max(columnWidth, o.Width)
}
colWidths = append(colWidths, columnWidth)
}
cursor := geo.NewPoint(0, 0)
if gd.rowDirected {
for i := 0; i < gd.rows; i++ {
for j := 0; j < gd.columns; j++ {
o := getObject(i, j)
if o == nil {
break
}
o.Width = colWidths[j]
o.Height = rowHeights[i]
o.TopLeft = cursor.Copy()
cursor.X += o.Width + HORIZONTAL_PAD
}
cursor.X = 0
cursor.Y += rowHeights[i] + VERTICAL_PAD
}
} else {
for j := 0; j < gd.columns; j++ {
for i := 0; i < gd.rows; i++ {
o := getObject(i, j)
if o == nil {
break
}
o.Width = colWidths[j]
o.Height = rowHeights[i]
o.TopLeft = cursor.Copy()
cursor.Y += o.Height + VERTICAL_PAD
}
cursor.X += colWidths[j] + HORIZONTAL_PAD
cursor.Y = 0
}
}
var totalWidth, totalHeight float64
for _, w := range colWidths {
totalWidth += w + HORIZONTAL_PAD
}
for _, h := range rowHeights {
totalHeight += h + VERTICAL_PAD
}
totalWidth -= HORIZONTAL_PAD
totalHeight -= VERTICAL_PAD
gd.width = totalWidth
gd.height = totalHeight
}
func (gd *gridDiagram) layoutDynamic(g *d2graph.Graph, obj *d2graph.Object) {
// assume we have the following objects to layout:
// . ┌A──────────────┐ ┌B──┐ ┌C─────────┐ ┌D────────┐ ┌E────────────────┐
// . └───────────────┘ │ │ │ │ │ │ │ │
// . │ │ └──────────┘ │ │ │ │
// . │ │ │ │ └─────────────────┘
// . └───┘ │ │
// . └─────────┘
// Note: if the grid is row dominant, all objects should be the same height (same width if column dominant)
// . ┌A─────────────┐ ┌B──┐ ┌C─────────┐ ┌D────────┐ ┌E────────────────┐
// . ├ ─ ─ ─ ─ ─ ─ ─┤ │ │ │ │ │ │ │ │
// . │ │ │ │ ├ ─ ─ ─ ─ ─┤ │ │ │ │
// . │ │ │ │ │ │ │ │ ├ ─ ─ ─ ─ ─ ─ ─ ─ ┤
// . │ │ ├ ─ ┤ │ │ │ │ │ │
// . └──────────────┘ └───┘ └──────────┘ └─────────┘ └─────────────────┘
// we want to split up the total width across the N rows or columns as evenly as possible
var totalWidth, totalHeight float64
for _, o := range gd.objects {
totalWidth += o.Width
totalHeight += o.Height
}
totalWidth += HORIZONTAL_PAD * float64(len(gd.objects)-gd.rows)
totalHeight += VERTICAL_PAD * float64(len(gd.objects)-gd.columns)
var layout [][]*d2graph.Object
if gd.rowDirected {
targetWidth := totalWidth / float64(gd.rows)
layout = gd.getBestLayout(targetWidth, false)
} else {
targetHeight := totalHeight / float64(gd.columns)
layout = gd.getBestLayout(targetHeight, true)
}
cursor := geo.NewPoint(0, 0)
var maxY, maxX float64
if gd.rowDirected {
// if we have 2 rows, then each row's objects should have the same height
// . ┌A─────────────┐ ┌B──┐ ┌C─────────┐ ┬ maxHeight(A,B,C)
// . ├ ─ ─ ─ ─ ─ ─ ─┤ │ │ │ │ │
// . │ │ │ │ ├ ─ ─ ─ ─ ─┤ │
// . │ │ │ │ │ │ │
// . └──────────────┘ └───┘ └──────────┘ ┴
// . ┌D────────┐ ┌E────────────────┐ ┬ maxHeight(D,E)
// . │ │ │ │ │
// . │ │ │ │ │
// . │ │ ├ ─ ─ ─ ─ ─ ─ ─ ─ ┤ │
// . │ │ │ │ │
// . └─────────┘ └─────────────────┘ ┴
rowWidths := []float64{}
for _, row := range layout {
rowHeight := 0.
for _, o := range row {
o.TopLeft = cursor.Copy()
cursor.X += o.Width + HORIZONTAL_PAD
rowHeight = math.Max(rowHeight, o.Height)
}
rowWidth := cursor.X - HORIZONTAL_PAD
rowWidths = append(rowWidths, rowWidth)
maxX = math.Max(maxX, rowWidth)
// set all objects in row to the same height
for _, o := range row {
o.Height = rowHeight
}
// new row
cursor.X = 0
cursor.Y += rowHeight + VERTICAL_PAD
}
maxY = cursor.Y - VERTICAL_PAD
// then expand thinnest objects to make each row the same width
// . ┌A─────────────┐ ┌B──┐ ┌C─────────┐ ┬ maxHeight(A,B,C)
// . │ │ │ │ │ │ │
// . │ │ │ │ │ │ │
// . │ │ │ │ │ │ │
// . └──────────────┘ └───┘ └──────────┘ ┴
// . ┌D────────┬────┐ ┌E────────────────┐ ┬ maxHeight(D,E)
// . │ │ │ │ │
// . │ │ │ │ │ │
// . │ │ │ │ │
// . │ │ │ │ │ │
// . └─────────┴────┘ └─────────────────┘ ┴
for i, row := range layout {
rowWidth := rowWidths[i]
if rowWidth == maxX {
continue
}
delta := maxX - rowWidth
objects := []*d2graph.Object{}
var widest float64
for _, o := range row {
widest = math.Max(widest, o.Width)
objects = append(objects, o)
}
sort.Slice(objects, func(i, j int) bool {
return objects[i].Width < objects[j].Width
})
// expand smaller objects to fill remaining space
for _, o := range objects {
if o.Width < widest {
var index int
for i, rowObj := range row {
if o == rowObj {
index = i
break
}
}
grow := math.Min(widest-o.Width, delta)
o.Width += grow
// shift following objects
for i := index + 1; i < len(row); i++ {
row[i].TopLeft.X += grow
}
delta -= grow
if delta <= 0 {
break
}
}
}
if delta > 0 {
grow := delta / float64(len(row))
for i := len(row) - 1; i >= 0; i-- {
o := row[i]
o.TopLeft.X += grow * float64(i)
o.Width += grow
delta -= grow
}
}
}
} else {
// if we have 3 columns, then each column's objects should have the same width
// . ├maxWidth(A,B)─┤ ├maxW(C,D)─┤ ├maxWidth(E)──────┤
// . ┌A─────────────┐ ┌C─────────┐ ┌E────────────────┐
// . └──────────────┘ │ │ │ │
// . ┌B──┬──────────┐ └──────────┘ │ │
// . │ │ ┌D────────┬┐ └─────────────────┘
// . │ │ │ │ │
// . │ │ │ ││
// . └───┴──────────┘ │ │
// . │ ││
// . └─────────┴┘
colHeights := []float64{}
for _, column := range layout {
colWidth := 0.
for _, o := range column {
o.TopLeft = cursor.Copy()
cursor.Y += o.Height + VERTICAL_PAD
colWidth = math.Max(colWidth, o.Width)
}
colHeight := cursor.Y - VERTICAL_PAD
colHeights = append(colHeights, colHeight)
maxY = math.Max(maxY, colHeight)
// set all objects in column to the same width
for _, o := range column {
o.Width = colWidth
}
// new column
cursor.Y = 0
cursor.X += colWidth + HORIZONTAL_PAD
}
maxX = cursor.X - HORIZONTAL_PAD
// then expand shortest objects to make each column the same height
// . ├maxWidth(A,B)─┤ ├maxW(C,D)─┤ ├maxWidth(E)──────┤
// . ┌A─────────────┐ ┌C─────────┐ ┌E────────────────┐
// . ├ ─ ─ ─ ─ ─ ─ ┤ │ │ │ │
// . │ │ └──────────┘ │ │
// . └──────────────┘ ┌D─────────┐ ├ ─ ─ ─ ─ ─ ─ ─ ─ ┤
// . ┌B─────────────┐ │ │ │ │
// . │ │ │ │ │ │
// . │ │ │ │ │ │
// . │ │ │ │ │ │
// . └──────────────┘ └──────────┘ └─────────────────┘
for i, column := range layout {
colHeight := colHeights[i]
if colHeight == maxY {
continue
}
delta := maxY - colHeight
objects := []*d2graph.Object{}
var tallest float64
for _, o := range column {
tallest = math.Max(tallest, o.Height)
objects = append(objects, o)
}
sort.Slice(objects, func(i, j int) bool {
return objects[i].Height < objects[j].Height
})
// expand smaller objects to fill remaining space
for _, o := range objects {
if o.Height < tallest {
var index int
for i, colObj := range column {
if o == colObj {
index = i
break
}
}
grow := math.Min(tallest-o.Height, delta)
o.Height += grow
// shift following objects
for i := index + 1; i < len(column); i++ {
column[i].TopLeft.Y += grow
}
delta -= grow
if delta <= 0 {
break
}
}
}
if delta > 0 {
grow := delta / float64(len(column))
for i := len(column) - 1; i >= 0; i-- {
o := column[i]
o.TopLeft.Y += grow * float64(i)
o.Height += grow
delta -= grow
}
}
}
}
gd.width = maxX
gd.height = maxY
}
// generate the best layout of objects aiming for each row to be the targetSize width
// if columns is true, each column aims to have the targetSize height
func (gd *gridDiagram) getBestLayout(targetSize float64, columns bool) [][]*d2graph.Object {
var nCuts int
if columns {
nCuts = gd.columns - 1
} else {
nCuts = gd.rows - 1
}
if nCuts == 0 {
return genLayout(gd.objects, nil)
}
// get all options for where to place these cuts, preferring later cuts over earlier cuts
// with 5 objects and 2 cuts we have these options:
// . A B C │ D │ E <- these cuts would produce: ┌A─┐ ┌B─┐ ┌C─┐
// . A B │ C D │ E └──┘ └──┘ └──┘
// . A │ B C D │ E ┌D───────────┐
// . A B │ C │ D E └────────────┘
// . A │ B C │ D E ┌E───────────┐
// . A │ B │ C D E └────────────┘
divisions := genDivisions(gd.objects, nCuts)
var bestLayout [][]*d2graph.Object
bestDist := math.MaxFloat64
// of these divisions, find the layout with rows closest to the targetSize
for _, division := range divisions {
layout := genLayout(gd.objects, division)
dist := getDistToTarget(layout, targetSize, columns)
if dist < bestDist {
bestLayout = layout
bestDist = dist
}
}
return bestLayout
}
// get all possible divisions of objects by the number of cuts
func genDivisions(objects []*d2graph.Object, nCuts int) (divisions [][]int) {
if len(objects) < 2 || nCuts == 0 {
return nil
}
// we go in this order to prefer extra objects in starting rows rather than later ones
lastObj := len(objects) - 1
for index := lastObj; index >= nCuts; index-- {
if nCuts > 1 {
for _, inner := range genDivisions(objects[:index], nCuts-1) {
divisions = append(divisions, append(inner, index-1))
}
} else {
divisions = append(divisions, []int{index - 1})
}
}
return divisions
}
// generate a grid of objects from the given cut indices
func genLayout(objects []*d2graph.Object, cutIndices []int) [][]*d2graph.Object {
layout := make([][]*d2graph.Object, len(cutIndices)+1)
objIndex := 0
for i := 0; i <= len(cutIndices); i++ {
var stop int
if i < len(cutIndices) {
stop = cutIndices[i]
} else {
stop = len(objects) - 1
}
for ; objIndex <= stop; objIndex++ {
layout[i] = append(layout[i], objects[objIndex])
}
}
return layout
}
func getDistToTarget(layout [][]*d2graph.Object, targetSize float64, columns bool) float64 {
totalDelta := 0.
for _, row := range layout {
rowSize := 0.
for _, o := range row {
if columns {
rowSize += o.Height + VERTICAL_PAD
} else {
rowSize += o.Width + HORIZONTAL_PAD
}
}
totalDelta += math.Abs(rowSize - targetSize)
}
return totalDelta
}
// cleanup restores the graph after the core layout engine finishes
// - translating the grid to its position placed by the core layout engine
// - restore the children of the grid
// - sorts objects to their original graph order
func cleanup(graph *d2graph.Graph, gridDiagrams map[string]*gridDiagram, objectsOrder map[string]int) {
defer func() {
sort.SliceStable(graph.Objects, func(i, j int) bool {
return objectsOrder[graph.Objects[i].AbsID()] < objectsOrder[graph.Objects[j].AbsID()]
})
}()
if graph.Root.IsGridDiagram() {
gd, exists := gridDiagrams[graph.Root.AbsID()]
if exists {
gd.cleanup(graph.Root, graph)
return
}
}
for _, obj := range graph.Objects {
gd, exists := gridDiagrams[obj.AbsID()]
if !exists {
continue
}
obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter))
// shift the grid from (0, 0)
gd.shift(
obj.TopLeft.X+CONTAINER_PADDING,
obj.TopLeft.Y+CONTAINER_PADDING,
)
gd.cleanup(obj, graph)
}
}

View file

@ -10,47 +10,62 @@ import (
"oss.terrastruct.com/d2/d2graph" "oss.terrastruct.com/d2/d2graph"
"oss.terrastruct.com/d2/lib/geo" "oss.terrastruct.com/d2/lib/geo"
"oss.terrastruct.com/d2/lib/label" "oss.terrastruct.com/d2/lib/label"
"oss.terrastruct.com/util-go/go2"
) )
const pad = 20 const pad = 20
// Layout finds the shapes which are assigned constant near keywords and places them. // Layout finds the shapes which are assigned constant near keywords and places them.
func Layout(ctx context.Context, g *d2graph.Graph, constantNears []*d2graph.Object) error { func Layout(ctx context.Context, g *d2graph.Graph, constantNearGraphs []*d2graph.Graph) error {
if len(constantNears) == 0 { if len(constantNearGraphs) == 0 {
return nil return nil
} }
for _, tempGraph := range constantNearGraphs {
tempGraph.Root.ChildrenArray[0].Parent = g.Root
for _, obj := range tempGraph.Objects {
obj.Graph = g
}
}
// Imagine the graph has two long texts, one at top center and one at top left. // Imagine the graph has two long texts, one at top center and one at top left.
// Top left should go left enough to not collide with center. // Top left should go left enough to not collide with center.
// So place the center ones first, then the later ones will consider them for bounding box // So place the center ones first, then the later ones will consider them for bounding box
for _, processCenters := range []bool{true, false} { for _, processCenters := range []bool{true, false} {
for _, obj := range constantNears { for _, tempGraph := range constantNearGraphs {
obj := tempGraph.Root.ChildrenArray[0]
if processCenters == strings.Contains(d2graph.Key(obj.Attributes.NearKey)[0], "-center") { if processCenters == strings.Contains(d2graph.Key(obj.Attributes.NearKey)[0], "-center") {
prevX, prevY := obj.TopLeft.X, obj.TopLeft.Y
obj.TopLeft = geo.NewPoint(place(obj)) obj.TopLeft = geo.NewPoint(place(obj))
dx, dy := obj.TopLeft.X-prevX, obj.TopLeft.Y-prevY
for _, subObject := range tempGraph.Objects {
// `obj` already been replaced above by `place(obj)`
if subObject == obj {
continue
}
subObject.TopLeft.X += dx
subObject.TopLeft.Y += dy
}
for _, subEdge := range tempGraph.Edges {
for _, point := range subEdge.Route {
point.X += dx
point.Y += dy
} }
} }
for _, obj := range constantNears { }
}
for _, tempGraph := range constantNearGraphs {
obj := tempGraph.Root.ChildrenArray[0]
if processCenters == strings.Contains(d2graph.Key(obj.Attributes.NearKey)[0], "-center") { if processCenters == strings.Contains(d2graph.Key(obj.Attributes.NearKey)[0], "-center") {
// The z-index for constant nears does not matter, as it will not collide // The z-index for constant nears does not matter, as it will not collide
g.Objects = append(g.Objects, obj) g.Objects = append(g.Objects, tempGraph.Objects...)
obj.Parent.Children[obj.ID] = obj obj.Parent.Children[strings.ToLower(obj.ID)] = obj
obj.Parent.ChildrenArray = append(obj.Parent.ChildrenArray, obj) obj.Parent.ChildrenArray = append(obj.Parent.ChildrenArray, obj)
g.Edges = append(g.Edges, tempGraph.Edges...)
} }
} }
} }
// These shapes skipped core layout, which means they also skipped label placements
for _, obj := range constantNears {
if obj.HasOutsideBottomLabel() {
obj.LabelPosition = go2.Pointer(string(label.OutsideBottomCenter))
} else if obj.Attributes.Icon != nil {
obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter))
} else {
obj.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter))
}
}
return nil return nil
} }
@ -59,30 +74,66 @@ func place(obj *d2graph.Object) (float64, float64) {
tl, br := boundingBox(obj.Graph) tl, br := boundingBox(obj.Graph)
w := br.X - tl.X w := br.X - tl.X
h := br.Y - tl.Y h := br.Y - tl.Y
switch d2graph.Key(obj.Attributes.NearKey)[0] {
nearKeyStr := d2graph.Key(obj.Attributes.NearKey)[0]
var x, y float64
switch nearKeyStr {
case "top-left": case "top-left":
return tl.X - obj.Width - pad, tl.Y - obj.Height - pad x, y = tl.X-obj.Width-pad, tl.Y-obj.Height-pad
break
case "top-center": case "top-center":
return tl.X + w/2 - obj.Width/2, tl.Y - obj.Height - pad x, y = tl.X+w/2-obj.Width/2, tl.Y-obj.Height-pad
break
case "top-right": case "top-right":
return br.X + pad, tl.Y - obj.Height - pad x, y = br.X+pad, tl.Y-obj.Height-pad
break
case "center-left": case "center-left":
return tl.X - obj.Width - pad, tl.Y + h/2 - obj.Height/2 x, y = tl.X-obj.Width-pad, tl.Y+h/2-obj.Height/2
break
case "center-right": case "center-right":
return br.X + pad, tl.Y + h/2 - obj.Height/2 x, y = br.X+pad, tl.Y+h/2-obj.Height/2
break
case "bottom-left": case "bottom-left":
return tl.X - obj.Width - pad, br.Y + pad x, y = tl.X-obj.Width-pad, br.Y+pad
break
case "bottom-center": case "bottom-center":
return br.X - w/2 - obj.Width/2, br.Y + pad x, y = br.X-w/2-obj.Width/2, br.Y+pad
break
case "bottom-right": case "bottom-right":
return br.X + pad, br.Y + pad x, y = br.X+pad, br.Y+pad
break
} }
return 0, 0
if obj.LabelPosition != nil && !strings.Contains(*obj.LabelPosition, "INSIDE") {
if strings.Contains(*obj.LabelPosition, "_TOP_") {
// label is on the top, and container is placed on the bottom
if strings.Contains(nearKeyStr, "bottom") {
y += float64(*obj.LabelHeight)
}
} else if strings.Contains(*obj.LabelPosition, "_LEFT_") {
// label is on the left, and container is placed on the right
if strings.Contains(nearKeyStr, "right") {
x += float64(*obj.LabelWidth)
}
} else if strings.Contains(*obj.LabelPosition, "_RIGHT_") {
// label is on the right, and container is placed on the left
if strings.Contains(nearKeyStr, "left") {
x -= float64(*obj.LabelWidth)
}
} else if strings.Contains(*obj.LabelPosition, "_BOTTOM_") {
// label is on the bottom, and container is placed on the top
if strings.Contains(nearKeyStr, "top") {
y -= float64(*obj.LabelHeight)
}
}
}
return x, y
} }
// WithoutConstantNears plucks out the graph objects which have "near" set to a constant value // WithoutConstantNears plucks out the graph objects which have "near" set to a constant value
// This is to be called before layout engines so they don't take part in regular positioning // This is to be called before layout engines so they don't take part in regular positioning
func WithoutConstantNears(ctx context.Context, g *d2graph.Graph) (nears []*d2graph.Object) { func WithoutConstantNears(ctx context.Context, g *d2graph.Graph) (constantNearGraphs []*d2graph.Graph) {
for i := 0; i < len(g.Objects); i++ { for i := 0; i < len(g.Objects); i++ {
obj := g.Objects[i] obj := g.Objects[i]
if obj.Attributes.NearKey == nil { if obj.Attributes.NearKey == nil {
@ -94,8 +145,20 @@ func WithoutConstantNears(ctx context.Context, g *d2graph.Graph) (nears []*d2gra
} }
_, isConst := d2graph.NearConstants[d2graph.Key(obj.Attributes.NearKey)[0]] _, isConst := d2graph.NearConstants[d2graph.Key(obj.Attributes.NearKey)[0]]
if isConst { if isConst {
nears = append(nears, obj) descendantObjects, edges := pluckObjAndEdges(g, obj)
g.Objects = append(g.Objects[:i], g.Objects[i+1:]...)
tempGraph := d2graph.NewGraph()
tempGraph.Root.ChildrenArray = []*d2graph.Object{obj}
tempGraph.Root.Children[strings.ToLower(obj.ID)] = obj
for _, descendantObj := range descendantObjects {
descendantObj.Graph = tempGraph
}
tempGraph.Objects = descendantObjects
tempGraph.Edges = edges
constantNearGraphs = append(constantNearGraphs, tempGraph)
i-- i--
delete(obj.Parent.Children, strings.ToLower(obj.ID)) delete(obj.Parent.Children, strings.ToLower(obj.ID))
for i := 0; i < len(obj.Parent.ChildrenArray); i++ { for i := 0; i < len(obj.Parent.ChildrenArray); i++ {
@ -104,9 +167,38 @@ func WithoutConstantNears(ctx context.Context, g *d2graph.Graph) (nears []*d2gra
break break
} }
} }
obj.Parent = tempGraph.Root
} }
} }
return nears return constantNearGraphs
}
func pluckObjAndEdges(g *d2graph.Graph, obj *d2graph.Object) (descendantsObjects []*d2graph.Object, edges []*d2graph.Edge) {
for i := 0; i < len(g.Edges); i++ {
edge := g.Edges[i]
if edge.Src == obj || edge.Dst == obj {
edges = append(edges, edge)
g.Edges = append(g.Edges[:i], g.Edges[i+1:]...)
i--
}
}
for i := 0; i < len(g.Objects); i++ {
temp := g.Objects[i]
if temp.AbsID() == obj.AbsID() {
descendantsObjects = append(descendantsObjects, obj)
g.Objects = append(g.Objects[:i], g.Objects[i+1:]...)
for _, child := range obj.ChildrenArray {
subObjects, subEdges := pluckObjAndEdges(g, child)
descendantsObjects = append(descendantsObjects, subObjects...)
edges = append(edges, subEdges...)
}
break
}
}
return descendantsObjects, edges
} }
// boundingBox gets the center of the graph as defined by shapes // boundingBox gets the center of the graph as defined by shapes
@ -134,6 +226,9 @@ func boundingBox(g *d2graph.Graph) (tl, br *geo.Point) {
y2 = math.Max(y2, obj.TopLeft.Y+obj.Height) y2 = math.Max(y2, obj.TopLeft.Y+obj.Height)
} }
} else { } else {
if obj.OuterNearContainer() != nil {
continue
}
x1 = math.Min(x1, obj.TopLeft.X) x1 = math.Min(x1, obj.TopLeft.X)
y1 = math.Min(y1, obj.TopLeft.Y) y1 = math.Min(y1, obj.TopLeft.Y)
x2 = math.Max(x2, obj.TopLeft.X+obj.Width) x2 = math.Max(x2, obj.TopLeft.X+obj.Width)

View file

@ -13,6 +13,33 @@ import (
"oss.terrastruct.com/d2/lib/label" "oss.terrastruct.com/d2/lib/label"
) )
// Layout runs the sequence diagram layout engine on objects of shape sequence_diagram
//
// 1. Traverse graph from root, skip objects with shape not `sequence_diagram`
// 2. Construct a sequence diagram from all descendant objects and edges
// 3. Remove those objects and edges from the main graph
// 4. Run layout on sequence diagrams
// 5. Set the resulting dimensions to the main graph shape
// 6. Run core layouts (still without sequence diagram innards)
// 7. Put back sequence diagram innards in correct location
func Layout(ctx context.Context, g *d2graph.Graph, layout d2graph.LayoutGraph) error {
sequenceDiagrams, objectOrder, edgeOrder, err := WithoutSequenceDiagrams(ctx, g)
if err != nil {
return err
}
if g.Root.IsSequenceDiagram() {
// the sequence diagram is the only layout engine if the whole diagram is
// shape: sequence_diagram
g.Root.TopLeft = geo.NewPoint(0, 0)
} else if err := layout(ctx, g); err != nil {
return err
}
cleanup(g, sequenceDiagrams, objectOrder, edgeOrder)
return nil
}
func WithoutSequenceDiagrams(ctx context.Context, g *d2graph.Graph) (map[string]*sequenceDiagram, map[string]int, map[string]int, error) { func WithoutSequenceDiagrams(ctx context.Context, g *d2graph.Graph) (map[string]*sequenceDiagram, map[string]int, map[string]int, error) {
objectsToRemove := make(map[*d2graph.Object]struct{}) objectsToRemove := make(map[*d2graph.Object]struct{})
edgesToRemove := make(map[*d2graph.Edge]struct{}) edgesToRemove := make(map[*d2graph.Edge]struct{})
@ -69,33 +96,6 @@ func WithoutSequenceDiagrams(ctx context.Context, g *d2graph.Graph) (map[string]
return sequenceDiagrams, objectOrder, edgeOrder, nil return sequenceDiagrams, objectOrder, edgeOrder, nil
} }
// Layout runs the sequence diagram layout engine on objects of shape sequence_diagram
//
// 1. Traverse graph from root, skip objects with shape not `sequence_diagram`
// 2. Construct a sequence diagram from all descendant objects and edges
// 3. Remove those objects and edges from the main graph
// 4. Run layout on sequence diagrams
// 5. Set the resulting dimensions to the main graph shape
// 6. Run core layouts (still without sequence diagram innards)
// 7. Put back sequence diagram innards in correct location
func Layout(ctx context.Context, g *d2graph.Graph, layout func(ctx context.Context, g *d2graph.Graph) error) error {
sequenceDiagrams, objectOrder, edgeOrder, err := WithoutSequenceDiagrams(ctx, g)
if err != nil {
return err
}
if g.Root.IsSequenceDiagram() {
// the sequence diagram is the only layout engine if the whole diagram is
// shape: sequence_diagram
g.Root.TopLeft = geo.NewPoint(0, 0)
} else if err := layout(ctx, g); err != nil {
return err
}
cleanup(g, sequenceDiagrams, objectOrder, edgeOrder)
return nil
}
// layoutSequenceDiagram finds the edges inside the sequence diagram and performs the layout on the object descendants // 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, error) { func layoutSequenceDiagram(g *d2graph.Graph, obj *d2graph.Object) (*sequenceDiagram, error) {
var edges []*d2graph.Edge var edges []*d2graph.Edge
@ -154,11 +154,11 @@ func cleanup(g *d2graph.Graph, sequenceDiagrams map[string]*sequenceDiagram, obj
objects = g.Objects objects = g.Objects
} }
for _, obj := range objects { for _, obj := range objects {
if _, exists := sequenceDiagrams[obj.AbsID()]; !exists { sd, exists := sequenceDiagrams[obj.AbsID()]
if !exists {
continue continue
} }
obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter))
sd := sequenceDiagrams[obj.AbsID()]
// shift the sequence diagrams as they are always placed at (0, 0) with some padding // shift the sequence diagrams as they are always placed at (0, 0) with some padding
sd.shift( sd.shift(
@ -171,22 +171,22 @@ func cleanup(g *d2graph.Graph, sequenceDiagrams map[string]*sequenceDiagram, obj
obj.Children = make(map[string]*d2graph.Object) obj.Children = make(map[string]*d2graph.Object)
obj.ChildrenArray = make([]*d2graph.Object, 0) obj.ChildrenArray = make([]*d2graph.Object, 0)
for _, child := range sd.actors { for _, child := range sd.actors {
obj.Children[child.ID] = child obj.Children[strings.ToLower(child.ID)] = child
obj.ChildrenArray = append(obj.ChildrenArray, child) obj.ChildrenArray = append(obj.ChildrenArray, child)
} }
for _, child := range sd.groups { for _, child := range sd.groups {
if child.Parent.AbsID() == obj.AbsID() { if child.Parent.AbsID() == obj.AbsID() {
obj.Children[child.ID] = child obj.Children[strings.ToLower(child.ID)] = child
obj.ChildrenArray = append(obj.ChildrenArray, child) obj.ChildrenArray = append(obj.ChildrenArray, child)
} }
} }
g.Edges = append(g.Edges, sequenceDiagrams[obj.AbsID()].messages...) g.Edges = append(g.Edges, sd.messages...)
g.Edges = append(g.Edges, sequenceDiagrams[obj.AbsID()].lifelines...) g.Edges = append(g.Edges, sd.lifelines...)
g.Objects = append(g.Objects, sequenceDiagrams[obj.AbsID()].actors...) g.Objects = append(g.Objects, sd.actors...)
g.Objects = append(g.Objects, sequenceDiagrams[obj.AbsID()].notes...) g.Objects = append(g.Objects, sd.notes...)
g.Objects = append(g.Objects, sequenceDiagrams[obj.AbsID()].groups...) g.Objects = append(g.Objects, sd.groups...)
g.Objects = append(g.Objects, sequenceDiagrams[obj.AbsID()].spans...) g.Objects = append(g.Objects, sd.spans...)
} }
// no new objects, so just keep the same position // no new objects, so just keep the same position

View file

@ -386,13 +386,19 @@ func (sd *sequenceDiagram) addLifelineEdges() {
} }
actorLifelineEnd := actor.Center() actorLifelineEnd := actor.Center()
actorLifelineEnd.Y = endY actorLifelineEnd.Y = endY
sd.lifelines = append(sd.lifelines, &d2graph.Edge{ style := d2graph.Style{
Attributes: &d2graph.Attributes{
Style: d2graph.Style{
StrokeDash: &d2graph.Scalar{Value: fmt.Sprintf("%d", LIFELINE_STROKE_DASH)}, StrokeDash: &d2graph.Scalar{Value: fmt.Sprintf("%d", LIFELINE_STROKE_DASH)},
StrokeWidth: &d2graph.Scalar{Value: fmt.Sprintf("%d", LIFELINE_STROKE_WIDTH)}, StrokeWidth: &d2graph.Scalar{Value: fmt.Sprintf("%d", LIFELINE_STROKE_WIDTH)},
}, }
}, if actor.Attributes.Style.StrokeDash != nil {
style.StrokeDash = &d2graph.Scalar{Value: actor.Attributes.Style.StrokeDash.Value}
}
if actor.Attributes.Style.Stroke != nil {
style.Stroke = &d2graph.Scalar{Value: actor.Attributes.Style.Stroke.Value}
}
sd.lifelines = append(sd.lifelines, &d2graph.Edge{
Attributes: &d2graph.Attributes{Style: style},
Src: actor, Src: actor,
SrcArrow: false, SrcArrow: false,
Dst: &d2graph.Object{ Dst: &d2graph.Object{

View file

@ -10,6 +10,7 @@ import (
"oss.terrastruct.com/d2/d2exporter" "oss.terrastruct.com/d2/d2exporter"
"oss.terrastruct.com/d2/d2graph" "oss.terrastruct.com/d2/d2graph"
"oss.terrastruct.com/d2/d2layouts/d2dagrelayout" "oss.terrastruct.com/d2/d2layouts/d2dagrelayout"
"oss.terrastruct.com/d2/d2layouts/d2grid"
"oss.terrastruct.com/d2/d2layouts/d2near" "oss.terrastruct.com/d2/d2layouts/d2near"
"oss.terrastruct.com/d2/d2layouts/d2sequence" "oss.terrastruct.com/d2/d2layouts/d2sequence"
"oss.terrastruct.com/d2/d2renderers/d2fonts" "oss.terrastruct.com/d2/d2renderers/d2fonts"
@ -68,14 +69,23 @@ func compile(ctx context.Context, g *d2graph.Graph, opts *CompileOptions) (*d2ta
return nil, err return nil, err
} }
constantNears := d2near.WithoutConstantNears(ctx, g) constantNearGraphs := d2near.WithoutConstantNears(ctx, g)
err = d2sequence.Layout(ctx, g, coreLayout) // run core layout for constantNears
for _, tempGraph := range constantNearGraphs {
if err = coreLayout(ctx, tempGraph); err != nil {
return nil, err
}
}
layoutWithGrids := d2grid.Layout(ctx, g, coreLayout)
err = d2sequence.Layout(ctx, g, layoutWithGrids)
if err != nil { if err != nil {
return nil, err return nil, err
} }
err = d2near.Layout(ctx, g, constantNears) err = d2near.Layout(ctx, g, constantNearGraphs)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -110,7 +120,7 @@ func compile(ctx context.Context, g *d2graph.Graph, opts *CompileOptions) (*d2ta
return d, nil return d, nil
} }
func getLayout(opts *CompileOptions) (func(context.Context, *d2graph.Graph) error, error) { func getLayout(opts *CompileOptions) (d2graph.LayoutGraph, error) {
if opts.Layout != nil { if opts.Layout != nil {
return opts.Layout, nil return opts.Layout, nil
} else if os.Getenv("D2_LAYOUT") == "dagre" { } else if os.Getenv("D2_LAYOUT") == "dagre" {

View file

@ -314,6 +314,16 @@ func _set(g *d2graph.Graph, key string, tag, value *string) error {
attrs.Left.MapKey.SetScalar(mk.Value.ScalarBox()) attrs.Left.MapKey.SetScalar(mk.Value.ScalarBox())
return nil return nil
} }
case "grid-rows":
if attrs.GridRows != nil && attrs.GridRows.MapKey != nil {
attrs.GridRows.MapKey.SetScalar(mk.Value.ScalarBox())
return nil
}
case "grid-columns":
if attrs.GridColumns != nil && attrs.GridColumns.MapKey != nil {
attrs.GridColumns.MapKey.SetScalar(mk.Value.ScalarBox())
return nil
}
case "source-arrowhead", "target-arrowhead": case "source-arrowhead", "target-arrowhead":
if reservedKey == "source-arrowhead" { if reservedKey == "source-arrowhead" {
attrs = edge.SrcArrowhead attrs = edge.SrcArrowhead

View file

@ -14,23 +14,23 @@ import (
var transitionDurationMS = 1 var transitionDurationMS = 1
func makeKeyframe(delayMS, durationMS, totalMS, identifier int) string { func makeKeyframe(delayMS, durationMS, totalMS, identifier int, diagramHash string) string {
percentageBefore := (math.Max(0, float64(delayMS-transitionDurationMS)) / float64(totalMS)) * 100. percentageBefore := (math.Max(0, float64(delayMS-transitionDurationMS)) / float64(totalMS)) * 100.
percentageStart := (float64(delayMS) / float64(totalMS)) * 100. percentageStart := (float64(delayMS) / float64(totalMS)) * 100.
percentageEnd := (float64(delayMS+durationMS-transitionDurationMS) / float64(totalMS)) * 100. percentageEnd := (float64(delayMS+durationMS-transitionDurationMS) / float64(totalMS)) * 100.
if int(math.Ceil(percentageEnd)) == 100 { if int(math.Ceil(percentageEnd)) == 100 {
return fmt.Sprintf(`@keyframes d2Transition-%d { return fmt.Sprintf(`@keyframes d2Transition-%s-%d {
0%%, %f%% { 0%%, %f%% {
opacity: 0; opacity: 0;
} }
%f%%, %f%% { %f%%, %f%% {
opacity: 1; opacity: 1;
} }
}`, identifier, percentageBefore, percentageStart, math.Ceil(percentageEnd)) }`, diagramHash, identifier, percentageBefore, percentageStart, math.Ceil(percentageEnd))
} }
percentageAfter := (float64(delayMS+durationMS) / float64(totalMS)) * 100. percentageAfter := (float64(delayMS+durationMS) / float64(totalMS)) * 100.
return fmt.Sprintf(`@keyframes d2Transition-%d { return fmt.Sprintf(`@keyframes d2Transition-%s-%d {
0%%, %f%% { 0%%, %f%% {
opacity: 0; opacity: 0;
} }
@ -40,7 +40,7 @@ func makeKeyframe(delayMS, durationMS, totalMS, identifier int) string {
%f%%, 100%% { %f%%, 100%% {
opacity: 0; opacity: 0;
} }
}`, identifier, percentageBefore, percentageStart, percentageEnd, percentageAfter) }`, diagramHash, identifier, percentageBefore, percentageStart, percentageEnd, percentageAfter)
} }
func Wrap(rootDiagram *d2target.Diagram, svgs [][]byte, renderOpts d2svg.RenderOpts, intervalMS int) ([]byte, error) { func Wrap(rootDiagram *d2target.Diagram, svgs [][]byte, renderOpts d2svg.RenderOpts, intervalMS int) ([]byte, error) {
@ -99,13 +99,13 @@ func Wrap(rootDiagram *d2target.Diagram, svgs [][]byte, renderOpts d2svg.RenderO
fmt.Fprint(buf, `<style type="text/css"><![CDATA[`) fmt.Fprint(buf, `<style type="text/css"><![CDATA[`)
for i := range svgs { for i := range svgs {
fmt.Fprint(buf, makeKeyframe(i*intervalMS, intervalMS, len(svgs)*intervalMS, i)) fmt.Fprint(buf, makeKeyframe(i*intervalMS, intervalMS, len(svgs)*intervalMS, i, diagramHash))
} }
fmt.Fprint(buf, `]]></style>`) fmt.Fprint(buf, `]]></style>`)
for i, svg := range svgs { for i, svg := range svgs {
str := string(svg) str := string(svg)
str = strings.Replace(str, "<g", fmt.Sprintf(`<g style="animation: d2Transition-%d %dms infinite"`, i, len(svgs)*intervalMS), 1) str = strings.Replace(str, "<g", fmt.Sprintf(`<g style="animation: d2Transition-%s-%d %dms infinite"`, diagramHash, i, len(svgs)*intervalMS), 1)
buf.Write([]byte(str)) buf.Write([]byte(str))
} }

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 127 KiB

After

Width:  |  Height:  |  Size: 127 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 118 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 67 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 124 KiB

After

Width:  |  Height:  |  Size: 125 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 115 KiB

After

Width:  |  Height:  |  Size: 115 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 161 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 152 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 161 KiB

After

Width:  |  Height:  |  Size: 162 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 165 KiB

After

Width:  |  Height:  |  Size: 165 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 108 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 59 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 89 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 80 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 493 KiB

After

Width:  |  Height:  |  Size: 493 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 100 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 74 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 65 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 108 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 180 KiB

After

Width:  |  Height:  |  Size: 181 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 180 KiB

After

Width:  |  Height:  |  Size: 181 KiB

View file

@ -238,7 +238,7 @@ func generateLine(i, y int, text string, ruler *textmeasure.Ruler) (string, int,
0, y, generateNumberedIcon(i, 0, 0)) 0, y, generateNumberedIcon(i, 0, 0))
line += fmt.Sprintf(`<text class="text" x="%d" y="%d" style="font-size: %dpx;">%s</text>`, line += fmt.Sprintf(`<text class="text" x="%d" y="%d" style="font-size: %dpx;">%s</text>`,
ICON_RADIUS*3, y, FONT_SIZE, d2svg.RenderText(text, ICON_RADIUS*3, float64(dims.Height))) ICON_RADIUS*3, y+5, FONT_SIZE, d2svg.RenderText(text, ICON_RADIUS*3, float64(dims.Height)))
return line, dims.Width + ICON_RADIUS*3, go2.IntMax(dims.Height, ICON_RADIUS*2) return line, dims.Width + ICON_RADIUS*3, go2.IntMax(dims.Height, ICON_RADIUS*2)
} }

View file

@ -115,8 +115,8 @@
<rect x="434.000000" y="1023.000000" width="140" height="21" fill="black"></rect> <rect x="434.000000" y="1023.000000" width="140" height="21" fill="black"></rect>
<rect x="551.000000" y="1093.000000" width="61" height="21" fill="black"></rect> <rect x="551.000000" y="1093.000000" width="61" height="21" fill="black"></rect>
<rect x="789.000000" y="1163.000000" width="65" height="21" fill="black"></rect> <rect x="789.000000" y="1163.000000" width="65" height="21" fill="black"></rect>
</mask><line x1="-132.000000" x2="1179.000000" y1="1294.000000" y2="1294.000000" class=" stroke-B2" /><g class="appendix" x="-92" y="1244" width="1231" height="100%"><g transform="translate(0 1344)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">1</text></g><text class="text" x="48" y="1344" style="font-size: 16px;">Like starbucks or something</text> </mask><line x1="-132.000000" x2="1179.000000" y1="1294.000000" y2="1294.000000" class=" stroke-B2" /><g class="appendix" x="-92" y="1244" width="1231" height="100%"><g transform="translate(0 1344)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">1</text></g><text class="text" x="48" y="1349" style="font-size: 16px;">Like starbucks or something</text>
<g transform="translate(0 1396)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">2</text></g><text class="text" x="48" y="1396" style="font-size: 16px;">I&#39;m not sure what this is</text></g> <g transform="translate(0 1396)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">2</text></g><text class="text" x="48" y="1401" style="font-size: 16px;">I&#39;m not sure what this is</text></g>
<style type="text/css"><![CDATA[ <style type="text/css"><![CDATA[
.text { .text {
font-family: "font-regular"; font-family: "font-regular";

Before

Width:  |  Height:  |  Size: 676 KiB

After

Width:  |  Height:  |  Size: 676 KiB

View file

@ -1,12 +1,12 @@
<?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.3.0-HEAD" preserveAspectRatio="xMinYMin meet" viewBox="0 0 304 407"><svg id="d2-svg" class="d2-3205202238" width="304" height="407" viewBox="-101 -118 304 407"><rect x="-101.000000" y="-118.000000" width="304" height="407" rx="0.000000" class=" fill-N7" stroke-width="0" /><style type="text/css"><![CDATA[ <?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.3.0-HEAD" preserveAspectRatio="xMinYMin meet" viewBox="0 0 304 407"><svg id="d2-svg" class="d2-916646398" width="304" height="407" viewBox="-101 -118 304 407"><rect x="-101.000000" y="-118.000000" width="304" height="407" rx="0.000000" class=" fill-N7" stroke-width="0" /><style type="text/css"><![CDATA[
.appendix-icon { .appendix-icon {
filter: drop-shadow(0px 0px 32px rgba(31, 36, 58, 0.1)); filter: drop-shadow(0px 0px 32px rgba(31, 36, 58, 0.1));
} }
.d2-3205202238 .text-bold { .d2-916646398 .text-bold {
font-family: "d2-3205202238-font-bold"; font-family: "d2-916646398-font-bold";
} }
@font-face { @font-face {
font-family: d2-3205202238-font-bold; font-family: d2-916646398-font-bold;
src: url("data:application/font-woff;base64,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"); src: url("data:application/font-woff;base64,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");
}]]></style><style type="text/css"><![CDATA[.shape { }]]></style><style type="text/css"><![CDATA[.shape {
shape-rendering: geometricPrecision; shape-rendering: geometricPrecision;
@ -21,81 +21,81 @@
opacity: 0.5; opacity: 0.5;
} }
.d2-3205202238 .fill-N1{fill:#0A0F25;} .d2-916646398 .fill-N1{fill:#0A0F25;}
.d2-3205202238 .fill-N2{fill:#676C7E;} .d2-916646398 .fill-N2{fill:#676C7E;}
.d2-3205202238 .fill-N3{fill:#9499AB;} .d2-916646398 .fill-N3{fill:#9499AB;}
.d2-3205202238 .fill-N4{fill:#CFD2DD;} .d2-916646398 .fill-N4{fill:#CFD2DD;}
.d2-3205202238 .fill-N5{fill:#DEE1EB;} .d2-916646398 .fill-N5{fill:#DEE1EB;}
.d2-3205202238 .fill-N6{fill:#EEF1F8;} .d2-916646398 .fill-N6{fill:#EEF1F8;}
.d2-3205202238 .fill-N7{fill:#FFFFFF;} .d2-916646398 .fill-N7{fill:#FFFFFF;}
.d2-3205202238 .fill-B1{fill:#0D32B2;} .d2-916646398 .fill-B1{fill:#0D32B2;}
.d2-3205202238 .fill-B2{fill:#0D32B2;} .d2-916646398 .fill-B2{fill:#0D32B2;}
.d2-3205202238 .fill-B3{fill:#E3E9FD;} .d2-916646398 .fill-B3{fill:#E3E9FD;}
.d2-3205202238 .fill-B4{fill:#E3E9FD;} .d2-916646398 .fill-B4{fill:#E3E9FD;}
.d2-3205202238 .fill-B5{fill:#EDF0FD;} .d2-916646398 .fill-B5{fill:#EDF0FD;}
.d2-3205202238 .fill-B6{fill:#F7F8FE;} .d2-916646398 .fill-B6{fill:#F7F8FE;}
.d2-3205202238 .fill-AA2{fill:#4A6FF3;} .d2-916646398 .fill-AA2{fill:#4A6FF3;}
.d2-3205202238 .fill-AA4{fill:#EDF0FD;} .d2-916646398 .fill-AA4{fill:#EDF0FD;}
.d2-3205202238 .fill-AA5{fill:#F7F8FE;} .d2-916646398 .fill-AA5{fill:#F7F8FE;}
.d2-3205202238 .fill-AB4{fill:#EDF0FD;} .d2-916646398 .fill-AB4{fill:#EDF0FD;}
.d2-3205202238 .fill-AB5{fill:#F7F8FE;} .d2-916646398 .fill-AB5{fill:#F7F8FE;}
.d2-3205202238 .stroke-N1{stroke:#0A0F25;} .d2-916646398 .stroke-N1{stroke:#0A0F25;}
.d2-3205202238 .stroke-N2{stroke:#676C7E;} .d2-916646398 .stroke-N2{stroke:#676C7E;}
.d2-3205202238 .stroke-N3{stroke:#9499AB;} .d2-916646398 .stroke-N3{stroke:#9499AB;}
.d2-3205202238 .stroke-N4{stroke:#CFD2DD;} .d2-916646398 .stroke-N4{stroke:#CFD2DD;}
.d2-3205202238 .stroke-N5{stroke:#DEE1EB;} .d2-916646398 .stroke-N5{stroke:#DEE1EB;}
.d2-3205202238 .stroke-N6{stroke:#EEF1F8;} .d2-916646398 .stroke-N6{stroke:#EEF1F8;}
.d2-3205202238 .stroke-N7{stroke:#FFFFFF;} .d2-916646398 .stroke-N7{stroke:#FFFFFF;}
.d2-3205202238 .stroke-B1{stroke:#0D32B2;} .d2-916646398 .stroke-B1{stroke:#0D32B2;}
.d2-3205202238 .stroke-B2{stroke:#0D32B2;} .d2-916646398 .stroke-B2{stroke:#0D32B2;}
.d2-3205202238 .stroke-B3{stroke:#E3E9FD;} .d2-916646398 .stroke-B3{stroke:#E3E9FD;}
.d2-3205202238 .stroke-B4{stroke:#E3E9FD;} .d2-916646398 .stroke-B4{stroke:#E3E9FD;}
.d2-3205202238 .stroke-B5{stroke:#EDF0FD;} .d2-916646398 .stroke-B5{stroke:#EDF0FD;}
.d2-3205202238 .stroke-B6{stroke:#F7F8FE;} .d2-916646398 .stroke-B6{stroke:#F7F8FE;}
.d2-3205202238 .stroke-AA2{stroke:#4A6FF3;} .d2-916646398 .stroke-AA2{stroke:#4A6FF3;}
.d2-3205202238 .stroke-AA4{stroke:#EDF0FD;} .d2-916646398 .stroke-AA4{stroke:#EDF0FD;}
.d2-3205202238 .stroke-AA5{stroke:#F7F8FE;} .d2-916646398 .stroke-AA5{stroke:#F7F8FE;}
.d2-3205202238 .stroke-AB4{stroke:#EDF0FD;} .d2-916646398 .stroke-AB4{stroke:#EDF0FD;}
.d2-3205202238 .stroke-AB5{stroke:#F7F8FE;} .d2-916646398 .stroke-AB5{stroke:#F7F8FE;}
.d2-3205202238 .background-color-N1{background-color:#0A0F25;} .d2-916646398 .background-color-N1{background-color:#0A0F25;}
.d2-3205202238 .background-color-N2{background-color:#676C7E;} .d2-916646398 .background-color-N2{background-color:#676C7E;}
.d2-3205202238 .background-color-N3{background-color:#9499AB;} .d2-916646398 .background-color-N3{background-color:#9499AB;}
.d2-3205202238 .background-color-N4{background-color:#CFD2DD;} .d2-916646398 .background-color-N4{background-color:#CFD2DD;}
.d2-3205202238 .background-color-N5{background-color:#DEE1EB;} .d2-916646398 .background-color-N5{background-color:#DEE1EB;}
.d2-3205202238 .background-color-N6{background-color:#EEF1F8;} .d2-916646398 .background-color-N6{background-color:#EEF1F8;}
.d2-3205202238 .background-color-N7{background-color:#FFFFFF;} .d2-916646398 .background-color-N7{background-color:#FFFFFF;}
.d2-3205202238 .background-color-B1{background-color:#0D32B2;} .d2-916646398 .background-color-B1{background-color:#0D32B2;}
.d2-3205202238 .background-color-B2{background-color:#0D32B2;} .d2-916646398 .background-color-B2{background-color:#0D32B2;}
.d2-3205202238 .background-color-B3{background-color:#E3E9FD;} .d2-916646398 .background-color-B3{background-color:#E3E9FD;}
.d2-3205202238 .background-color-B4{background-color:#E3E9FD;} .d2-916646398 .background-color-B4{background-color:#E3E9FD;}
.d2-3205202238 .background-color-B5{background-color:#EDF0FD;} .d2-916646398 .background-color-B5{background-color:#EDF0FD;}
.d2-3205202238 .background-color-B6{background-color:#F7F8FE;} .d2-916646398 .background-color-B6{background-color:#F7F8FE;}
.d2-3205202238 .background-color-AA2{background-color:#4A6FF3;} .d2-916646398 .background-color-AA2{background-color:#4A6FF3;}
.d2-3205202238 .background-color-AA4{background-color:#EDF0FD;} .d2-916646398 .background-color-AA4{background-color:#EDF0FD;}
.d2-3205202238 .background-color-AA5{background-color:#F7F8FE;} .d2-916646398 .background-color-AA5{background-color:#F7F8FE;}
.d2-3205202238 .background-color-AB4{background-color:#EDF0FD;} .d2-916646398 .background-color-AB4{background-color:#EDF0FD;}
.d2-3205202238 .background-color-AB5{background-color:#F7F8FE;} .d2-916646398 .background-color-AB5{background-color:#F7F8FE;}
.d2-3205202238 .color-N1{color:#0A0F25;} .d2-916646398 .color-N1{color:#0A0F25;}
.d2-3205202238 .color-N2{color:#676C7E;} .d2-916646398 .color-N2{color:#676C7E;}
.d2-3205202238 .color-N3{color:#9499AB;} .d2-916646398 .color-N3{color:#9499AB;}
.d2-3205202238 .color-N4{color:#CFD2DD;} .d2-916646398 .color-N4{color:#CFD2DD;}
.d2-3205202238 .color-N5{color:#DEE1EB;} .d2-916646398 .color-N5{color:#DEE1EB;}
.d2-3205202238 .color-N6{color:#EEF1F8;} .d2-916646398 .color-N6{color:#EEF1F8;}
.d2-3205202238 .color-N7{color:#FFFFFF;} .d2-916646398 .color-N7{color:#FFFFFF;}
.d2-3205202238 .color-B1{color:#0D32B2;} .d2-916646398 .color-B1{color:#0D32B2;}
.d2-3205202238 .color-B2{color:#0D32B2;} .d2-916646398 .color-B2{color:#0D32B2;}
.d2-3205202238 .color-B3{color:#E3E9FD;} .d2-916646398 .color-B3{color:#E3E9FD;}
.d2-3205202238 .color-B4{color:#E3E9FD;} .d2-916646398 .color-B4{color:#E3E9FD;}
.d2-3205202238 .color-B5{color:#EDF0FD;} .d2-916646398 .color-B5{color:#EDF0FD;}
.d2-3205202238 .color-B6{color:#F7F8FE;} .d2-916646398 .color-B6{color:#F7F8FE;}
.d2-3205202238 .color-AA2{color:#4A6FF3;} .d2-916646398 .color-AA2{color:#4A6FF3;}
.d2-3205202238 .color-AA4{color:#EDF0FD;} .d2-916646398 .color-AA4{color:#EDF0FD;}
.d2-3205202238 .color-AA5{color:#F7F8FE;} .d2-916646398 .color-AA5{color:#F7F8FE;}
.d2-3205202238 .color-AB4{color:#EDF0FD;} .d2-916646398 .color-AB4{color:#EDF0FD;}
.d2-3205202238 .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><a href="root.layers.x" xlink:href="root.layers.x"><g id="x"><g class="shape" ><rect x="0.000000" y="0.000000" width="85.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="42.500000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">x</text><g transform="translate(69 -16)" class="appendix-icon"><circle cx="16" cy="16" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="21" style="font-size: 16px;text-anchor:middle;">1</text></g></g></a><mask id="d2-3205202238" maskUnits="userSpaceOnUse" x="-101" y="-118" width="304" height="285"> .d2-916646398 .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><a href="root.layers.x" xlink:href="root.layers.x"><g id="x"><g class="shape" ><rect x="0.000000" y="0.000000" width="85.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="42.500000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">x</text><g transform="translate(69 -16)" class="appendix-icon"><circle cx="16" cy="16" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="21" style="font-size: 16px;text-anchor:middle;">1</text></g></g></a><mask id="d2-916646398" maskUnits="userSpaceOnUse" x="-101" y="-118" width="304" height="285">
<rect x="-101" y="-118" width="304" height="285" fill="white"></rect> <rect x="-101" y="-118" width="304" height="285" fill="white"></rect>
</mask><line x1="-41.000000" x2="143.000000" y1="117.000000" y2="117.000000" class=" stroke-B2" /><g class="appendix" x="-1" y="67" width="104" height="100%"><g transform="translate(0 167)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">1</text></g><text class="text" x="48" y="167" style="font-size: 16px;">root &gt; x</text></g> </mask><line x1="-41.000000" x2="143.000000" y1="117.000000" y2="117.000000" class=" stroke-B2" /><g class="appendix" x="-1" y="67" width="104" height="100%"><g transform="translate(0 167)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">1</text></g><text class="text" x="48" y="172" style="font-size: 16px;">root &gt; x</text></g>
<style type="text/css"><![CDATA[ <style type="text/css"><![CDATA[
.text { .text {
font-family: "font-regular"; font-family: "font-regular";

Before

Width:  |  Height:  |  Size: 657 KiB

After

Width:  |  Height:  |  Size: 657 KiB

View file

@ -95,9 +95,9 @@
.d2-109718516 .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><a href="https://d2lang.com" xlink:href="https://d2lang.com"><g id="x"><g class="shape" ><rect x="17.000000" y="0.000000" width="85.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="59.500000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">x</text><g transform="translate(86 -16)" class="appendix-icon"><circle cx="16" cy="16" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="21" style="font-size: 16px;text-anchor:middle;">1</text></g></g></a><a href="https://terrastruct.com" xlink:href="https://terrastruct.com"><g id="y"><g class="shape" ><rect x="0.000000" y="166.000000" width="118.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="59.000000" y="204.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">y</text><g transform="translate(102 150)" class="appendix-icon"><circle cx="16" cy="16" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="21" style="font-size: 16px;text-anchor:middle;">2</text></g><title>Gee, I feel kind of LIGHT in the head now,&#xA;knowing I can&#39;t make my satellite dish PAYMENTS!</title><g transform="translate(70 150)" class="appendix-icon"><circle cx="16" cy="16" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="21" style="font-size: 16px;text-anchor:middle;">3</text></g></g></a><g id="(x -&gt; y)[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 59.000000 68.000000 C 59.000000 106.000000 59.000000 126.000000 59.000000 162.000000" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-109718516)" /></g><mask id="d2-109718516" maskUnits="userSpaceOnUse" x="-101" y="-118" width="337" height="451"> .d2-109718516 .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><a href="https://d2lang.com" xlink:href="https://d2lang.com"><g id="x"><g class="shape" ><rect x="17.000000" y="0.000000" width="85.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="59.500000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">x</text><g transform="translate(86 -16)" class="appendix-icon"><circle cx="16" cy="16" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="21" style="font-size: 16px;text-anchor:middle;">1</text></g></g></a><a href="https://terrastruct.com" xlink:href="https://terrastruct.com"><g id="y"><g class="shape" ><rect x="0.000000" y="166.000000" width="118.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="59.000000" y="204.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">y</text><g transform="translate(102 150)" class="appendix-icon"><circle cx="16" cy="16" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="21" style="font-size: 16px;text-anchor:middle;">2</text></g><title>Gee, I feel kind of LIGHT in the head now,&#xA;knowing I can&#39;t make my satellite dish PAYMENTS!</title><g transform="translate(70 150)" class="appendix-icon"><circle cx="16" cy="16" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="21" style="font-size: 16px;text-anchor:middle;">3</text></g></g></a><g id="(x -&gt; y)[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 59.000000 68.000000 C 59.000000 106.000000 59.000000 126.000000 59.000000 162.000000" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-109718516)" /></g><mask id="d2-109718516" maskUnits="userSpaceOnUse" x="-101" y="-118" width="337" height="451">
<rect x="-101" y="-118" width="337" height="451" fill="white"></rect> <rect x="-101" y="-118" width="337" height="451" fill="white"></rect>
</mask><line x1="-41.000000" x2="423.000000" y1="283.000000" y2="283.000000" class=" stroke-B2" /><g class="appendix" x="-1" y="233" width="137" height="100%"><g transform="translate(0 333)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">1</text></g><text class="text" x="48" y="333" style="font-size: 16px;">https://d2lang.com</text> </mask><line x1="-41.000000" x2="423.000000" y1="283.000000" y2="283.000000" class=" stroke-B2" /><g class="appendix" x="-1" y="233" width="137" height="100%"><g transform="translate(0 333)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">1</text></g><text class="text" x="48" y="338" style="font-size: 16px;">https://d2lang.com</text>
<g transform="translate(0 385)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">2</text></g><text class="text" x="48" y="385" style="font-size: 16px;"><tspan x="48.000000" dy="0.000000">Gee, I feel kind of LIGHT in the head now,</tspan><tspan x="48.000000" dy="18.500000">knowing I can&#39;t make my satellite dish PAYMENTS!</tspan></text> <g transform="translate(0 385)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">2</text></g><text class="text" x="48" y="390" style="font-size: 16px;"><tspan x="48.000000" dy="0.000000">Gee, I feel kind of LIGHT in the head now,</tspan><tspan x="48.000000" dy="18.500000">knowing I can&#39;t make my satellite dish PAYMENTS!</tspan></text>
<g transform="translate(0 442)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">3</text></g><text class="text" x="48" y="442" style="font-size: 16px;">https://terrastruct.com</text></g> <g transform="translate(0 442)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">3</text></g><text class="text" x="48" y="447" style="font-size: 16px;">https://terrastruct.com</text></g>
<style type="text/css"><![CDATA[ <style type="text/css"><![CDATA[
.text { .text {
font-family: "font-regular"; font-family: "font-regular";

Before

Width:  |  Height:  |  Size: 661 KiB

After

Width:  |  Height:  |  Size: 661 KiB

View file

@ -95,9 +95,9 @@
.d2-1293182475 .color-AB5{color:#313244;}.appendix text.text{fill:#CDD6F4}.md{--color-fg-default:#CDD6F4;--color-fg-muted:#BAC2DE;--color-fg-subtle:#A6ADC8;--color-canvas-default:#1E1E2E;--color-canvas-subtle:#313244;--color-border-default:#CBA6f7;--color-border-muted:#CBA6f7;--color-neutral-muted:#313244;--color-accent-fg:#CBA6f7;--color-accent-emphasis:#CBA6f7;--color-attention-subtle:#BAC2DE;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-B2{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-B3{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-B4{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-B5{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B6{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-AA2{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-AA4{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-AA5{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-AB4{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-AB5{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N1{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N2{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N5{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N6{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N7{fill:url(#streaks-darker);mix-blend-mode:lighten}.light-code{display: none}.dark-code{display: block}]]></style><a href="https://d2lang.com" xlink:href="https://d2lang.com"><g id="x"><g class="shape" ><rect x="17.000000" y="0.000000" width="85.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="59.500000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">x</text><g transform="translate(86 -16)" class="appendix-icon"><circle cx="16" cy="16" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="21" style="font-size: 16px;text-anchor:middle;">1</text></g></g></a><a href="https://fosny.eu" xlink:href="https://fosny.eu"><g id="y"><g class="shape" ><rect x="0.000000" y="166.000000" width="118.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="59.000000" y="204.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">y</text><g transform="translate(102 150)" class="appendix-icon"><circle cx="16" cy="16" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="21" style="font-size: 16px;text-anchor:middle;">2</text></g><title>Gee, I feel kind of LIGHT in the head now,&#xA;knowing I can&#39;t make my satellite dish PAYMENTS!</title><g transform="translate(70 150)" class="appendix-icon"><circle cx="16" cy="16" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="21" style="font-size: 16px;text-anchor:middle;">3</text></g></g></a><g id="(x -&gt; y)[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 59.000000 68.000000 C 59.000000 106.000000 59.000000 126.000000 59.000000 162.000000" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-1293182475)" /></g><mask id="d2-1293182475" maskUnits="userSpaceOnUse" x="-101" y="-118" width="337" height="451"> .d2-1293182475 .color-AB5{color:#313244;}.appendix text.text{fill:#CDD6F4}.md{--color-fg-default:#CDD6F4;--color-fg-muted:#BAC2DE;--color-fg-subtle:#A6ADC8;--color-canvas-default:#1E1E2E;--color-canvas-subtle:#313244;--color-border-default:#CBA6f7;--color-border-muted:#CBA6f7;--color-neutral-muted:#313244;--color-accent-fg:#CBA6f7;--color-accent-emphasis:#CBA6f7;--color-attention-subtle:#BAC2DE;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-B2{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-B3{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-B4{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-B5{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B6{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-AA2{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-AA4{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-AA5{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-AB4{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-AB5{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N1{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N2{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N5{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N6{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N7{fill:url(#streaks-darker);mix-blend-mode:lighten}.light-code{display: none}.dark-code{display: block}]]></style><a href="https://d2lang.com" xlink:href="https://d2lang.com"><g id="x"><g class="shape" ><rect x="17.000000" y="0.000000" width="85.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="59.500000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">x</text><g transform="translate(86 -16)" class="appendix-icon"><circle cx="16" cy="16" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="21" style="font-size: 16px;text-anchor:middle;">1</text></g></g></a><a href="https://fosny.eu" xlink:href="https://fosny.eu"><g id="y"><g class="shape" ><rect x="0.000000" y="166.000000" width="118.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="59.000000" y="204.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">y</text><g transform="translate(102 150)" class="appendix-icon"><circle cx="16" cy="16" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="21" style="font-size: 16px;text-anchor:middle;">2</text></g><title>Gee, I feel kind of LIGHT in the head now,&#xA;knowing I can&#39;t make my satellite dish PAYMENTS!</title><g transform="translate(70 150)" class="appendix-icon"><circle cx="16" cy="16" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="21" style="font-size: 16px;text-anchor:middle;">3</text></g></g></a><g id="(x -&gt; y)[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 59.000000 68.000000 C 59.000000 106.000000 59.000000 126.000000 59.000000 162.000000" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-1293182475)" /></g><mask id="d2-1293182475" maskUnits="userSpaceOnUse" x="-101" y="-118" width="337" height="451">
<rect x="-101" y="-118" width="337" height="451" fill="white"></rect> <rect x="-101" y="-118" width="337" height="451" fill="white"></rect>
</mask><line x1="-41.000000" x2="423.000000" y1="283.000000" y2="283.000000" class=" stroke-B2" /><g class="appendix" x="-1" y="233" width="137" height="100%"><g transform="translate(0 333)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">1</text></g><text class="text" x="48" y="333" style="font-size: 16px;">https://d2lang.com</text> </mask><line x1="-41.000000" x2="423.000000" y1="283.000000" y2="283.000000" class=" stroke-B2" /><g class="appendix" x="-1" y="233" width="137" height="100%"><g transform="translate(0 333)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">1</text></g><text class="text" x="48" y="338" style="font-size: 16px;">https://d2lang.com</text>
<g transform="translate(0 385)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">2</text></g><text class="text" x="48" y="385" style="font-size: 16px;"><tspan x="48.000000" dy="0.000000">Gee, I feel kind of LIGHT in the head now,</tspan><tspan x="48.000000" dy="18.500000">knowing I can&#39;t make my satellite dish PAYMENTS!</tspan></text> <g transform="translate(0 385)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">2</text></g><text class="text" x="48" y="390" style="font-size: 16px;"><tspan x="48.000000" dy="0.000000">Gee, I feel kind of LIGHT in the head now,</tspan><tspan x="48.000000" dy="18.500000">knowing I can&#39;t make my satellite dish PAYMENTS!</tspan></text>
<g transform="translate(0 442)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">3</text></g><text class="text" x="48" y="442" style="font-size: 16px;">https://fosny.eu</text></g> <g transform="translate(0 442)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">3</text></g><text class="text" x="48" y="447" style="font-size: 16px;">https://fosny.eu</text></g>
<style type="text/css"><![CDATA[ <style type="text/css"><![CDATA[
.text { .text {
font-family: "font-regular"; font-family: "font-regular";

Before

Width:  |  Height:  |  Size: 661 KiB

After

Width:  |  Height:  |  Size: 661 KiB

View file

@ -95,8 +95,8 @@
.d2-1773020175 .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="x"><g class="shape" ><rect x="1.000000" y="0.000000" width="85.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="43.500000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">x</text><g transform="translate(70 -16)" class="appendix-icon"><circle cx="16" cy="16" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="21" style="font-size: 16px;text-anchor:middle;">1</text></g><title>Total abstinence is easier than perfect moderation</title></g><g id="y"><g class="shape" ><rect x="0.000000" y="166.000000" width="86.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="43.000000" y="204.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">y</text><g transform="translate(70 150)" class="appendix-icon"><circle cx="16" cy="16" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="21" style="font-size: 16px;text-anchor:middle;">2</text></g><title>Gee, I feel kind of LIGHT in the head now,&#xA;knowing I can&#39;t make my satellite dish PAYMENTS!</title></g><g id="(x -&gt; y)[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 43.000000 68.000000 C 43.000000 106.000000 43.000000 126.000000 43.000000 162.000000" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-1773020175)" /></g><mask id="d2-1773020175" maskUnits="userSpaceOnUse" x="-101" y="-118" width="305" height="451"> .d2-1773020175 .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="x"><g class="shape" ><rect x="1.000000" y="0.000000" width="85.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="43.500000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">x</text><g transform="translate(70 -16)" class="appendix-icon"><circle cx="16" cy="16" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="21" style="font-size: 16px;text-anchor:middle;">1</text></g><title>Total abstinence is easier than perfect moderation</title></g><g id="y"><g class="shape" ><rect x="0.000000" y="166.000000" width="86.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="43.000000" y="204.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">y</text><g transform="translate(70 150)" class="appendix-icon"><circle cx="16" cy="16" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="21" style="font-size: 16px;text-anchor:middle;">2</text></g><title>Gee, I feel kind of LIGHT in the head now,&#xA;knowing I can&#39;t make my satellite dish PAYMENTS!</title></g><g id="(x -&gt; y)[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 43.000000 68.000000 C 43.000000 106.000000 43.000000 126.000000 43.000000 162.000000" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-1773020175)" /></g><mask id="d2-1773020175" maskUnits="userSpaceOnUse" x="-101" y="-118" width="305" height="451">
<rect x="-101" y="-118" width="305" height="451" fill="white"></rect> <rect x="-101" y="-118" width="305" height="451" fill="white"></rect>
</mask><line x1="-41.000000" x2="424.000000" y1="283.000000" y2="283.000000" class=" stroke-B2" /><g class="appendix" x="-1" y="233" width="105" height="100%"><g transform="translate(0 333)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">1</text></g><text class="text" x="48" y="333" style="font-size: 16px;">Total abstinence is easier than perfect moderation</text> </mask><line x1="-41.000000" x2="424.000000" y1="283.000000" y2="283.000000" class=" stroke-B2" /><g class="appendix" x="-1" y="233" width="105" height="100%"><g transform="translate(0 333)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">1</text></g><text class="text" x="48" y="338" style="font-size: 16px;">Total abstinence is easier than perfect moderation</text>
<g transform="translate(0 385)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">2</text></g><text class="text" x="48" y="385" style="font-size: 16px;"><tspan x="48.000000" dy="0.000000">Gee, I feel kind of LIGHT in the head now,</tspan><tspan x="48.000000" dy="18.500000">knowing I can&#39;t make my satellite dish PAYMENTS!</tspan></text></g> <g transform="translate(0 385)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">2</text></g><text class="text" x="48" y="390" style="font-size: 16px;"><tspan x="48.000000" dy="0.000000">Gee, I feel kind of LIGHT in the head now,</tspan><tspan x="48.000000" dy="18.500000">knowing I can&#39;t make my satellite dish PAYMENTS!</tspan></text></g>
<style type="text/css"><![CDATA[ <style type="text/css"><![CDATA[
.text { .text {
font-family: "font-regular"; font-family: "font-regular";

Before

Width:  |  Height:  |  Size: 661 KiB

After

Width:  |  Height:  |  Size: 661 KiB

View file

@ -95,8 +95,8 @@
.d2-1773020175 .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="x"><g class="shape" ><rect x="1.000000" y="0.000000" width="85.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="43.500000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">x</text><g transform="translate(70 -16)" class="appendix-icon"><circle cx="16" cy="16" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="21" style="font-size: 16px;text-anchor:middle;">1</text></g><title>Total abstinence is easier than perfect moderation</title></g><g id="y"><g class="shape" ><rect x="0.000000" y="166.000000" width="86.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="43.000000" y="204.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">y</text><g transform="translate(70 150)" class="appendix-icon"><circle cx="16" cy="16" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="21" style="font-size: 16px;text-anchor:middle;">2</text></g><title>Gee, I feel kind of LIGHT in the head now,&#xA;knowing I can&#39;t make my satellite dish PAYMENTS!</title></g><g id="(x -&gt; y)[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 43.000000 68.000000 C 43.000000 106.000000 43.000000 126.000000 43.000000 162.000000" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-1773020175)" /></g><mask id="d2-1773020175" maskUnits="userSpaceOnUse" x="-101" y="-118" width="305" height="451"> .d2-1773020175 .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="x"><g class="shape" ><rect x="1.000000" y="0.000000" width="85.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="43.500000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">x</text><g transform="translate(70 -16)" class="appendix-icon"><circle cx="16" cy="16" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="21" style="font-size: 16px;text-anchor:middle;">1</text></g><title>Total abstinence is easier than perfect moderation</title></g><g id="y"><g class="shape" ><rect x="0.000000" y="166.000000" width="86.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="43.000000" y="204.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">y</text><g transform="translate(70 150)" class="appendix-icon"><circle cx="16" cy="16" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="21" style="font-size: 16px;text-anchor:middle;">2</text></g><title>Gee, I feel kind of LIGHT in the head now,&#xA;knowing I can&#39;t make my satellite dish PAYMENTS!</title></g><g id="(x -&gt; y)[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 43.000000 68.000000 C 43.000000 106.000000 43.000000 126.000000 43.000000 162.000000" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-1773020175)" /></g><mask id="d2-1773020175" maskUnits="userSpaceOnUse" x="-101" y="-118" width="305" height="451">
<rect x="-101" y="-118" width="305" height="451" fill="white"></rect> <rect x="-101" y="-118" width="305" height="451" fill="white"></rect>
</mask><line x1="-41.000000" x2="424.000000" y1="283.000000" y2="283.000000" class=" stroke-B2" /><g class="appendix" x="-1" y="233" width="105" height="100%"><g transform="translate(0 333)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">1</text></g><text class="text" x="48" y="333" style="font-size: 16px;">Total abstinence is easier than perfect moderation</text> </mask><line x1="-41.000000" x2="424.000000" y1="283.000000" y2="283.000000" class=" stroke-B2" /><g class="appendix" x="-1" y="233" width="105" height="100%"><g transform="translate(0 333)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">1</text></g><text class="text" x="48" y="338" style="font-size: 16px;">Total abstinence is easier than perfect moderation</text>
<g transform="translate(0 385)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">2</text></g><text class="text" x="48" y="385" style="font-size: 16px;"><tspan x="48.000000" dy="0.000000">Gee, I feel kind of LIGHT in the head now,</tspan><tspan x="48.000000" dy="18.500000">knowing I can&#39;t make my satellite dish PAYMENTS!</tspan></text></g> <g transform="translate(0 385)" class="appendix-icon"><circle cx="16" cy="0" r="16" fill="white" stroke="#DEE1EB" /><text class="text-bold" x="16" y="5" style="font-size: 16px;text-anchor:middle;">2</text></g><text class="text" x="48" y="390" style="font-size: 16px;"><tspan x="48.000000" dy="0.000000">Gee, I feel kind of LIGHT in the head now,</tspan><tspan x="48.000000" dy="18.500000">knowing I can&#39;t make my satellite dish PAYMENTS!</tspan></text></g>
<style type="text/css"><![CDATA[ <style type="text/css"><![CDATA[
.text { .text {
font-family: "font-regular"; font-family: "font-regular";

Before

Width:  |  Height:  |  Size: 661 KiB

After

Width:  |  Height:  |  Size: 661 KiB

View file

@ -515,7 +515,12 @@ func drawConnection(writer io.Writer, labelMaskID string, connection d2target.Co
if connection.Opacity != 1.0 { if connection.Opacity != 1.0 {
opacityStyle = fmt.Sprintf(" style='opacity:%f'", connection.Opacity) opacityStyle = fmt.Sprintf(" style='opacity:%f'", connection.Opacity)
} }
fmt.Fprintf(writer, `<g id="%s"%s>`, svg.EscapeText(connection.ID), opacityStyle)
classStr := ""
if len(connection.Classes) > 0 {
classStr = fmt.Sprintf(` class="%s"`, strings.Join(connection.Classes, " "))
}
fmt.Fprintf(writer, `<g id="%s"%s%s>`, svg.EscapeText(connection.ID), opacityStyle, classStr)
var markerStart string var markerStart string
if connection.SrcArrow != d2target.NoArrowhead { if connection.SrcArrow != d2target.NoArrowhead {
id := arrowheadMarkerID(false, connection) id := arrowheadMarkerID(false, connection)
@ -919,7 +924,11 @@ func drawShape(writer io.Writer, diagramHash string, targetShape d2target.Shape,
if targetShape.BorderRadius != 0 && (targetShape.Type == d2target.ShapeClass || targetShape.Type == d2target.ShapeSQLTable) { if targetShape.BorderRadius != 0 && (targetShape.Type == d2target.ShapeClass || targetShape.Type == d2target.ShapeSQLTable) {
fmt.Fprint(writer, clipPathForBorderRadius(diagramHash, targetShape)) fmt.Fprint(writer, clipPathForBorderRadius(diagramHash, targetShape))
} }
fmt.Fprintf(writer, `<g id="%s"%s>`, svg.EscapeText(targetShape.ID), opacityStyle) classStr := ""
if len(targetShape.Classes) > 0 {
classStr = fmt.Sprintf(` class="%s"`, strings.Join(targetShape.Classes, " "))
}
fmt.Fprintf(writer, `<g id="%s"%s%s>`, svg.EscapeText(targetShape.ID), opacityStyle, classStr)
tl := geo.NewPoint(float64(targetShape.Pos.X), float64(targetShape.Pos.Y)) tl := geo.NewPoint(float64(targetShape.Pos.X), float64(targetShape.Pos.Y))
width := float64(targetShape.Width) width := float64(targetShape.Width)
height := float64(targetShape.Height) height := float64(targetShape.Height)

View file

@ -305,6 +305,8 @@ type Shape struct {
ID string `json:"id"` ID string `json:"id"`
Type string `json:"type"` Type string `json:"type"`
Classes []string `json:"classes,omitempty"`
Pos Point `json:"pos"` Pos Point `json:"pos"`
Width int `json:"width"` Width int `json:"width"`
Height int `json:"height"` Height int `json:"height"`
@ -425,6 +427,8 @@ func BaseShape() *Shape {
type Connection struct { type Connection struct {
ID string `json:"id"` ID string `json:"id"`
Classes []string `json:"classes,omitempty"`
Src string `json:"src"` Src string `json:"src"`
SrcArrow Arrowhead `json:"srcArrow"` SrcArrow Arrowhead `json:"srcArrow"`
SrcLabel string `json:"srcLabel"` SrcLabel string `json:"srcLabel"`

View file

@ -57,6 +57,16 @@ func TestCLI_E2E(t *testing.T) {
assert.Testdata(t, ".svg", svg) assert.Testdata(t, ".svg", svg)
}, },
}, },
{
name: "empty-layer",
run: func(t *testing.T, ctx context.Context, dir string, env *xos.Env) {
writeFile(t, dir, "empty-layer.d2", `layers: { x: {} }`)
err := runTestMain(t, ctx, dir, env, "empty-layer.d2")
assert.Success(t, err)
assert.TestdataDir(t, filepath.Join(dir, "empty-layer"))
},
},
{ {
name: "animation", name: "animation",
run: func(t *testing.T, ctx context.Context, dir string, env *xos.Env) { run: func(t *testing.T, ctx context.Context, dir string, env *xos.Env) {

View file

@ -1,16 +1,16 @@
<?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.3.0-HEAD" preserveAspectRatio="xMinYMin meet" viewBox="0 0 514 665"><svg id="d2-svg" width="514" height="665" viewBox="-206 -166 514 665"><style type="text/css"><![CDATA[ <?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.3.0-HEAD" preserveAspectRatio="xMinYMin meet" viewBox="0 0 514 665"><svg id="d2-svg" width="514" height="665" viewBox="-206 -166 514 665"><style type="text/css"><![CDATA[
.d2-1015877328 .text { .d2-3751819762 .text {
font-family: "d2-1015877328-font-regular"; font-family: "d2-3751819762-font-regular";
} }
@font-face { @font-face {
font-family: d2-1015877328-font-regular; font-family: d2-3751819762-font-regular;
src: url("data:application/font-woff;base64,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"); src: url("data:application/font-woff;base64,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");
} }
.d2-1015877328 .text-bold { .d2-3751819762 .text-bold {
font-family: "d2-1015877328-font-bold"; font-family: "d2-3751819762-font-bold";
} }
@font-face { @font-face {
font-family: d2-1015877328-font-bold; font-family: d2-3751819762-font-bold;
src: url("data:application/font-woff;base64,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"); src: url("data:application/font-woff;base64,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");
}]]></style><style type="text/css"><![CDATA[.shape { }]]></style><style type="text/css"><![CDATA[.shape {
shape-rendering: geometricPrecision; shape-rendering: geometricPrecision;
@ -25,92 +25,92 @@
opacity: 0.5; opacity: 0.5;
} }
.d2-1015877328 .fill-N1{fill:#0A0F25;} .d2-3751819762 .fill-N1{fill:#0A0F25;}
.d2-1015877328 .fill-N2{fill:#676C7E;} .d2-3751819762 .fill-N2{fill:#676C7E;}
.d2-1015877328 .fill-N3{fill:#9499AB;} .d2-3751819762 .fill-N3{fill:#9499AB;}
.d2-1015877328 .fill-N4{fill:#CFD2DD;} .d2-3751819762 .fill-N4{fill:#CFD2DD;}
.d2-1015877328 .fill-N5{fill:#DEE1EB;} .d2-3751819762 .fill-N5{fill:#DEE1EB;}
.d2-1015877328 .fill-N6{fill:#EEF1F8;} .d2-3751819762 .fill-N6{fill:#EEF1F8;}
.d2-1015877328 .fill-N7{fill:#FFFFFF;} .d2-3751819762 .fill-N7{fill:#FFFFFF;}
.d2-1015877328 .fill-B1{fill:#0D32B2;} .d2-3751819762 .fill-B1{fill:#0D32B2;}
.d2-1015877328 .fill-B2{fill:#0D32B2;} .d2-3751819762 .fill-B2{fill:#0D32B2;}
.d2-1015877328 .fill-B3{fill:#E3E9FD;} .d2-3751819762 .fill-B3{fill:#E3E9FD;}
.d2-1015877328 .fill-B4{fill:#E3E9FD;} .d2-3751819762 .fill-B4{fill:#E3E9FD;}
.d2-1015877328 .fill-B5{fill:#EDF0FD;} .d2-3751819762 .fill-B5{fill:#EDF0FD;}
.d2-1015877328 .fill-B6{fill:#F7F8FE;} .d2-3751819762 .fill-B6{fill:#F7F8FE;}
.d2-1015877328 .fill-AA2{fill:#4A6FF3;} .d2-3751819762 .fill-AA2{fill:#4A6FF3;}
.d2-1015877328 .fill-AA4{fill:#EDF0FD;} .d2-3751819762 .fill-AA4{fill:#EDF0FD;}
.d2-1015877328 .fill-AA5{fill:#F7F8FE;} .d2-3751819762 .fill-AA5{fill:#F7F8FE;}
.d2-1015877328 .fill-AB4{fill:#EDF0FD;} .d2-3751819762 .fill-AB4{fill:#EDF0FD;}
.d2-1015877328 .fill-AB5{fill:#F7F8FE;} .d2-3751819762 .fill-AB5{fill:#F7F8FE;}
.d2-1015877328 .stroke-N1{stroke:#0A0F25;} .d2-3751819762 .stroke-N1{stroke:#0A0F25;}
.d2-1015877328 .stroke-N2{stroke:#676C7E;} .d2-3751819762 .stroke-N2{stroke:#676C7E;}
.d2-1015877328 .stroke-N3{stroke:#9499AB;} .d2-3751819762 .stroke-N3{stroke:#9499AB;}
.d2-1015877328 .stroke-N4{stroke:#CFD2DD;} .d2-3751819762 .stroke-N4{stroke:#CFD2DD;}
.d2-1015877328 .stroke-N5{stroke:#DEE1EB;} .d2-3751819762 .stroke-N5{stroke:#DEE1EB;}
.d2-1015877328 .stroke-N6{stroke:#EEF1F8;} .d2-3751819762 .stroke-N6{stroke:#EEF1F8;}
.d2-1015877328 .stroke-N7{stroke:#FFFFFF;} .d2-3751819762 .stroke-N7{stroke:#FFFFFF;}
.d2-1015877328 .stroke-B1{stroke:#0D32B2;} .d2-3751819762 .stroke-B1{stroke:#0D32B2;}
.d2-1015877328 .stroke-B2{stroke:#0D32B2;} .d2-3751819762 .stroke-B2{stroke:#0D32B2;}
.d2-1015877328 .stroke-B3{stroke:#E3E9FD;} .d2-3751819762 .stroke-B3{stroke:#E3E9FD;}
.d2-1015877328 .stroke-B4{stroke:#E3E9FD;} .d2-3751819762 .stroke-B4{stroke:#E3E9FD;}
.d2-1015877328 .stroke-B5{stroke:#EDF0FD;} .d2-3751819762 .stroke-B5{stroke:#EDF0FD;}
.d2-1015877328 .stroke-B6{stroke:#F7F8FE;} .d2-3751819762 .stroke-B6{stroke:#F7F8FE;}
.d2-1015877328 .stroke-AA2{stroke:#4A6FF3;} .d2-3751819762 .stroke-AA2{stroke:#4A6FF3;}
.d2-1015877328 .stroke-AA4{stroke:#EDF0FD;} .d2-3751819762 .stroke-AA4{stroke:#EDF0FD;}
.d2-1015877328 .stroke-AA5{stroke:#F7F8FE;} .d2-3751819762 .stroke-AA5{stroke:#F7F8FE;}
.d2-1015877328 .stroke-AB4{stroke:#EDF0FD;} .d2-3751819762 .stroke-AB4{stroke:#EDF0FD;}
.d2-1015877328 .stroke-AB5{stroke:#F7F8FE;} .d2-3751819762 .stroke-AB5{stroke:#F7F8FE;}
.d2-1015877328 .background-color-N1{background-color:#0A0F25;} .d2-3751819762 .background-color-N1{background-color:#0A0F25;}
.d2-1015877328 .background-color-N2{background-color:#676C7E;} .d2-3751819762 .background-color-N2{background-color:#676C7E;}
.d2-1015877328 .background-color-N3{background-color:#9499AB;} .d2-3751819762 .background-color-N3{background-color:#9499AB;}
.d2-1015877328 .background-color-N4{background-color:#CFD2DD;} .d2-3751819762 .background-color-N4{background-color:#CFD2DD;}
.d2-1015877328 .background-color-N5{background-color:#DEE1EB;} .d2-3751819762 .background-color-N5{background-color:#DEE1EB;}
.d2-1015877328 .background-color-N6{background-color:#EEF1F8;} .d2-3751819762 .background-color-N6{background-color:#EEF1F8;}
.d2-1015877328 .background-color-N7{background-color:#FFFFFF;} .d2-3751819762 .background-color-N7{background-color:#FFFFFF;}
.d2-1015877328 .background-color-B1{background-color:#0D32B2;} .d2-3751819762 .background-color-B1{background-color:#0D32B2;}
.d2-1015877328 .background-color-B2{background-color:#0D32B2;} .d2-3751819762 .background-color-B2{background-color:#0D32B2;}
.d2-1015877328 .background-color-B3{background-color:#E3E9FD;} .d2-3751819762 .background-color-B3{background-color:#E3E9FD;}
.d2-1015877328 .background-color-B4{background-color:#E3E9FD;} .d2-3751819762 .background-color-B4{background-color:#E3E9FD;}
.d2-1015877328 .background-color-B5{background-color:#EDF0FD;} .d2-3751819762 .background-color-B5{background-color:#EDF0FD;}
.d2-1015877328 .background-color-B6{background-color:#F7F8FE;} .d2-3751819762 .background-color-B6{background-color:#F7F8FE;}
.d2-1015877328 .background-color-AA2{background-color:#4A6FF3;} .d2-3751819762 .background-color-AA2{background-color:#4A6FF3;}
.d2-1015877328 .background-color-AA4{background-color:#EDF0FD;} .d2-3751819762 .background-color-AA4{background-color:#EDF0FD;}
.d2-1015877328 .background-color-AA5{background-color:#F7F8FE;} .d2-3751819762 .background-color-AA5{background-color:#F7F8FE;}
.d2-1015877328 .background-color-AB4{background-color:#EDF0FD;} .d2-3751819762 .background-color-AB4{background-color:#EDF0FD;}
.d2-1015877328 .background-color-AB5{background-color:#F7F8FE;} .d2-3751819762 .background-color-AB5{background-color:#F7F8FE;}
.d2-1015877328 .color-N1{color:#0A0F25;} .d2-3751819762 .color-N1{color:#0A0F25;}
.d2-1015877328 .color-N2{color:#676C7E;} .d2-3751819762 .color-N2{color:#676C7E;}
.d2-1015877328 .color-N3{color:#9499AB;} .d2-3751819762 .color-N3{color:#9499AB;}
.d2-1015877328 .color-N4{color:#CFD2DD;} .d2-3751819762 .color-N4{color:#CFD2DD;}
.d2-1015877328 .color-N5{color:#DEE1EB;} .d2-3751819762 .color-N5{color:#DEE1EB;}
.d2-1015877328 .color-N6{color:#EEF1F8;} .d2-3751819762 .color-N6{color:#EEF1F8;}
.d2-1015877328 .color-N7{color:#FFFFFF;} .d2-3751819762 .color-N7{color:#FFFFFF;}
.d2-1015877328 .color-B1{color:#0D32B2;} .d2-3751819762 .color-B1{color:#0D32B2;}
.d2-1015877328 .color-B2{color:#0D32B2;} .d2-3751819762 .color-B2{color:#0D32B2;}
.d2-1015877328 .color-B3{color:#E3E9FD;} .d2-3751819762 .color-B3{color:#E3E9FD;}
.d2-1015877328 .color-B4{color:#E3E9FD;} .d2-3751819762 .color-B4{color:#E3E9FD;}
.d2-1015877328 .color-B5{color:#EDF0FD;} .d2-3751819762 .color-B5{color:#EDF0FD;}
.d2-1015877328 .color-B6{color:#F7F8FE;} .d2-3751819762 .color-B6{color:#F7F8FE;}
.d2-1015877328 .color-AA2{color:#4A6FF3;} .d2-3751819762 .color-AA2{color:#4A6FF3;}
.d2-1015877328 .color-AA4{color:#EDF0FD;} .d2-3751819762 .color-AA4{color:#EDF0FD;}
.d2-1015877328 .color-AA5{color:#F7F8FE;} .d2-3751819762 .color-AA5{color:#F7F8FE;}
.d2-1015877328 .color-AB4{color:#EDF0FD;} .d2-3751819762 .color-AB4{color:#EDF0FD;}
.d2-1015877328 .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><style type="text/css">.md em, .d2-3751819762 .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><style type="text/css">.md em,
.md dfn { .md dfn {
font-family: "d2-1015877328-font-italic"; font-family: "d2-3751819762-font-italic";
} }
.md b, .md b,
.md strong { .md strong {
font-family: "d2-1015877328-font-bold"; font-family: "d2-3751819762-font-bold";
} }
.md code, .md code,
.md kbd, .md kbd,
.md pre, .md pre,
.md samp { .md samp {
font-family: "d2-1015877328-font-mono"; font-family: "d2-3751819762-font-mono";
font-size: 1em; font-size: 1em;
} }
@ -126,7 +126,7 @@
margin: 0; margin: 0;
color: var(--color-fg-default); color: var(--color-fg-default);
background-color: transparent; /* we don't want to define the background color */ background-color: transparent; /* we don't want to define the background color */
font-family: "d2-1015877328-font-regular"; font-family: "d2-3751819762-font-regular";
font-size: 16px; font-size: 16px;
line-height: 1.5; line-height: 1.5;
word-wrap: break-word; word-wrap: break-word;
@ -340,7 +340,7 @@
margin-bottom: 16px; margin-bottom: 16px;
font-weight: 600; font-weight: 600;
line-height: 1.25; line-height: 1.25;
font-family: "d2-1015877328-font-regular"; font-family: "d2-3751819762-font-regular";
} }
.md h2 { .md h2 {
@ -838,7 +838,7 @@
.md .contains-task-list:dir(rtl) .task-list-item-checkbox { .md .contains-task-list:dir(rtl) .task-list-item-checkbox {
margin: 0 -1.6em 0.25em 0.2em; margin: 0 -1.6em 0.25em 0.2em;
} }
</style><style type="text/css"><![CDATA[@keyframes d2Transition-0 { </style><style type="text/css"><![CDATA[@keyframes d2Transition-d2-3751819762-0 {
0%, 0.000000% { 0%, 0.000000% {
opacity: 0; opacity: 0;
} }
@ -848,7 +848,7 @@
25.000000%, 100% { 25.000000%, 100% {
opacity: 0; opacity: 0;
} }
}@keyframes d2Transition-1 { }@keyframes d2Transition-d2-3751819762-1 {
0%, 24.982143% { 0%, 24.982143% {
opacity: 0; opacity: 0;
} }
@ -858,7 +858,7 @@
50.000000%, 100% { 50.000000%, 100% {
opacity: 0; opacity: 0;
} }
}@keyframes d2Transition-2 { }@keyframes d2Transition-d2-3751819762-2 {
0%, 49.982143% { 0%, 49.982143% {
opacity: 0; opacity: 0;
} }
@ -868,23 +868,23 @@
75.000000%, 100% { 75.000000%, 100% {
opacity: 0; opacity: 0;
} }
}@keyframes d2Transition-3 { }@keyframes d2Transition-d2-3751819762-3 {
0%, 74.982143% { 0%, 74.982143% {
opacity: 0; opacity: 0;
} }
75.000000%, 100.000000% { 75.000000%, 100.000000% {
opacity: 1; opacity: 1;
} }
}]]></style><g style="animation: d2Transition-0 5600ms infinite" class="d2-1015877328" width="412" height="247" viewBox="-206 -166 412 247"><rect x="-206.000000" y="-166.000000" width="412.000000" height="247.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><g id="&#34;Chicken&#39;s plan&#34;"><g class="shape" ></g><text x="0.000000" y="-30.000000" class="text fill-N1" style="text-anchor:middle;font-size:35px">Chicken&#39;s plan</text></g><mask id="d2-1015877328" maskUnits="userSpaceOnUse" x="-206" y="-166" width="412" height="247"> }]]></style><g style="animation: d2Transition-d2-3751819762-0 5600ms infinite" class="d2-3751819762" width="412" height="247" viewBox="-206 -166 412 247"><rect x="-206.000000" y="-166.000000" width="412.000000" height="247.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><g id="&#34;Chicken&#39;s plan&#34;"><g class="shape" ></g><text x="0.000000" y="-30.000000" class="text fill-N1" style="text-anchor:middle;font-size:35px">Chicken&#39;s plan</text></g><mask id="d2-3751819762" maskUnits="userSpaceOnUse" x="-206" y="-166" width="412" height="247">
<rect x="-206" y="-166" width="412" height="247" fill="white"></rect> <rect x="-206" y="-166" width="412" height="247" fill="white"></rect>
</mask></g><g style="animation: d2Transition-1 5600ms infinite" class="d2-1015877328" width="412" height="333" viewBox="-131 -166 412 333"><rect x="-131.000000" y="-166.000000" width="412.000000" height="333.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><g id="Approach road"><g class="shape" ><rect x="0.000000" y="0.000000" width="150.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="75.000000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Approach road</text></g><g id="&#34;Chicken&#39;s plan&#34;"><g class="shape" ></g><text x="75.000000" y="-30.000000" class="text fill-N1" style="text-anchor:middle;font-size:35px">Chicken&#39;s plan</text></g><mask id="d2-1041619556" maskUnits="userSpaceOnUse" x="-131" y="-166" width="412" height="333"> </mask></g><g style="animation: d2Transition-d2-3751819762-1 5600ms infinite" class="d2-3751819762" width="412" height="333" viewBox="-131 -166 412 333"><rect x="-131.000000" y="-166.000000" width="412.000000" height="333.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><g id="Approach road"><g class="shape" ><rect x="0.000000" y="0.000000" width="150.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="75.000000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Approach road</text></g><g id="&#34;Chicken&#39;s plan&#34;"><g class="shape" ></g><text x="75.000000" y="-30.000000" class="text fill-N1" style="text-anchor:middle;font-size:35px">Chicken&#39;s plan</text></g><mask id="d2-3302893893" maskUnits="userSpaceOnUse" x="-131" y="-166" width="412" height="333">
<rect x="-131" y="-166" width="412" height="333" fill="white"></rect> <rect x="-131" y="-166" width="412" height="333" fill="white"></rect>
</mask></g><g style="animation: d2Transition-2 5600ms infinite" class="d2-1015877328" width="412" height="499" viewBox="-131 -166 412 499"><rect x="-131.000000" y="-166.000000" width="412.000000" height="499.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><g id="Approach road"><g class="shape" ><rect x="0.000000" y="0.000000" width="150.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="75.000000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Approach road</text></g><g id="Cross road"><g class="shape" ><rect x="15.000000" y="166.000000" width="120.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="75.000000" y="204.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Cross road</text></g><g id="&#34;Chicken&#39;s plan&#34;"><g class="shape" ></g><text x="75.000000" y="-30.000000" class="text fill-N1" style="text-anchor:middle;font-size:35px">Chicken&#39;s plan</text></g><g id="(Approach road -&gt; Cross road)[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 75.000000 68.000000 C 75.000000 106.000000 75.000000 126.000000 75.000000 162.000000" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-681643259)" /></g><mask id="d2-681643259" maskUnits="userSpaceOnUse" x="-131" y="-166" width="412" height="499"> </mask></g><g style="animation: d2Transition-d2-3751819762-2 5600ms infinite" class="d2-3751819762" width="412" height="499" viewBox="-131 -166 412 499"><rect x="-131.000000" y="-166.000000" width="412.000000" height="499.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><g id="Approach road"><g class="shape" ><rect x="0.000000" y="0.000000" width="150.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="75.000000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Approach road</text></g><g id="Cross road"><g class="shape" ><rect x="15.000000" y="166.000000" width="120.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="75.000000" y="204.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Cross road</text></g><g id="&#34;Chicken&#39;s plan&#34;"><g class="shape" ></g><text x="75.000000" y="-30.000000" class="text fill-N1" style="text-anchor:middle;font-size:35px">Chicken&#39;s plan</text></g><g id="(Approach road -&gt; Cross road)[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 75.000000 68.000000 C 75.000000 106.000000 75.000000 126.000000 75.000000 162.000000" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-2369911030)" /></g><mask id="d2-2369911030" maskUnits="userSpaceOnUse" x="-131" y="-166" width="412" height="499">
<rect x="-131" y="-166" width="412" height="499" fill="white"></rect> <rect x="-131" y="-166" width="412" height="499" fill="white"></rect>
</mask></g><g style="animation: d2Transition-3 5600ms infinite" class="d2-1015877328" width="412" height="665" viewBox="-104 -166 412 665"><rect x="-104.000000" y="-166.000000" width="412.000000" height="665.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><g id="Approach road"><g class="shape" ><rect x="27.000000" y="0.000000" width="150.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="102.000000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Approach road</text></g><g id="Cross road"><g class="shape" ><rect x="42.000000" y="166.000000" width="120.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="102.000000" y="204.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Cross road</text></g><g id="Make you wonder why"><g class="shape" ><rect x="0.000000" y="332.000000" width="203.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="101.500000" y="370.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Make you wonder why</text></g><g id="&#34;Chicken&#39;s plan&#34;"><g class="shape" ></g><text x="102.000000" y="-30.000000" class="text fill-N1" style="text-anchor:middle;font-size:35px">Chicken&#39;s plan</text></g><g id="(Approach road -&gt; Cross road)[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 101.500000 68.000000 C 101.500000 106.000000 101.500000 126.000000 101.500000 162.000000" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-2302375566)" /></g><g id="(Cross road -&gt; Make you wonder why)[0]"><path d="M 101.500000 234.000000 C 101.500000 272.000000 101.500000 292.000000 101.500000 328.000000" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-2302375566)" /></g><mask id="d2-2302375566" maskUnits="userSpaceOnUse" x="-104" y="-166" width="412" height="665"> </mask></g><g style="animation: d2Transition-d2-3751819762-3 5600ms infinite" class="d2-3751819762" width="412" height="665" viewBox="-104 -166 412 665"><rect x="-104.000000" y="-166.000000" width="412.000000" height="665.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><g id="Approach road"><g class="shape" ><rect x="27.000000" y="0.000000" width="150.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="102.000000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Approach road</text></g><g id="Cross road"><g class="shape" ><rect x="42.000000" y="166.000000" width="120.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="102.000000" y="204.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Cross road</text></g><g id="Make you wonder why"><g class="shape" ><rect x="0.000000" y="332.000000" width="203.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="101.500000" y="370.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Make you wonder why</text></g><g id="&#34;Chicken&#39;s plan&#34;"><g class="shape" ></g><text x="102.000000" y="-30.000000" class="text fill-N1" style="text-anchor:middle;font-size:35px">Chicken&#39;s plan</text></g><g id="(Approach road -&gt; Cross road)[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 101.500000 68.000000 C 101.500000 106.000000 101.500000 126.000000 101.500000 162.000000" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-1488407051)" /></g><g id="(Cross road -&gt; Make you wonder why)[0]"><path d="M 101.500000 234.000000 C 101.500000 272.000000 101.500000 292.000000 101.500000 328.000000" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-1488407051)" /></g><mask id="d2-1488407051" maskUnits="userSpaceOnUse" x="-104" y="-166" width="412" height="665">
<rect x="-104" y="-166" width="412" height="665" fill="white"></rect> <rect x="-104" y="-166" width="412" height="665" fill="white"></rect>
</mask></g></svg></svg> </mask></g></svg></svg>

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View file

@ -0,0 +1,88 @@
<?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.3.0-HEAD" preserveAspectRatio="xMinYMin meet" viewBox="0 0 200 200"><svg id="d2-svg" class="d2-121760133" width="200" height="200" viewBox="-100 -100 200 200"><rect x="-100.000000" y="-100.000000" width="200.000000" height="200.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><style type="text/css"><![CDATA[]]></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-121760133 .fill-N1{fill:#0A0F25;}
.d2-121760133 .fill-N2{fill:#676C7E;}
.d2-121760133 .fill-N3{fill:#9499AB;}
.d2-121760133 .fill-N4{fill:#CFD2DD;}
.d2-121760133 .fill-N5{fill:#DEE1EB;}
.d2-121760133 .fill-N6{fill:#EEF1F8;}
.d2-121760133 .fill-N7{fill:#FFFFFF;}
.d2-121760133 .fill-B1{fill:#0D32B2;}
.d2-121760133 .fill-B2{fill:#0D32B2;}
.d2-121760133 .fill-B3{fill:#E3E9FD;}
.d2-121760133 .fill-B4{fill:#E3E9FD;}
.d2-121760133 .fill-B5{fill:#EDF0FD;}
.d2-121760133 .fill-B6{fill:#F7F8FE;}
.d2-121760133 .fill-AA2{fill:#4A6FF3;}
.d2-121760133 .fill-AA4{fill:#EDF0FD;}
.d2-121760133 .fill-AA5{fill:#F7F8FE;}
.d2-121760133 .fill-AB4{fill:#EDF0FD;}
.d2-121760133 .fill-AB5{fill:#F7F8FE;}
.d2-121760133 .stroke-N1{stroke:#0A0F25;}
.d2-121760133 .stroke-N2{stroke:#676C7E;}
.d2-121760133 .stroke-N3{stroke:#9499AB;}
.d2-121760133 .stroke-N4{stroke:#CFD2DD;}
.d2-121760133 .stroke-N5{stroke:#DEE1EB;}
.d2-121760133 .stroke-N6{stroke:#EEF1F8;}
.d2-121760133 .stroke-N7{stroke:#FFFFFF;}
.d2-121760133 .stroke-B1{stroke:#0D32B2;}
.d2-121760133 .stroke-B2{stroke:#0D32B2;}
.d2-121760133 .stroke-B3{stroke:#E3E9FD;}
.d2-121760133 .stroke-B4{stroke:#E3E9FD;}
.d2-121760133 .stroke-B5{stroke:#EDF0FD;}
.d2-121760133 .stroke-B6{stroke:#F7F8FE;}
.d2-121760133 .stroke-AA2{stroke:#4A6FF3;}
.d2-121760133 .stroke-AA4{stroke:#EDF0FD;}
.d2-121760133 .stroke-AA5{stroke:#F7F8FE;}
.d2-121760133 .stroke-AB4{stroke:#EDF0FD;}
.d2-121760133 .stroke-AB5{stroke:#F7F8FE;}
.d2-121760133 .background-color-N1{background-color:#0A0F25;}
.d2-121760133 .background-color-N2{background-color:#676C7E;}
.d2-121760133 .background-color-N3{background-color:#9499AB;}
.d2-121760133 .background-color-N4{background-color:#CFD2DD;}
.d2-121760133 .background-color-N5{background-color:#DEE1EB;}
.d2-121760133 .background-color-N6{background-color:#EEF1F8;}
.d2-121760133 .background-color-N7{background-color:#FFFFFF;}
.d2-121760133 .background-color-B1{background-color:#0D32B2;}
.d2-121760133 .background-color-B2{background-color:#0D32B2;}
.d2-121760133 .background-color-B3{background-color:#E3E9FD;}
.d2-121760133 .background-color-B4{background-color:#E3E9FD;}
.d2-121760133 .background-color-B5{background-color:#EDF0FD;}
.d2-121760133 .background-color-B6{background-color:#F7F8FE;}
.d2-121760133 .background-color-AA2{background-color:#4A6FF3;}
.d2-121760133 .background-color-AA4{background-color:#EDF0FD;}
.d2-121760133 .background-color-AA5{background-color:#F7F8FE;}
.d2-121760133 .background-color-AB4{background-color:#EDF0FD;}
.d2-121760133 .background-color-AB5{background-color:#F7F8FE;}
.d2-121760133 .color-N1{color:#0A0F25;}
.d2-121760133 .color-N2{color:#676C7E;}
.d2-121760133 .color-N3{color:#9499AB;}
.d2-121760133 .color-N4{color:#CFD2DD;}
.d2-121760133 .color-N5{color:#DEE1EB;}
.d2-121760133 .color-N6{color:#EEF1F8;}
.d2-121760133 .color-N7{color:#FFFFFF;}
.d2-121760133 .color-B1{color:#0D32B2;}
.d2-121760133 .color-B2{color:#0D32B2;}
.d2-121760133 .color-B3{color:#E3E9FD;}
.d2-121760133 .color-B4{color:#E3E9FD;}
.d2-121760133 .color-B5{color:#EDF0FD;}
.d2-121760133 .color-B6{color:#F7F8FE;}
.d2-121760133 .color-AA2{color:#4A6FF3;}
.d2-121760133 .color-AA4{color:#EDF0FD;}
.d2-121760133 .color-AA5{color:#F7F8FE;}
.d2-121760133 .color-AB4{color:#EDF0FD;}
.d2-121760133 .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><mask id="d2-121760133" maskUnits="userSpaceOnUse" x="-100" y="-100" width="200" height="200">
<rect x="-100" y="-100" width="200" height="200" fill="white"></rect>
</mask></svg></svg>

After

Width:  |  Height:  |  Size: 5.8 KiB

View file

@ -271,9 +271,9 @@ m6_desc -> queue.M6
name: "unnamed_class_table_code", name: "unnamed_class_table_code",
script: ` script: `
class -> users -> code class2 -> users -> code
class: "" { class2: "" {
shape: class shape: class
-num: int -num: int
-timeout: int -timeout: int
@ -318,7 +318,7 @@ ico: {
name: "only_header_class_table", name: "only_header_class_table",
script: ` script: `
class: RefreshAuthorizationPolicyProtocolServerSideTranslatorProtocolBuffer { class2: RefreshAuthorizationPolicyProtocolServerSideTranslatorProtocolBuffer {
shape: class shape: class
} }
@ -331,7 +331,7 @@ table with short col: RefreshAuthorizationPolicyCache {
ok ok
} }
class -> table -> table with short col class2 -> table -> table with short col
`, `,
}, },
{ {

View file

@ -12,6 +12,68 @@ var testMarkdown string
func testStable(t *testing.T) { func testStable(t *testing.T) {
tcs := []testCase{ tcs := []testCase{
{
name: "legend_with_near_key",
script: `
direction: right
x -> y: {
style.stroke: green
}
y -> z: {
style.stroke: red
}
legend: {
near: bottom-center
color1: foo {
shape: text
style.font-color: green
}
color2: bar {
shape: text
style.font-color: red
}
}
`,
},
{
name: "near_keys_for_container",
script: `
x: {
near: top-left
a -> b
c -> d
}
y: {
near: top-right
a -> b
c -> d
}
z: {
near: bottom-center
a -> b
c -> d
}
a: {
near: top-center
b: {
c
}
}
b: {
near: bottom-right
a: {
c: {
d
}
}
}
`,
},
{ {
name: "class_and_sqlTable_border_radius", name: "class_and_sqlTable_border_radius",
script: ` script: `
@ -143,6 +205,12 @@ logs: { shape: page; style.multiple: true }
network.data processor -> api server network.data processor -> api server
`, `,
}, },
{
name: "edge-label-overflow",
script: `student -> committee chair: Apply for appeal
student <- committee chair: Deny. Need more information
committee chair -> committee: Accept appeal`,
},
{ {
name: "mono-edge", name: "mono-edge",
script: `direction: right script: `direction: right
@ -1481,8 +1549,13 @@ finally: {
sequence: { sequence: {
shape: sequence_diagram shape: sequence_diagram
# items appear in this order # items appear in this order
scorer scorer {
concept style.stroke: red
style.stroke-dash: 2
}
concept {
style.stroke-width: 6
}
essayRubric essayRubric
item item
itemOutcome itemOutcome
@ -1932,9 +2005,9 @@ x -> y
name: "unnamed_only_width", name: "unnamed_only_width",
script: ` script: `
class -> users -> code -> package -> no width class2 -> users -> code -> package -> no width
class: "" { class2: "" {
shape: class shape: class
-num: int -num: int
-timeout: int -timeout: int
@ -1964,7 +2037,7 @@ package: "" { shape: package }
no width: "" no width: ""
class.width: 512 class2.width: 512
users.width: 512 users.width: 512
code.width: 512 code.width: 512
package.width: 512 package.width: 512
@ -1974,9 +2047,9 @@ package.width: 512
name: "unnamed_only_height", name: "unnamed_only_height",
script: ` script: `
class -> users -> code -> package -> no height class2 -> users -> code -> package -> no height
class: "" { class2: "" {
shape: class shape: class
-num: int -num: int
-timeout: int -timeout: int
@ -2006,7 +2079,7 @@ package: "" { shape: package }
no height: "" no height: ""
class.height: 512 class2.height: 512
users.height: 512 users.height: 512
code.height: 512 code.height: 512
package.height: 512 package.height: 512
@ -2301,6 +2374,29 @@ y: {
z: { z: {
near: center-left near: center-left
} }
`,
},
{
name: "classes",
script: `classes: {
dragon_ball: {
label: ""
shape: circle
style.fill: orange
style.stroke-width: 0
width: 50
}
path: {
label: "then"
style.stroke-width: 4
}
}
nostar: { class: dragon_ball }
1star: { label: "*"; class: dragon_ball }
2star: { label: "**"; class: dragon_ball }
nostar -> 1star: { class: path }
1star -> 2star: { class: path }
`, `,
}, },
{ {
@ -2465,6 +2561,10 @@ scenarios: {
}`, }`,
}, },
loadFromFile(t, "arrowhead_scaling"), loadFromFile(t, "arrowhead_scaling"),
loadFromFile(t, "teleport_grid"),
loadFromFile(t, "dagger_grid"),
loadFromFile(t, "grid_tests"),
loadFromFile(t, "executive_grid"),
} }
runa(t, tcs) runa(t, tcs)

90
e2etests/testdata/files/dagger_grid.d2 vendored Normal file
View file

@ -0,0 +1,90 @@
grid-rows: 5
style.fill: black
flow1: "" {
width: 120
style: {fill: white; stroke: cornflowerblue; stroke-width: 10}
}
flow2: "" {
width: 120
style: {fill: white; stroke: cornflowerblue; stroke-width: 10}
}
flow3: "" {
width: 120
style: {fill: white; stroke: cornflowerblue; stroke-width: 10}
}
flow4: "" {
width: 120
style: {fill: white; stroke: cornflowerblue; stroke-width: 10}
}
flow5: "" {
width: 120
style: {fill: white; stroke: cornflowerblue; stroke-width: 10}
}
flow6: "" {
width: 240
style: {fill: white; stroke: cornflowerblue; stroke-width: 10}
}
flow7: "" {
width: 80
style: {fill: white; stroke: cornflowerblue; stroke-width: 10}
}
flow8: "" {
width: 160
style: {fill: white; stroke: cornflowerblue; stroke-width: 10}
}
flow9: "" {
width: 160
style: {fill: white; stroke: cornflowerblue; stroke-width: 10}
}
DAGGER ENGINE: {
width: 800
style: {
fill: beige
stroke: darkcyan
font-color: blue
stroke-width: 8
}
}
ANY DOCKER COMPATIBLE RUNTIME: {
width: 800
style: {
fill: lightcyan
stroke: darkcyan
font-color: black
stroke-width: 8
}
icon: https://icons.terrastruct.com/dev%2Fdocker.svg
}
ANY CI: {
style: {
fill: gold
stroke: maroon
font-color: maroon
stroke-width: 8
}
}
WINDOWS.style: {
font-color: white
fill: darkcyan
stroke: black
}
LINUX.style: {
font-color: white
fill: darkcyan
stroke: black
}
MACOS.style: {
font-color: white
fill: darkcyan
stroke: black
}
KUBERNETES.style: {
font-color: white
fill: darkcyan
stroke: black
}

View file

@ -0,0 +1,16 @@
grid-rows: 3
Executive Services.width: 1000
I/O\nManager.width: 100
I/O\nManager.height: 200
Security\nReference\nMonitor.width: 100
IPC\nManager.width: 100
Virtual\nMemory\nManager\n(VMM).width: 100
Process\nManager.width: 100
PnP\nManager.width: 100
Power\nManager.width: 100
# TODO recursive grids
Window\nManager\n\nGDI.width: 100
Object Manager.width: 1000

134
e2etests/testdata/files/grid_tests.d2 vendored Normal file
View file

@ -0,0 +1,134 @@
rows 1: {
grid-rows: 1
a
b
c
d
e
f
g
}
columns 1: {
grid-columns: 1
a
b
c
d
e
f
g
}
rows 2: {
grid-rows: 2
a
b
c
d
e
f
g
}
columns 2: {
grid-columns: 2
a
b
c
d
e
f
g
}
rows 2 columns 2: {
grid-rows: 2
grid-columns: 2
a
b
c
d
e
f
g
}
columns 2 rows 2: {
grid-columns: 2
grid-rows: 2
a
b
c
d
e
f
g
}
rows 3 columns 3: {
grid-rows: 3
grid-columns: 3
a
b
c
d
e
f
g
}
columns 3 rows 3: {
grid-columns: 3
grid-rows: 3
a
b
c
d
e
f
g
}
rows 3: {
grid-rows: 3
a
b
c
d
e
f
g
}
columns 3: {
grid-columns: 3
a
b
c
d
e
f
g
}
widths heights: {
grid-rows: 3
grid-columns: 3
a w200.width: 200
b h300.height: 300
c
d h200.height: 200
e
f w400.width: 400
g
h
i
}

View file

@ -0,0 +1,70 @@
direction: right
users -- via -- teleport
teleport -> jita: "all connections audited and logged"
teleport -> infra
teleport -> identity provider
teleport <- identity provider
users: "" {
grid-columns: 1
Engineers: {
shape: circle
icon: https://icons.terrastruct.com/essentials%2F365-user.svg
}
Machines: {
shape: circle
icon: https://icons.terrastruct.com/aws%2FCompute%2FCompute.svg
}
}
via: "" {
grid-columns: 1
https: "HTTPS://"
kubectl: "> kubectl"
tsh: "> tsh"
api: "> api"
db clients: "DB Clients"
}
teleport: Teleport {
grid-rows: 2
inp: |md
# Identity Native Proxy
| {
width: 300
}
Audit Log.icon: https://icons.terrastruct.com/tech%2Flaptop.svg
Cert Authority.icon: https://icons.terrastruct.com/azure%2FWeb%20Service%20Color%2FApp%20Service%20Certificates.svg
}
jita: "Just-in-time Access via" {
grid-rows: 1
Slack.icon: https://icons.terrastruct.com/dev%2Fslack.svg
Mattermost
Jira
Pagerduty
Email.icon: https://icons.terrastruct.com/aws%2F_General%2FAWS-Email_light-bg.svg
}
infra: Infrastructure {
grid-rows: 2
ssh.icon: https://icons.terrastruct.com/essentials%2F112-server.svg
Kubernetes.icon: https://icons.terrastruct.com/azure%2F_Companies%2FKubernetes.svg
My SQL.icon: https://icons.terrastruct.com/dev%2Fmysql.svg
MongoDB.icon: https://icons.terrastruct.com/dev%2Fmongodb.svg
PSQL.icon: https://icons.terrastruct.com/dev%2Fpostgresql.svg
Windows.icon: https://icons.terrastruct.com/dev%2Fwindows.svg
}
identity provider: Indentity Provider {
icon: https://icons.terrastruct.com/azure%2FIdentity%20Service%20Color%2FIdentity%20governance.svg
}

View file

@ -10,7 +10,7 @@
"x": 0, "x": 0,
"y": 41 "y": 41
}, },
"width": 334, "width": 360,
"height": 640, "height": 640,
"opacity": 1, "opacity": 1,
"strokeDash": 0, "strokeDash": 0,
@ -52,7 +52,7 @@
"x": 20, "x": 20,
"y": 106 "y": 106
}, },
"width": 294, "width": 320,
"height": 545, "height": 545,
"opacity": 1, "opacity": 1,
"strokeDash": 0, "strokeDash": 0,
@ -91,7 +91,7 @@
"id": "NETWORK.CELL TOWER.satellites", "id": "NETWORK.CELL TOWER.satellites",
"type": "stored_data", "type": "stored_data",
"pos": { "pos": {
"x": 87, "x": 100,
"y": 195 "y": 195
}, },
"width": 161, "width": 161,
@ -132,7 +132,7 @@
"id": "NETWORK.CELL TOWER.transmitter", "id": "NETWORK.CELL TOWER.transmitter",
"type": "rectangle", "type": "rectangle",
"pos": { "pos": {
"x": 92, "x": 105,
"y": 496 "y": 496
}, },
"width": 151, "width": 151,
@ -173,7 +173,7 @@
"id": "costumes", "id": "costumes",
"type": "sql_table", "type": "sql_table",
"pos": { "pos": {
"x": 374, "x": 401,
"y": 100 "y": 100
}, },
"width": 311, "width": 311,
@ -330,7 +330,7 @@
"id": "monsters", "id": "monsters",
"type": "sql_table", "type": "sql_table",
"pos": { "pos": {
"x": 374, "x": 401,
"y": 401 "y": 401
}, },
"width": 311, "width": 311,
@ -512,19 +512,19 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 151, "x": 163,
"y": 262 "y": 262
}, },
{ {
"x": 108, "x": 114.4,
"y": 355.6 "y": 355.6
}, },
{ {
"x": 108.05, "x": 114.45,
"y": 402.6 "y": 402.6
}, },
{ {
"x": 151.25, "x": 163.25,
"y": 497 "y": 497
} }
], ],
@ -561,19 +561,19 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 167, "x": 180,
"y": 262 "y": 262
}, },
{ {
"x": 167, "x": 180.2,
"y": 355.6 "y": 355.6
}, },
{ {
"x": 167, "x": 180.25,
"y": 402.6 "y": 402.6
}, },
{ {
"x": 167, "x": 180.25,
"y": 497 "y": 497
} }
], ],
@ -610,19 +610,19 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 183, "x": 198,
"y": 262 "y": 262
}, },
{ {
"x": 226, "x": 246.2,
"y": 355.6 "y": 355.6
}, },
{ {
"x": 225.95, "x": 246.05,
"y": 402.6 "y": 402.6
}, },
{ {
"x": 182.75, "x": 197.25,
"y": 497 "y": 497
} }
], ],
@ -659,19 +659,19 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 529.5, "x": 556,
"y": 280 "y": 280
}, },
{ {
"x": 529.5, "x": 556,
"y": 328.4 "y": 328.4
}, },
{ {
"x": 529.5, "x": 556,
"y": 352.7 "y": 352.7
}, },
{ {
"x": 529.5, "x": 556,
"y": 401.5 "y": 401.5
} }
], ],

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View file

@ -10,7 +10,7 @@
"x": 0, "x": 0,
"y": 41 "y": 41
}, },
"width": 334, "width": 360,
"height": 412, "height": 412,
"opacity": 1, "opacity": 1,
"strokeDash": 0, "strokeDash": 0,
@ -52,7 +52,7 @@
"x": 20, "x": 20,
"y": 106 "y": 106
}, },
"width": 294, "width": 320,
"height": 317, "height": 317,
"opacity": 1, "opacity": 1,
"strokeDash": 0, "strokeDash": 0,
@ -91,7 +91,7 @@
"id": "NETWORK.CELL TOWER.satellites", "id": "NETWORK.CELL TOWER.satellites",
"type": "stored_data", "type": "stored_data",
"pos": { "pos": {
"x": 87, "x": 100,
"y": 138 "y": 138
}, },
"width": 161, "width": 161,
@ -132,7 +132,7 @@
"id": "NETWORK.CELL TOWER.transmitter", "id": "NETWORK.CELL TOWER.transmitter",
"type": "rectangle", "type": "rectangle",
"pos": { "pos": {
"x": 92, "x": 105,
"y": 325 "y": 325
}, },
"width": 151, "width": 151,
@ -198,19 +198,19 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 142, "x": 152,
"y": 205 "y": 205
}, },
{ {
"x": 106.19999999999999, "x": 112.19999999999999,
"y": 253 "y": 253
}, },
{ {
"x": 106.25, "x": 112.25,
"y": 277.2 "y": 277.2
}, },
{ {
"x": 142.25, "x": 152.25,
"y": 326 "y": 326
} }
], ],
@ -247,19 +247,19 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 167, "x": 180,
"y": 205 "y": 205
}, },
{ {
"x": 167, "x": 180.2,
"y": 253 "y": 253
}, },
{ {
"x": 167, "x": 180.25,
"y": 277.2 "y": 277.2
}, },
{ {
"x": 167, "x": 180.25,
"y": 326 "y": 326
} }
], ],
@ -296,19 +296,19 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 192, "x": 208,
"y": 205 "y": 205
}, },
{ {
"x": 227.8, "x": 248.2,
"y": 253 "y": 253
}, },
{ {
"x": 227.75, "x": 248.25,
"y": 277.2 "y": 277.2
}, },
{ {
"x": 191.75, "x": 208.25,
"y": 326 "y": 326
} }
], ],

View file

@ -1,16 +1,16 @@
<?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.3.0-HEAD" preserveAspectRatio="xMinYMin meet" viewBox="0 0 336 454"><svg id="d2-svg" class="d2-2665946492" width="336" height="454" viewBox="-1 0 336 454"><rect x="-1.000000" y="0.000000" width="336.000000" height="454.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><style type="text/css"><![CDATA[ <?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.3.0-HEAD" preserveAspectRatio="xMinYMin meet" viewBox="0 0 362 454"><svg id="d2-svg" class="d2-3084549463" width="362" height="454" viewBox="-1 0 362 454"><rect x="-1.000000" y="0.000000" width="362.000000" height="454.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><style type="text/css"><![CDATA[
.d2-2665946492 .text-mono { .d2-3084549463 .text-mono {
font-family: "d2-2665946492-font-mono"; font-family: "d2-3084549463-font-mono";
} }
@font-face { @font-face {
font-family: d2-2665946492-font-mono; font-family: d2-3084549463-font-mono;
src: url("data:application/font-woff;base64,d09GRgABAAAAAA0oAAoAAAAAF6wAAgm6AAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAAA9AAAAGAAAABgld/X+GNtYXAAAAFUAAAAaAAAAHwBUgHZZ2x5ZgAAAbwAAAOxAAAEVLnFpmFoZWFkAAAFcAAAADYAAAA2GanOOmhoZWEAAAWoAAAAJAAAACQGMwCXaG10eAAABcwAAABAAAAAQCWABFRsb2NhAAAGDAAAACIAAAAiCM4Hkm1heHAAAAYwAAAAIAAAACAARAJhbmFtZQAABlAAAAa4AAAQztydAx9wb3N0AAANCAAAACAAAAAg/7gAMwADAlgBkAAFAAACigJYAAAASwKKAlgAAAFeADIBIwAAAgsFCQMEAwICBCAAAvcCADgDAAAAAAAAAABBREJPAEAAIP//Au7/BgAAA9gBEWAAAZ8AAAAAAeYClAAAACAAA3icVMxPqkFhAIfh57vfuf4enCXYimRwMlBSxnYpUSzFSn4iE+/wGbwoqoJW44ROp2JpZaO3c3BMvrLW29q/Jc88cs8t11xy/jx+K/5UjX8DQyNjE1OtmbkFLwAAAP//AQAA//9nyhUfeJxUk0tsG1UUhs89Y880wbSZOmPTJrE9uc1MEtl5+I49SYr8SnDsJC22aZTSODZtrSa4CXlIpQJFJUi0VKJIEymiLbgsyAJVSCwpbGDDogtUAasi0Q2LKlKlioUXdOEJGtuRQCPNHGnu+fWf8/0X7BABwOO4Axy0gAOOggTARFnskVWVCoKuupmuUy+KEfKnaRCS1mzhK1tb39iGE88S5z/Andry2EeLi5mnez8Url799Cl5BAg+ABxBA1pABHAKTFUUlfI852ROqlJhz/uzV5SP2Np8fzwpPDkbeR4lq6WSvjI6umKeQ6O29vAhAACB+H4V+7ECXQD2bkUJaeEwC7rcgqLQbp6X2l0uFgzrbp4nxeyHMzPXZ0/mOwePJfqiC5q2EA2kvIPqRUf2zuXyndyQL9Qhx9/N5d5LKJQFggCAMAeAfWjAIcsnE1nQJbXzVGXBcEhTKJ37aqfyxfYb6fXV1fU0Gvcr976d+GRz83rd2wYAHkUDXqrvSzp4Nshn5o+kzfybzKCRfDT5fBIIFAHIi+bZEBNpSJaoyKTi7i75fHd3ErlkslabbMx8AQAn0ABH3ZHICBOclBOkC2c40l78da/w0zoa5gOSfmG+Tc5+/JvVcwMAu9AAe6NHlm7kyGto1B40NVMA2IYGdNT/O91MdzKRilo4rFOBo5xKPSiJqUt5n827cCljF5DrKbyaV5Dj7WiYe+UyeaW2RlK+udnOLdMkuNU5O+czv7e0cwDIowHOA21FCYlMtERdLknM5X+PIrZkGh80zNLN4csaOVNbI5WbwSVm3geEof0q9mIFjlgO/0PawsGrDRrdFm/in9qIxTamGu/p+fnp6fl5R+7ucvl2JnO7vHw3lzaubd66tXnNsPiWmnwPg7vJ11K09klF8YBy6ZfxxZOZ8a+LX15ZOZXNnlpBg2YnZhZE8y8imc/Im9FYXGvscXy/isewAoG6S1Wv5y+kKYqqDuD/02mF0+32oDUBGU697w/2XByZmPaGugty3K+fj0aWTvh9p9lokoY7831xdWTJEfKP9QTGBmh/5+G+l/sTQ8HXA4ET4S5Z83t7jzt62wLxYW02CAT6AXAADRAA5GaaCD5G22OcSiZr39W9tgLgadyGHgDGMacH3SyCus7czcrJOMo17qXAvVMqDHF2G+H41lY+lokIrS28DTkbN3DuraWY4LBz9tZDMdw2Sx2BQVke9HdUqx3+RkXu1VbJIc+YxzPmMf8B+BcAAP//AQAA//8PIvLPAAAAAAEAAAACCbquIZQ1Xw889QADA+gAAAAA3B0N9wAAAADcHHNL/z/+OgMZBCQAAAADAAIAAAAAAAAAAQAAA9j+7wAAAlj/P/8/AxkAAQAAAAAAAAAAAAAAAAAAABACWAA+AlgAAAJYACACWABBAlgAVwJYAHICWABfAlgAYgJYAIYCWABIAlgAUgJYADACWABkAlgAQwJYACoCWAAKAAAAKgAqAE4AfgCcALIAyADiAPIBIAFCAW4BlgHaAewCKgAAAAEAAAAQAfgAKgBlAAYAAQAAAAAAAAAAAAAAAAADAAN4nJyWS2yT2RXHf865Ab94GVQNCFVXI4SmCIydScBNIOCQAcIgQklm2gpR1STGsUjsyHZg6GIWXVZddV11M120ErQKJWomgUIgpGoFqtRFNauuuqi66KqaRVfVd77jxHESOoOQyO8+zv+e173+gItyCyHiohFIgnGEJEnjDg7xjrGQ5JSxI8lF406SjBpvI8kPjbeTYtI4ymE+NY5xmF8axznCn40TnOA/xkkGI0eMd9IbqRjv4mDkV8a76YosG+9p8TPFwciXxntXdWLASkfKOMI3O74w7mBnx5fGwmVxxq5lTyfjctV4G0fkkfF2nsnfjaN0u18Yx+h2fzVO0NW5zXiH+M6c8U66o98LOQK7oz81jrA7+nPjDg5E7xsLyeiKsSMVNf1IJ6noP4y3kYpaLEH+Y1HjKIdiB4xj+Fi/cZyjsR8YJ8jEfmKcJB1bMN5BV+yfxjvJxZs6uzgcv2a8m1PxT4z3tPic4t245Sqyt0Vz36rm/gik4n8zjpCKN+c7eDf+X2NhX+KgseNAImPcyYHEJeNtHEiMG29nX+JT4yiZxM+MY7yXeG4c52jiX8YJupPfME6SSzY1d3Iq+WPjXWSSfzDezcXkv433tPiZomvHCeO9gY7MyjNZlFd4Ci1cooznMJ5JvDyWObzMyoIsyZw8llfyRObkuXwm9+Wx/B4fuSRL8kD+JE/w8rCF51t4RT6TB7IkD+VzWZCneJeVBXkpS/K5LMqizr4y+1n5o7zGc73jC24EZ8gjeaAqoS8Lcl/mZU6WAx2uk+GGLMtLeSZP5Xdqv6J6v8HLM5mV17Ios7rz2BY7n8pzjfGFLMucLMlv5UVzlusc4Ya8kNfyWB7KU1kMTg3Olpd4eaQzs2oTzmzu46EtTr6Plzl5IrOahSDLy8159feont6SX46qp2t1a8l321pJxxvz3lIV27FaSX6Np4sMWTJ4jtmoS0d5xqlykyKeEe5Rp0GRKep4hqgwRpUa0/p/QdfG8bzHBA0aTNPLcY5zV/+lKayqpdVyiuN8K/CHu5RpMIHnGkXqFKlxx9TOU6VCA88VCkwFvvh3GKHKDDXGKPr9pFvHeM5RZVzpKjWqqlpihkkK1OgiTYb3ydFHnkEGGKZvnULTPrQ+1mYfWg0zwAd8rL7WKauXfp32BFUaGmmFO3iyupYmS5YT9DFFgdsUddctinyiHgcKPaQ5QQ8ntC5f3bP1WShrnQp4Glqfca1dsO82niq33rrCZY01qFhg9xEVrV+4NkLDdoanVxjnuNp7jXRCM+ZVeUYrW6Osu9Nv5c1VChq/Z5A0noumGvTVqGY3+Duj/Rb4XaTyNfqzwT2mKTLKhOVzrR9HNIcN7mpO1zI+SVkrUNFODnIyo1kI425mbYQhLuMZVv3KOuXL6xSCSNr7LKt9lNbYJjY9d63+dyhQ1g65yaSurN23gp6b5zvKDXrxbdmpM6YVmqahNaqrVlprUOI4w5zncpsn/z9H4/o3rP1NZla7J4wu6JrglucZ0cqP+P14BnQ8xIhm5LsMMcpFhvmIUR3nucY18lxhlCE+UNthrul7MMwVBtViSDlcO6834Arfx/MhQ7on0C5afsKKBTdzWr2vq+9hL5eZYlpzHnie1liLGuHXr7Dnlqk2betqM0aZW7rTa/0qetcLlKwrptXDKc1lszfWbl3YEVMaS1DbtfUSVX1fa3pzA1XPPXs7gm4NfQpfiMZXqGr6rXqmvprDovq8flyy34Gyvo3hq9P8RhnRX4Ky/n6NqdeBbRBR8HvZPjO/YWZFa1XjJuWw12SFc9zT0ybtHnluamxqEX6ZUNcq1LVGgUc/UpVq85vEXosqJX2fpjVzY3qj7uko7AL9Ktlyb8FevZpm/Xbze2TD2cFbNWnvvtfYSqZ+iBsUmDSVir2Ungoz+vtZ09XwrmlsZN/oT7tSvfVLZUMVj+rb3l6T9tputku/Ztor47Lrqr2Z3Yo74866fpd3A67ffRvvMu0zlNzHeJfDu7/gXR7vTrqMy7sed8H1uow75XIu7zJKedfrcoFV5JJyv2qd0R2n3YfBijzccmV+y5UVPe+sy66d4LJKZ13O9bk+l3MXXI+uZtww3vW6sy7jBoJxswfV7wuq0+tOu3NuIFR3p12/63OXm73oBlzOnXH97n3VGGw5s9v1uMHAs2Yvbro39OCk63I97qTrdv1hppr9uKUfJ91pl3G9ek6/RpUJVJuduYVfPVaRUxp/sGfA9QQZae21jXUO+uGNNdqQb7XY0B1v1JnfrDPeaLHyPwAAAP//AQAA//+blbgHAAMAAAAAAAD/tQAyAAAAAQAAAAAAAAAAAAAAAAAAAAA="); src: url("data:application/font-woff;base64,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");
} }
.d2-2665946492 .text-mono-italic { .d2-3084549463 .text-mono-italic {
font-family: "d2-2665946492-font-mono-italic"; font-family: "d2-3084549463-font-mono-italic";
} }
@font-face { @font-face {
font-family: d2-2665946492-font-mono-italic; font-family: d2-3084549463-font-mono-italic;
src: url("data:application/font-woff;base64,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"); src: url("data:application/font-woff;base64,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");
}]]></style><style type="text/css"><![CDATA[.shape { }]]></style><style type="text/css"><![CDATA[.shape {
shape-rendering: geometricPrecision; shape-rendering: geometricPrecision;
@ -25,78 +25,78 @@
opacity: 0.5; opacity: 0.5;
} }
.d2-2665946492 .fill-N1{fill:#0A0F25;} .d2-3084549463 .fill-N1{fill:#0A0F25;}
.d2-2665946492 .fill-N2{fill:#676C7E;} .d2-3084549463 .fill-N2{fill:#676C7E;}
.d2-2665946492 .fill-N3{fill:#9499AB;} .d2-3084549463 .fill-N3{fill:#9499AB;}
.d2-2665946492 .fill-N4{fill:#CFD2DD;} .d2-3084549463 .fill-N4{fill:#CFD2DD;}
.d2-2665946492 .fill-N5{fill:#DEE1EB;} .d2-3084549463 .fill-N5{fill:#DEE1EB;}
.d2-2665946492 .fill-N6{fill:#EEF1F8;} .d2-3084549463 .fill-N6{fill:#EEF1F8;}
.d2-2665946492 .fill-N7{fill:#FFFFFF;} .d2-3084549463 .fill-N7{fill:#FFFFFF;}
.d2-2665946492 .fill-B1{fill:#0D32B2;} .d2-3084549463 .fill-B1{fill:#0D32B2;}
.d2-2665946492 .fill-B2{fill:#0D32B2;} .d2-3084549463 .fill-B2{fill:#0D32B2;}
.d2-2665946492 .fill-B3{fill:#E3E9FD;} .d2-3084549463 .fill-B3{fill:#E3E9FD;}
.d2-2665946492 .fill-B4{fill:#E3E9FD;} .d2-3084549463 .fill-B4{fill:#E3E9FD;}
.d2-2665946492 .fill-B5{fill:#EDF0FD;} .d2-3084549463 .fill-B5{fill:#EDF0FD;}
.d2-2665946492 .fill-B6{fill:#F7F8FE;} .d2-3084549463 .fill-B6{fill:#F7F8FE;}
.d2-2665946492 .fill-AA2{fill:#4A6FF3;} .d2-3084549463 .fill-AA2{fill:#4A6FF3;}
.d2-2665946492 .fill-AA4{fill:#EDF0FD;} .d2-3084549463 .fill-AA4{fill:#EDF0FD;}
.d2-2665946492 .fill-AA5{fill:#F7F8FE;} .d2-3084549463 .fill-AA5{fill:#F7F8FE;}
.d2-2665946492 .fill-AB4{fill:#EDF0FD;} .d2-3084549463 .fill-AB4{fill:#EDF0FD;}
.d2-2665946492 .fill-AB5{fill:#F7F8FE;} .d2-3084549463 .fill-AB5{fill:#F7F8FE;}
.d2-2665946492 .stroke-N1{stroke:#0A0F25;} .d2-3084549463 .stroke-N1{stroke:#0A0F25;}
.d2-2665946492 .stroke-N2{stroke:#676C7E;} .d2-3084549463 .stroke-N2{stroke:#676C7E;}
.d2-2665946492 .stroke-N3{stroke:#9499AB;} .d2-3084549463 .stroke-N3{stroke:#9499AB;}
.d2-2665946492 .stroke-N4{stroke:#CFD2DD;} .d2-3084549463 .stroke-N4{stroke:#CFD2DD;}
.d2-2665946492 .stroke-N5{stroke:#DEE1EB;} .d2-3084549463 .stroke-N5{stroke:#DEE1EB;}
.d2-2665946492 .stroke-N6{stroke:#EEF1F8;} .d2-3084549463 .stroke-N6{stroke:#EEF1F8;}
.d2-2665946492 .stroke-N7{stroke:#FFFFFF;} .d2-3084549463 .stroke-N7{stroke:#FFFFFF;}
.d2-2665946492 .stroke-B1{stroke:#0D32B2;} .d2-3084549463 .stroke-B1{stroke:#0D32B2;}
.d2-2665946492 .stroke-B2{stroke:#0D32B2;} .d2-3084549463 .stroke-B2{stroke:#0D32B2;}
.d2-2665946492 .stroke-B3{stroke:#E3E9FD;} .d2-3084549463 .stroke-B3{stroke:#E3E9FD;}
.d2-2665946492 .stroke-B4{stroke:#E3E9FD;} .d2-3084549463 .stroke-B4{stroke:#E3E9FD;}
.d2-2665946492 .stroke-B5{stroke:#EDF0FD;} .d2-3084549463 .stroke-B5{stroke:#EDF0FD;}
.d2-2665946492 .stroke-B6{stroke:#F7F8FE;} .d2-3084549463 .stroke-B6{stroke:#F7F8FE;}
.d2-2665946492 .stroke-AA2{stroke:#4A6FF3;} .d2-3084549463 .stroke-AA2{stroke:#4A6FF3;}
.d2-2665946492 .stroke-AA4{stroke:#EDF0FD;} .d2-3084549463 .stroke-AA4{stroke:#EDF0FD;}
.d2-2665946492 .stroke-AA5{stroke:#F7F8FE;} .d2-3084549463 .stroke-AA5{stroke:#F7F8FE;}
.d2-2665946492 .stroke-AB4{stroke:#EDF0FD;} .d2-3084549463 .stroke-AB4{stroke:#EDF0FD;}
.d2-2665946492 .stroke-AB5{stroke:#F7F8FE;} .d2-3084549463 .stroke-AB5{stroke:#F7F8FE;}
.d2-2665946492 .background-color-N1{background-color:#0A0F25;} .d2-3084549463 .background-color-N1{background-color:#0A0F25;}
.d2-2665946492 .background-color-N2{background-color:#676C7E;} .d2-3084549463 .background-color-N2{background-color:#676C7E;}
.d2-2665946492 .background-color-N3{background-color:#9499AB;} .d2-3084549463 .background-color-N3{background-color:#9499AB;}
.d2-2665946492 .background-color-N4{background-color:#CFD2DD;} .d2-3084549463 .background-color-N4{background-color:#CFD2DD;}
.d2-2665946492 .background-color-N5{background-color:#DEE1EB;} .d2-3084549463 .background-color-N5{background-color:#DEE1EB;}
.d2-2665946492 .background-color-N6{background-color:#EEF1F8;} .d2-3084549463 .background-color-N6{background-color:#EEF1F8;}
.d2-2665946492 .background-color-N7{background-color:#FFFFFF;} .d2-3084549463 .background-color-N7{background-color:#FFFFFF;}
.d2-2665946492 .background-color-B1{background-color:#0D32B2;} .d2-3084549463 .background-color-B1{background-color:#0D32B2;}
.d2-2665946492 .background-color-B2{background-color:#0D32B2;} .d2-3084549463 .background-color-B2{background-color:#0D32B2;}
.d2-2665946492 .background-color-B3{background-color:#E3E9FD;} .d2-3084549463 .background-color-B3{background-color:#E3E9FD;}
.d2-2665946492 .background-color-B4{background-color:#E3E9FD;} .d2-3084549463 .background-color-B4{background-color:#E3E9FD;}
.d2-2665946492 .background-color-B5{background-color:#EDF0FD;} .d2-3084549463 .background-color-B5{background-color:#EDF0FD;}
.d2-2665946492 .background-color-B6{background-color:#F7F8FE;} .d2-3084549463 .background-color-B6{background-color:#F7F8FE;}
.d2-2665946492 .background-color-AA2{background-color:#4A6FF3;} .d2-3084549463 .background-color-AA2{background-color:#4A6FF3;}
.d2-2665946492 .background-color-AA4{background-color:#EDF0FD;} .d2-3084549463 .background-color-AA4{background-color:#EDF0FD;}
.d2-2665946492 .background-color-AA5{background-color:#F7F8FE;} .d2-3084549463 .background-color-AA5{background-color:#F7F8FE;}
.d2-2665946492 .background-color-AB4{background-color:#EDF0FD;} .d2-3084549463 .background-color-AB4{background-color:#EDF0FD;}
.d2-2665946492 .background-color-AB5{background-color:#F7F8FE;} .d2-3084549463 .background-color-AB5{background-color:#F7F8FE;}
.d2-2665946492 .color-N1{color:#0A0F25;} .d2-3084549463 .color-N1{color:#0A0F25;}
.d2-2665946492 .color-N2{color:#676C7E;} .d2-3084549463 .color-N2{color:#676C7E;}
.d2-2665946492 .color-N3{color:#9499AB;} .d2-3084549463 .color-N3{color:#9499AB;}
.d2-2665946492 .color-N4{color:#CFD2DD;} .d2-3084549463 .color-N4{color:#CFD2DD;}
.d2-2665946492 .color-N5{color:#DEE1EB;} .d2-3084549463 .color-N5{color:#DEE1EB;}
.d2-2665946492 .color-N6{color:#EEF1F8;} .d2-3084549463 .color-N6{color:#EEF1F8;}
.d2-2665946492 .color-N7{color:#FFFFFF;} .d2-3084549463 .color-N7{color:#FFFFFF;}
.d2-2665946492 .color-B1{color:#0D32B2;} .d2-3084549463 .color-B1{color:#0D32B2;}
.d2-2665946492 .color-B2{color:#0D32B2;} .d2-3084549463 .color-B2{color:#0D32B2;}
.d2-2665946492 .color-B3{color:#E3E9FD;} .d2-3084549463 .color-B3{color:#E3E9FD;}
.d2-2665946492 .color-B4{color:#E3E9FD;} .d2-3084549463 .color-B4{color:#E3E9FD;}
.d2-2665946492 .color-B5{color:#EDF0FD;} .d2-3084549463 .color-B5{color:#EDF0FD;}
.d2-2665946492 .color-B6{color:#F7F8FE;} .d2-3084549463 .color-B6{color:#F7F8FE;}
.d2-2665946492 .color-AA2{color:#4A6FF3;} .d2-3084549463 .color-AA2{color:#4A6FF3;}
.d2-2665946492 .color-AA4{color:#EDF0FD;} .d2-3084549463 .color-AA4{color:#EDF0FD;}
.d2-2665946492 .color-AA5{color:#F7F8FE;} .d2-3084549463 .color-AA5{color:#F7F8FE;}
.d2-2665946492 .color-AB4{color:#EDF0FD;} .d2-3084549463 .color-AB4{color:#EDF0FD;}
.d2-2665946492 .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><style type="text/css"><![CDATA[ .d2-3084549463 .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><style type="text/css"><![CDATA[
.dots-overlay { .dots-overlay {
fill: url(#dots); fill: url(#dots);
mix-blend-mode: multiply; mix-blend-mode: multiply;
@ -129,9 +129,9 @@
<rect x="7" y="7" width="1" height="1" fill="#0A0F25"/> <rect x="7" y="7" width="1" height="1" fill="#0A0F25"/>
</g> </g>
</pattern> </pattern>
</defs><g id="NETWORK"><g class="shape" ><rect x="0.000000" y="41.000000" width="334.000000" height="412.000000" stroke="black" fill="#E7E9EE" style="stroke-width:2;" /><rect x="0.000000" y="41.000000" width="334.000000" height="412.000000" class="dots-overlay" style="stroke-width:2;" /><rect x="5.000000" y="46.000000" width="324.000000" height="402.000000" stroke="black" fill="transparent" style="stroke-width:2;" /></g><text x="167.000000" y="28.000000" class="text-mono fill-N1" style="text-anchor:middle;font-size:28px">NETWORK</text></g><g id="NETWORK.CELL TOWER"><g class="shape" ><rect x="20.000000" y="106.000000" width="294.000000" height="317.000000" stroke="black" fill="#F5F6F9" style="stroke-width:2;" /><rect x="20.000000" y="106.000000" width="294.000000" height="317.000000" class="dots-overlay" style="stroke-width:2;" /></g><text x="167.000000" y="94.000000" class="text-mono fill-N1" style="text-anchor:middle;font-size:24px">CELL TOWER</text></g><g id="NETWORK.CELL TOWER.satellites"><g class="shape" ><path d="M 112 128 H 258 C 254 128 243 146 243 161 C 243 176 254 194 258 194 H 112 C 108 194 97 176 97 161 C 97 146 108 128 112 128 Z" stroke="black" fill="white" style="stroke-width:2;" /><path d="M 102 138 H 248 C 244 138 233 156 233 171 C 233 186 244 204 248 204 H 102 C 98 204 87 186 87 171 C 87 156 98 138 102 138 Z" stroke="black" fill="white" style="stroke-width:2;" /></g><text x="167.500000" y="176.500000" class="text-mono fill-N1" style="text-anchor:middle;font-size:16px">SATELLITES</text></g><g id="NETWORK.CELL TOWER.transmitter"><g class="shape" ><rect x="92.000000" y="325.000000" width="151.000000" height="66.000000" stroke="black" fill="white" style="stroke-width:2;" /></g><text x="167.500000" y="363.500000" class="text-mono fill-N1" style="text-anchor:middle;font-size:16px">TRANSMITTER</text></g><g id="NETWORK.CELL TOWER.(satellites -&gt; transmitter)[0]"><marker id="mk-27687146" 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" fill="black" class="connection" stroke-width="2" /> </marker><path d="M 140.804279 206.603201 C 106.200000 253.000000 106.250000 277.200000 139.875404 322.781103" stroke="black" fill="none" class="connection" style="stroke-width:2;" marker-end="url(#mk-27687146)" mask="url(#d2-2665946492)" /><text x="106.000000" y="271.000000" class="text-mono-italic fill-N2" style="text-anchor:middle;font-size:16px">SEND</text></g><g id="NETWORK.CELL TOWER.(satellites -&gt; transmitter)[1]"><path d="M 167.000000 207.000000 C 167.000000 253.000000 167.000000 277.200000 167.000000 322.000000" stroke="black" fill="none" class="connection" style="stroke-width:2;" marker-end="url(#mk-27687146)" mask="url(#d2-2665946492)" /><text x="167.000000" y="271.000000" class="text-mono-italic fill-N2" style="text-anchor:middle;font-size:16px">SEND</text></g><g id="NETWORK.CELL TOWER.(satellites -&gt; transmitter)[2]"><path d="M 193.195721 206.603201 C 227.800000 253.000000 227.750000 277.200000 194.124596 322.781103" stroke="black" fill="none" class="connection" style="stroke-width:2;" marker-end="url(#mk-27687146)" mask="url(#d2-2665946492)" /><text x="228.000000" y="271.000000" class="text-mono-italic fill-N2" style="text-anchor:middle;font-size:16px">SEND</text></g><mask id="d2-2665946492" maskUnits="userSpaceOnUse" x="-1" y="0" width="336" height="454"> </defs><g id="NETWORK"><g class="shape" ><rect x="0.000000" y="41.000000" width="360.000000" height="412.000000" stroke="black" fill="#E7E9EE" style="stroke-width:2;" /><rect x="0.000000" y="41.000000" width="360.000000" height="412.000000" class="dots-overlay" style="stroke-width:2;" /><rect x="5.000000" y="46.000000" width="350.000000" height="402.000000" stroke="black" fill="transparent" style="stroke-width:2;" /></g><text x="180.000000" y="28.000000" class="text-mono fill-N1" style="text-anchor:middle;font-size:28px">NETWORK</text></g><g id="NETWORK.CELL TOWER"><g class="shape" ><rect x="20.000000" y="106.000000" width="320.000000" height="317.000000" stroke="black" fill="#F5F6F9" style="stroke-width:2;" /><rect x="20.000000" y="106.000000" width="320.000000" height="317.000000" class="dots-overlay" style="stroke-width:2;" /></g><text x="180.000000" y="94.000000" class="text-mono fill-N1" style="text-anchor:middle;font-size:24px">CELL TOWER</text></g><g id="NETWORK.CELL TOWER.satellites"><g class="shape" ><path d="M 125 128 H 271 C 267 128 256 146 256 161 C 256 176 267 194 271 194 H 125 C 121 194 110 176 110 161 C 110 146 121 128 125 128 Z" stroke="black" fill="white" style="stroke-width:2;" /><path d="M 115 138 H 261 C 257 138 246 156 246 171 C 246 186 257 204 261 204 H 115 C 111 204 100 186 100 171 C 100 156 111 138 115 138 Z" stroke="black" fill="white" style="stroke-width:2;" /></g><text x="180.500000" y="176.500000" class="text-mono fill-N1" style="text-anchor:middle;font-size:16px">SATELLITES</text></g><g id="NETWORK.CELL TOWER.transmitter"><g class="shape" ><rect x="105.000000" y="325.000000" width="151.000000" height="66.000000" stroke="black" fill="white" style="stroke-width:2;" /></g><text x="180.500000" y="363.500000" class="text-mono fill-N1" style="text-anchor:middle;font-size:16px">TRANSMITTER</text></g><g id="NETWORK.CELL TOWER.(satellites -&gt; transmitter)[0]"><marker id="mk-27687146" 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" fill="black" class="connection" stroke-width="2" /> </marker><path d="M 150.723421 206.539593 C 112.200000 253.000000 112.250000 277.200000 149.714288 322.906432" stroke="black" fill="none" class="connection" style="stroke-width:2;" marker-end="url(#mk-27687146)" mask="url(#d2-3084549463)" /><text x="112.000000" y="271.000000" class="text-mono-italic fill-N2" style="text-anchor:middle;font-size:16px">SEND</text></g><g id="NETWORK.CELL TOWER.(satellites -&gt; transmitter)[1]"><path d="M 180.008333 206.999983 C 180.200000 253.000000 180.250000 277.200000 180.250000 322.000000" stroke="black" fill="none" class="connection" style="stroke-width:2;" marker-end="url(#mk-27687146)" mask="url(#d2-3084549463)" /><text x="180.000000" y="271.000000" class="text-mono-italic fill-N2" style="text-anchor:middle;font-size:16px">SEND</text></g><g id="NETWORK.CELL TOWER.(satellites -&gt; transmitter)[2]"><path d="M 209.284135 206.533296 C 248.200000 253.000000 248.250000 277.200000 210.785712 322.906432" stroke="black" fill="none" class="connection" style="stroke-width:2;" marker-end="url(#mk-27687146)" mask="url(#d2-3084549463)" /><text x="248.000000" y="271.000000" class="text-mono-italic fill-N2" style="text-anchor:middle;font-size:16px">SEND</text></g><mask id="d2-3084549463" maskUnits="userSpaceOnUse" x="-1" y="0" width="362" height="454">
<rect x="-1" y="0" width="336" height="454" fill="white"></rect> <rect x="-1" y="0" width="362" height="454" fill="white"></rect>
<rect x="87.000000" y="255.000000" width="38" height="21" fill="black"></rect> <rect x="93.000000" y="255.000000" width="38" height="21" fill="black"></rect>
<rect x="148.000000" y="255.000000" width="38" height="21" fill="black"></rect> <rect x="161.000000" y="255.000000" width="38" height="21" fill="black"></rect>
<rect x="209.000000" y="255.000000" width="38" height="21" fill="black"></rect> <rect x="229.000000" y="255.000000" width="38" height="21" fill="black"></rect>
</mask></svg></svg> </mask></svg></svg>

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View file

@ -4,7 +4,7 @@
"fontFamily": "SourceSansPro", "fontFamily": "SourceSansPro",
"shapes": [ "shapes": [
{ {
"id": "class", "id": "class2",
"type": "class", "type": "class",
"pos": { "pos": {
"x": 0, "x": 0,
@ -164,8 +164,8 @@
], ],
"connections": [ "connections": [
{ {
"id": "(class -> table)[0]", "id": "(class2 -> table)[0]",
"src": "class", "src": "class2",
"srcArrow": "none", "srcArrow": "none",
"srcLabel": "", "srcLabel": "",
"dst": "table", "dst": "table",

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View file

@ -4,7 +4,7 @@
"fontFamily": "SourceSansPro", "fontFamily": "SourceSansPro",
"shapes": [ "shapes": [
{ {
"id": "class", "id": "class2",
"type": "class", "type": "class",
"pos": { "pos": {
"x": 12, "x": 12,
@ -164,8 +164,8 @@
], ],
"connections": [ "connections": [
{ {
"id": "(class -> table)[0]", "id": "(class2 -> table)[0]",
"src": "class", "src": "class2",
"srcArrow": "none", "srcArrow": "none",
"srcLabel": "", "srcLabel": "",
"dst": "table", "dst": "table",

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View file

@ -10,7 +10,7 @@
"x": 0, "x": 0,
"y": 41 "y": 41
}, },
"width": 1200, "width": 1220,
"height": 125, "height": 125,
"opacity": 1, "opacity": 1,
"strokeDash": 0, "strokeDash": 0,
@ -294,10 +294,10 @@
"id": "osvc", "id": "osvc",
"type": "rectangle", "type": "rectangle",
"pos": { "pos": {
"x": 826, "x": 796,
"y": 328 "y": 328
}, },
"width": 364, "width": 414,
"height": 125, "height": 125,
"opacity": 1, "opacity": 1,
"strokeDash": 0, "strokeDash": 0,
@ -335,7 +335,7 @@
"id": "osvc.vm1", "id": "osvc.vm1",
"type": "rectangle", "type": "rectangle",
"pos": { "pos": {
"x": 926, "x": 916,
"y": 357 "y": 357
}, },
"width": 76, "width": 76,
@ -376,7 +376,7 @@
"id": "osvc.vm2", "id": "osvc.vm2",
"type": "rectangle", "type": "rectangle",
"pos": { "pos": {
"x": 1074, "x": 1094,
"y": 357 "y": 357
}, },
"width": 76, "width": 76,
@ -442,19 +442,19 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 884.75, "x": 854.75,
"y": 166 "y": 166
}, },
{ {
"x": 884.75, "x": 854.75,
"y": 214.4 "y": 214.4
}, },
{ {
"x": 884.75, "x": 854.75,
"y": 246.9 "y": 246.9
}, },
{ {
"x": 884.75, "x": 854.75,
"y": 328.5 "y": 328.5
} }
], ],
@ -491,19 +491,19 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 966.75, "x": 956.75,
"y": 166 "y": 166
}, },
{ {
"x": 966.75, "x": 956.75,
"y": 214.4 "y": 214.4
}, },
{ {
"x": 966.75, "x": 956.75,
"y": 238.7 "y": 238.7
}, },
{ {
"x": 966.75, "x": 956.75,
"y": 287.5 "y": 287.5
} }
], ],
@ -540,19 +540,19 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 1042.75, "x": 1052.75,
"y": 166 "y": 166
}, },
{ {
"x": 1042.75, "x": 1052.75,
"y": 214.4 "y": 214.4
}, },
{ {
"x": 1042.75, "x": 1052.75,
"y": 238.7 "y": 238.7
}, },
{ {
"x": 1042.75, "x": 1052.75,
"y": 287.5 "y": 287.5
} }
], ],
@ -589,19 +589,19 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 1137, "x": 1157,
"y": 166 "y": 166
}, },
{ {
"x": 1137, "x": 1157,
"y": 214.4 "y": 214.4
}, },
{ {
"x": 1137, "x": 1157,
"y": 246.9 "y": 246.9
}, },
{ {
"x": 1137, "x": 1157,
"y": 328.5 "y": 328.5
} }
], ],

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View file

@ -531,7 +531,6 @@
"underline": false, "underline": false,
"labelWidth": 639, "labelWidth": 639,
"labelHeight": 51, "labelHeight": 51,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0, "zIndex": 0,
"level": 1 "level": 1
} }

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View file

@ -531,7 +531,6 @@
"underline": false, "underline": false,
"labelWidth": 639, "labelWidth": 639,
"labelHeight": 51, "labelHeight": 51,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0, "zIndex": 0,
"level": 1 "level": 1
} }

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View file

@ -4,7 +4,7 @@
"fontFamily": "SourceSansPro", "fontFamily": "SourceSansPro",
"shapes": [ "shapes": [
{ {
"id": "class", "id": "class2",
"type": "class", "type": "class",
"pos": { "pos": {
"x": 0, "x": 0,
@ -305,8 +305,8 @@
], ],
"connections": [ "connections": [
{ {
"id": "(class -> users)[0]", "id": "(class2 -> users)[0]",
"src": "class", "src": "class2",
"srcArrow": "none", "srcArrow": "none",
"srcLabel": "", "srcLabel": "",
"dst": "users", "dst": "users",

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View file

@ -4,7 +4,7 @@
"fontFamily": "SourceSansPro", "fontFamily": "SourceSansPro",
"shapes": [ "shapes": [
{ {
"id": "class", "id": "class2",
"type": "class", "type": "class",
"pos": { "pos": {
"x": 12, "x": 12,
@ -305,8 +305,8 @@
], ],
"connections": [ "connections": [
{ {
"id": "(class -> users)[0]", "id": "(class2 -> users)[0]",
"src": "class", "src": "class2",
"srcArrow": "none", "srcArrow": "none",
"srcLabel": "", "srcLabel": "",
"dst": "users", "dst": "users",

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View file

@ -10,7 +10,7 @@
"x": 0, "x": 0,
"y": 41 "y": 41
}, },
"width": 806, "width": 834,
"height": 1314, "height": 1314,
"opacity": 1, "opacity": 1,
"strokeDash": 0, "strokeDash": 0,
@ -51,7 +51,7 @@
"x": 20, "x": 20,
"y": 106 "y": 106
}, },
"width": 567, "width": 595,
"height": 1219, "height": 1219,
"opacity": 1, "opacity": 1,
"strokeDash": 0, "strokeDash": 0,
@ -92,7 +92,7 @@
"x": 40, "x": 40,
"y": 721 "y": 721
}, },
"width": 393, "width": 421,
"height": 572, "height": 572,
"opacity": 1, "opacity": 1,
"strokeDash": 0, "strokeDash": 0,
@ -252,7 +252,7 @@
"id": "aa.bb.cc.gg", "id": "aa.bb.cc.gg",
"type": "text", "type": "text",
"pos": { "pos": {
"x": 190, "x": 187,
"y": 1043 "y": 1043
}, },
"width": 17, "width": 17,
@ -292,7 +292,7 @@
"id": "aa.bb.cc.hh", "id": "aa.bb.cc.hh",
"type": "rectangle", "type": "rectangle",
"pos": { "pos": {
"x": 324, "x": 334,
"y": 1189 "y": 1189
}, },
"width": 63, "width": 63,
@ -336,7 +336,7 @@
"x": 52, "x": 52,
"y": 169 "y": 169
}, },
"width": 469, "width": 496,
"height": 161, "height": 161,
"opacity": 1, "opacity": 1,
"strokeDash": 0, "strokeDash": 0,
@ -374,7 +374,7 @@
"id": "aa.bb.ii.jj", "id": "aa.bb.ii.jj",
"type": "diamond", "type": "diamond",
"pos": { "pos": {
"x": 431, "x": 458,
"y": 204 "y": 204
}, },
"width": 50, "width": 50,
@ -415,7 +415,7 @@
"id": "aa.bb.kk", "id": "aa.bb.kk",
"type": "oval", "type": "oval",
"pos": { "pos": {
"x": 474, "x": 501,
"y": 1169 "y": 1169
}, },
"width": 74, "width": 74,
@ -456,7 +456,7 @@
"id": "aa.ll", "id": "aa.ll",
"type": "rectangle", "type": "rectangle",
"pos": { "pos": {
"x": 670, "x": 698,
"y": 772 "y": 772
}, },
"width": 54, "width": 54,
@ -497,7 +497,7 @@
"id": "aa.mm", "id": "aa.mm",
"type": "cylinder", "type": "cylinder",
"pos": { "pos": {
"x": 662, "x": 689,
"y": 433 "y": 433
}, },
"width": 71, "width": 71,
@ -538,7 +538,7 @@
"id": "aa.nn", "id": "aa.nn",
"type": "text", "type": "text",
"pos": { "pos": {
"x": 628, "x": 655,
"y": 1178 "y": 1178
}, },
"width": 16, "width": 16,
@ -578,7 +578,7 @@
"id": "aa.oo", "id": "aa.oo",
"type": "rectangle", "type": "rectangle",
"pos": { "pos": {
"x": 704, "x": 731,
"y": 1155 "y": 1155
}, },
"width": 63, "width": 63,
@ -652,12 +652,12 @@
"y": 910.3 "y": 910.3
}, },
{ {
"x": 132.35, "x": 131.8,
"y": 995.1959501557633 "y": 995.1
}, },
{ {
"x": 189.75, "x": 187,
"y": 1045.9797507788162 "y": 1045.5
} }
], ],
"isCurve": true, "isCurve": true,
@ -693,20 +693,20 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 198.25, "x": 195.5,
"y": 1064 "y": 1064
}, },
{ {
"x": 198.25, "x": 195.5,
"y": 1112.4 "y": 1112.4
}, },
{ {
"x": 223.45, "x": 223.3,
"y": 1140.1 "y": 1140.3
}, },
{ {
"x": 324.25, "x": 334.5,
"y": 1202.5 "y": 1203.5
} }
], ],
"isCurve": true, "isCurve": true,
@ -815,12 +815,12 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 670.25, "x": 697.5,
"y": 811.7993675333802 "y": 811.4285714285714
}, },
{ {
"x": 587.25, "x": 614.5,
"y": 866.7993675333802 "y": 865.4285714285714
} }
], ],
"animated": false, "animated": false,
@ -855,12 +855,12 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 662, "x": 689,
"y": 501 "y": 500
}, },
{ {
"x": 284.79999999999995, "x": 290.2,
"y": 589.8 "y": 589.6
}, },
{ {
"x": 190.5, "x": 190.5,
@ -904,31 +904,31 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 697, "x": 725,
"y": 552 "y": 552
}, },
{ {
"x": 697.2, "x": 724.6,
"y": 600 "y": 600
}, },
{ {
"x": 697.25, "x": 724.5,
"y": 624.1 "y": 624.1
}, },
{ {
"x": 697.25, "x": 724.5,
"y": 642.25 "y": 642.25
}, },
{ {
"x": 697.25, "x": 724.5,
"y": 660.4 "y": 660.4
}, },
{ {
"x": 697.25, "x": 724.5,
"y": 732.5 "y": 732.5
}, },
{ {
"x": 697.25, "x": 724.5,
"y": 772.5 "y": 772.5
} }
], ],
@ -965,12 +965,12 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 662, "x": 689,
"y": 505 "y": 505
}, },
{ {
"x": 587.75, "x": 615,
"y": 568.4633307868602 "y": 566.9955817378498
} }
], ],
"animated": false, "animated": false,
@ -1005,19 +1005,19 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 670.25, "x": 697.5,
"y": 811.1842105263158 "y": 810.8167259786477
}, },
{ {
"x": 376.45, "x": 381.9,
"y": 873.0368421052632 "y": 872.9633451957295
}, },
{ {
"x": 283.8, "x": 283.2,
"y": 968.7 "y": 968.7
}, },
{ {
"x": 207, "x": 204,
"y": 1047.5 "y": 1047.5
} }
], ],
@ -1054,19 +1054,19 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 662, "x": 689,
"y": 473 "y": 473
}, },
{ {
"x": 517.8, "x": 545,
"y": 393 "y": 393
}, },
{ {
"x": 481.8, "x": 509,
"y": 364.6 "y": 364.6
}, },
{ {
"x": 482, "x": 509,
"y": 331 "y": 331
} }
], ],
@ -1103,12 +1103,12 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 434, "x": 461,
"y": 896.5 "y": 896.5
}, },
{ {
"x": 670, "x": 697.5,
"y": 813.5 "y": 812.9328358208955
} }
], ],
"animated": false, "animated": false,
@ -1143,56 +1143,56 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 454, "x": 481,
"y": 331 "y": 331
}, },
{ {
"x": 453.8, "x": 481,
"y": 364.6 "y": 364.6
}, },
{ {
"x": 453.75, "x": 481,
"y": 396.9 "y": 396.9
}, },
{ {
"x": 453.75, "x": 481,
"y": 432.75 "y": 432.75
}, },
{ {
"x": 453.75, "x": 481,
"y": 468.6 "y": 468.6
}, },
{ {
"x": 453.75, "x": 481,
"y": 516.4 "y": 516.4
}, },
{ {
"x": 453.75, "x": 481,
"y": 552.25 "y": 552.25
}, },
{ {
"x": 453.75, "x": 481,
"y": 588.1 "y": 588.1
}, },
{ {
"x": 453.75, "x": 481,
"y": 624.1 "y": 624.1
}, },
{ {
"x": 453.75, "x": 481,
"y": 642.25 "y": 642.25
}, },
{ {
"x": 453.75, "x": 481,
"y": 660.4 "y": 660.4
}, },
{ {
"x": 496.95, "x": 524.3,
"y": 737.3 "y": 737.2593429158111
}, },
{ {
"x": 669.75, "x": 697.5,
"y": 796.5 "y": 796.2967145790554
} }
], ],
"isCurve": true, "isCurve": true,

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

284
e2etests/testdata/stable/classes/dagre/board.exp.json generated vendored Normal file
View file

@ -0,0 +1,284 @@
{
"name": "",
"isFolderOnly": false,
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "nostar",
"type": "oval",
"classes": [
"dragon_ball"
],
"pos": {
"x": 1,
"y": 0
},
"width": 50,
"height": 50,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 0,
"borderRadius": 0,
"fill": "orange",
"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": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"zIndex": 0,
"level": 1
},
{
"id": "1star",
"type": "oval",
"classes": [
"dragon_ball"
],
"pos": {
"x": 1,
"y": 171
},
"width": 50,
"height": 50,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 0,
"borderRadius": 0,
"fill": "orange",
"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": "*",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 7,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "2star",
"type": "oval",
"classes": [
"dragon_ball"
],
"pos": {
"x": 0,
"y": 342
},
"width": 52,
"height": 52,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 0,
"borderRadius": 0,
"fill": "orange",
"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": "**",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 15,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
}
],
"connections": [
{
"id": "(nostar -> 1star)[0]",
"classes": [
"path"
],
"src": "nostar",
"srcArrow": "none",
"srcLabel": "",
"dst": "1star",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 4,
"stroke": "B1",
"borderRadius": 10,
"label": "then",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 30,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"labelPercentage": 0,
"route": [
{
"x": 26,
"y": 50
},
{
"x": 26,
"y": 98.4
},
{
"x": 26,
"y": 122.6
},
{
"x": 26,
"y": 171
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(1star -> 2star)[0]",
"classes": [
"path"
],
"src": "1star",
"srcArrow": "none",
"srcLabel": "",
"dst": "2star",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 4,
"stroke": "B1",
"borderRadius": 10,
"label": "then",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 30,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"labelPercentage": 0,
"route": [
{
"x": 26,
"y": 221
},
{
"x": 26,
"y": 269.4
},
{
"x": 26,
"y": 293.6
},
{
"x": 26,
"y": 342
}
],
"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,103 @@
<?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.3.0-HEAD" preserveAspectRatio="xMinYMin meet" viewBox="0 0 52 394"><svg id="d2-svg" class="d2-2376789252" width="52" height="394" viewBox="0 0 52 394"><rect x="0.000000" y="0.000000" width="52.000000" height="394.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><style type="text/css"><![CDATA[
.d2-2376789252 .text-bold {
font-family: "d2-2376789252-font-bold";
}
@font-face {
font-family: d2-2376789252-font-bold;
src: url("data:application/font-woff;base64,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");
}
.d2-2376789252 .text-italic {
font-family: "d2-2376789252-font-italic";
}
@font-face {
font-family: d2-2376789252-font-italic;
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-2376789252 .fill-N1{fill:#0A0F25;}
.d2-2376789252 .fill-N2{fill:#676C7E;}
.d2-2376789252 .fill-N3{fill:#9499AB;}
.d2-2376789252 .fill-N4{fill:#CFD2DD;}
.d2-2376789252 .fill-N5{fill:#DEE1EB;}
.d2-2376789252 .fill-N6{fill:#EEF1F8;}
.d2-2376789252 .fill-N7{fill:#FFFFFF;}
.d2-2376789252 .fill-B1{fill:#0D32B2;}
.d2-2376789252 .fill-B2{fill:#0D32B2;}
.d2-2376789252 .fill-B3{fill:#E3E9FD;}
.d2-2376789252 .fill-B4{fill:#E3E9FD;}
.d2-2376789252 .fill-B5{fill:#EDF0FD;}
.d2-2376789252 .fill-B6{fill:#F7F8FE;}
.d2-2376789252 .fill-AA2{fill:#4A6FF3;}
.d2-2376789252 .fill-AA4{fill:#EDF0FD;}
.d2-2376789252 .fill-AA5{fill:#F7F8FE;}
.d2-2376789252 .fill-AB4{fill:#EDF0FD;}
.d2-2376789252 .fill-AB5{fill:#F7F8FE;}
.d2-2376789252 .stroke-N1{stroke:#0A0F25;}
.d2-2376789252 .stroke-N2{stroke:#676C7E;}
.d2-2376789252 .stroke-N3{stroke:#9499AB;}
.d2-2376789252 .stroke-N4{stroke:#CFD2DD;}
.d2-2376789252 .stroke-N5{stroke:#DEE1EB;}
.d2-2376789252 .stroke-N6{stroke:#EEF1F8;}
.d2-2376789252 .stroke-N7{stroke:#FFFFFF;}
.d2-2376789252 .stroke-B1{stroke:#0D32B2;}
.d2-2376789252 .stroke-B2{stroke:#0D32B2;}
.d2-2376789252 .stroke-B3{stroke:#E3E9FD;}
.d2-2376789252 .stroke-B4{stroke:#E3E9FD;}
.d2-2376789252 .stroke-B5{stroke:#EDF0FD;}
.d2-2376789252 .stroke-B6{stroke:#F7F8FE;}
.d2-2376789252 .stroke-AA2{stroke:#4A6FF3;}
.d2-2376789252 .stroke-AA4{stroke:#EDF0FD;}
.d2-2376789252 .stroke-AA5{stroke:#F7F8FE;}
.d2-2376789252 .stroke-AB4{stroke:#EDF0FD;}
.d2-2376789252 .stroke-AB5{stroke:#F7F8FE;}
.d2-2376789252 .background-color-N1{background-color:#0A0F25;}
.d2-2376789252 .background-color-N2{background-color:#676C7E;}
.d2-2376789252 .background-color-N3{background-color:#9499AB;}
.d2-2376789252 .background-color-N4{background-color:#CFD2DD;}
.d2-2376789252 .background-color-N5{background-color:#DEE1EB;}
.d2-2376789252 .background-color-N6{background-color:#EEF1F8;}
.d2-2376789252 .background-color-N7{background-color:#FFFFFF;}
.d2-2376789252 .background-color-B1{background-color:#0D32B2;}
.d2-2376789252 .background-color-B2{background-color:#0D32B2;}
.d2-2376789252 .background-color-B3{background-color:#E3E9FD;}
.d2-2376789252 .background-color-B4{background-color:#E3E9FD;}
.d2-2376789252 .background-color-B5{background-color:#EDF0FD;}
.d2-2376789252 .background-color-B6{background-color:#F7F8FE;}
.d2-2376789252 .background-color-AA2{background-color:#4A6FF3;}
.d2-2376789252 .background-color-AA4{background-color:#EDF0FD;}
.d2-2376789252 .background-color-AA5{background-color:#F7F8FE;}
.d2-2376789252 .background-color-AB4{background-color:#EDF0FD;}
.d2-2376789252 .background-color-AB5{background-color:#F7F8FE;}
.d2-2376789252 .color-N1{color:#0A0F25;}
.d2-2376789252 .color-N2{color:#676C7E;}
.d2-2376789252 .color-N3{color:#9499AB;}
.d2-2376789252 .color-N4{color:#CFD2DD;}
.d2-2376789252 .color-N5{color:#DEE1EB;}
.d2-2376789252 .color-N6{color:#EEF1F8;}
.d2-2376789252 .color-N7{color:#FFFFFF;}
.d2-2376789252 .color-B1{color:#0D32B2;}
.d2-2376789252 .color-B2{color:#0D32B2;}
.d2-2376789252 .color-B3{color:#E3E9FD;}
.d2-2376789252 .color-B4{color:#E3E9FD;}
.d2-2376789252 .color-B5{color:#EDF0FD;}
.d2-2376789252 .color-B6{color:#F7F8FE;}
.d2-2376789252 .color-AA2{color:#4A6FF3;}
.d2-2376789252 .color-AA4{color:#EDF0FD;}
.d2-2376789252 .color-AA5{color:#F7F8FE;}
.d2-2376789252 .color-AB4{color:#EDF0FD;}
.d2-2376789252 .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="nostar" class="dragon_ball"><g class="shape" ><ellipse rx="25.000000" ry="25.000000" cx="26.000000" cy="25.000000" fill="orange" class="shape stroke-B1" style="stroke-width:0;" /></g></g><g id="1star" class="dragon_ball"><g class="shape" ><ellipse rx="25.000000" ry="25.000000" cx="26.000000" cy="196.000000" fill="orange" class="shape stroke-B1" style="stroke-width:0;" /></g><text x="26.000000" y="201.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">*</text></g><g id="2star" class="dragon_ball"><g class="shape" ><ellipse rx="26.000000" ry="26.000000" cx="26.000000" cy="368.000000" fill="orange" class="shape stroke-B1" style="stroke-width:0;" /></g><text x="26.000000" y="373.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">**</text></g><g id="(nostar -&gt; 1star)[0]" class="path"><marker id="mk-3519660172" markerWidth="16.000000" markerHeight="20.000000" refX="10.000000" refY="10.000000" viewBox="0.000000 0.000000 16.000000 20.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon points="0.000000,0.000000 16.000000,10.000000 0.000000,20.000000" class="connection fill-B1" stroke-width="4" /> </marker><path d="M 26.000000 52.000000 C 26.000000 98.400000 26.000000 122.600000 26.000000 165.000000" fill="none" class="connection stroke-B1" style="stroke-width:4;" marker-end="url(#mk-3519660172)" mask="url(#d2-2376789252)" /><text x="26.000000" y="116.000000" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px">then</text></g><g id="(1star -&gt; 2star)[0]" class="path"><path d="M 26.000000 223.000000 C 26.000000 269.400000 26.000000 293.600000 26.000000 336.000000" fill="none" class="connection stroke-B1" style="stroke-width:4;" marker-end="url(#mk-3519660172)" mask="url(#d2-2376789252)" /><text x="26.000000" y="287.000000" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px">then</text></g><mask id="d2-2376789252" maskUnits="userSpaceOnUse" x="0" y="0" width="52" height="394">
<rect x="0" y="0" width="52" height="394" fill="white"></rect>
<rect x="11.000000" y="100.000000" width="30" height="21" fill="black"></rect>
<rect x="11.000000" y="271.000000" width="30" height="21" fill="black"></rect>
</mask></svg></svg>

After

Width:  |  Height:  |  Size: 13 KiB

266
e2etests/testdata/stable/classes/elk/board.exp.json generated vendored Normal file
View file

@ -0,0 +1,266 @@
{
"name": "",
"isFolderOnly": false,
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "nostar",
"type": "oval",
"classes": [
"dragon_ball"
],
"pos": {
"x": 13,
"y": 12
},
"width": 50,
"height": 50,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 0,
"borderRadius": 0,
"fill": "orange",
"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": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"zIndex": 0,
"level": 1
},
{
"id": "1star",
"type": "oval",
"classes": [
"dragon_ball"
],
"pos": {
"x": 13,
"y": 223
},
"width": 50,
"height": 50,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 0,
"borderRadius": 0,
"fill": "orange",
"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": "*",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 7,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "2star",
"type": "oval",
"classes": [
"dragon_ball"
],
"pos": {
"x": 12,
"y": 434
},
"width": 52,
"height": 52,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 0,
"borderRadius": 0,
"fill": "orange",
"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": "**",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 15,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
}
],
"connections": [
{
"id": "(nostar -> 1star)[0]",
"classes": [
"path"
],
"src": "nostar",
"srcArrow": "none",
"srcLabel": "",
"dst": "1star",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 4,
"stroke": "B1",
"borderRadius": 10,
"label": "then",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 30,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"labelPercentage": 0,
"route": [
{
"x": 38,
"y": 62
},
{
"x": 38,
"y": 223
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(1star -> 2star)[0]",
"classes": [
"path"
],
"src": "1star",
"srcArrow": "none",
"srcLabel": "",
"dst": "2star",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 4,
"stroke": "B1",
"borderRadius": 10,
"label": "then",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 30,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"labelPercentage": 0,
"route": [
{
"x": 38,
"y": 273
},
{
"x": 38,
"y": 434
}
],
"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,103 @@
<?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.3.0-HEAD" preserveAspectRatio="xMinYMin meet" viewBox="0 0 52 474"><svg id="d2-svg" class="d2-2782748831" width="52" height="474" viewBox="12 12 52 474"><rect x="12.000000" y="12.000000" width="52.000000" height="474.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><style type="text/css"><![CDATA[
.d2-2782748831 .text-bold {
font-family: "d2-2782748831-font-bold";
}
@font-face {
font-family: d2-2782748831-font-bold;
src: url("data:application/font-woff;base64,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");
}
.d2-2782748831 .text-italic {
font-family: "d2-2782748831-font-italic";
}
@font-face {
font-family: d2-2782748831-font-italic;
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-2782748831 .fill-N1{fill:#0A0F25;}
.d2-2782748831 .fill-N2{fill:#676C7E;}
.d2-2782748831 .fill-N3{fill:#9499AB;}
.d2-2782748831 .fill-N4{fill:#CFD2DD;}
.d2-2782748831 .fill-N5{fill:#DEE1EB;}
.d2-2782748831 .fill-N6{fill:#EEF1F8;}
.d2-2782748831 .fill-N7{fill:#FFFFFF;}
.d2-2782748831 .fill-B1{fill:#0D32B2;}
.d2-2782748831 .fill-B2{fill:#0D32B2;}
.d2-2782748831 .fill-B3{fill:#E3E9FD;}
.d2-2782748831 .fill-B4{fill:#E3E9FD;}
.d2-2782748831 .fill-B5{fill:#EDF0FD;}
.d2-2782748831 .fill-B6{fill:#F7F8FE;}
.d2-2782748831 .fill-AA2{fill:#4A6FF3;}
.d2-2782748831 .fill-AA4{fill:#EDF0FD;}
.d2-2782748831 .fill-AA5{fill:#F7F8FE;}
.d2-2782748831 .fill-AB4{fill:#EDF0FD;}
.d2-2782748831 .fill-AB5{fill:#F7F8FE;}
.d2-2782748831 .stroke-N1{stroke:#0A0F25;}
.d2-2782748831 .stroke-N2{stroke:#676C7E;}
.d2-2782748831 .stroke-N3{stroke:#9499AB;}
.d2-2782748831 .stroke-N4{stroke:#CFD2DD;}
.d2-2782748831 .stroke-N5{stroke:#DEE1EB;}
.d2-2782748831 .stroke-N6{stroke:#EEF1F8;}
.d2-2782748831 .stroke-N7{stroke:#FFFFFF;}
.d2-2782748831 .stroke-B1{stroke:#0D32B2;}
.d2-2782748831 .stroke-B2{stroke:#0D32B2;}
.d2-2782748831 .stroke-B3{stroke:#E3E9FD;}
.d2-2782748831 .stroke-B4{stroke:#E3E9FD;}
.d2-2782748831 .stroke-B5{stroke:#EDF0FD;}
.d2-2782748831 .stroke-B6{stroke:#F7F8FE;}
.d2-2782748831 .stroke-AA2{stroke:#4A6FF3;}
.d2-2782748831 .stroke-AA4{stroke:#EDF0FD;}
.d2-2782748831 .stroke-AA5{stroke:#F7F8FE;}
.d2-2782748831 .stroke-AB4{stroke:#EDF0FD;}
.d2-2782748831 .stroke-AB5{stroke:#F7F8FE;}
.d2-2782748831 .background-color-N1{background-color:#0A0F25;}
.d2-2782748831 .background-color-N2{background-color:#676C7E;}
.d2-2782748831 .background-color-N3{background-color:#9499AB;}
.d2-2782748831 .background-color-N4{background-color:#CFD2DD;}
.d2-2782748831 .background-color-N5{background-color:#DEE1EB;}
.d2-2782748831 .background-color-N6{background-color:#EEF1F8;}
.d2-2782748831 .background-color-N7{background-color:#FFFFFF;}
.d2-2782748831 .background-color-B1{background-color:#0D32B2;}
.d2-2782748831 .background-color-B2{background-color:#0D32B2;}
.d2-2782748831 .background-color-B3{background-color:#E3E9FD;}
.d2-2782748831 .background-color-B4{background-color:#E3E9FD;}
.d2-2782748831 .background-color-B5{background-color:#EDF0FD;}
.d2-2782748831 .background-color-B6{background-color:#F7F8FE;}
.d2-2782748831 .background-color-AA2{background-color:#4A6FF3;}
.d2-2782748831 .background-color-AA4{background-color:#EDF0FD;}
.d2-2782748831 .background-color-AA5{background-color:#F7F8FE;}
.d2-2782748831 .background-color-AB4{background-color:#EDF0FD;}
.d2-2782748831 .background-color-AB5{background-color:#F7F8FE;}
.d2-2782748831 .color-N1{color:#0A0F25;}
.d2-2782748831 .color-N2{color:#676C7E;}
.d2-2782748831 .color-N3{color:#9499AB;}
.d2-2782748831 .color-N4{color:#CFD2DD;}
.d2-2782748831 .color-N5{color:#DEE1EB;}
.d2-2782748831 .color-N6{color:#EEF1F8;}
.d2-2782748831 .color-N7{color:#FFFFFF;}
.d2-2782748831 .color-B1{color:#0D32B2;}
.d2-2782748831 .color-B2{color:#0D32B2;}
.d2-2782748831 .color-B3{color:#E3E9FD;}
.d2-2782748831 .color-B4{color:#E3E9FD;}
.d2-2782748831 .color-B5{color:#EDF0FD;}
.d2-2782748831 .color-B6{color:#F7F8FE;}
.d2-2782748831 .color-AA2{color:#4A6FF3;}
.d2-2782748831 .color-AA4{color:#EDF0FD;}
.d2-2782748831 .color-AA5{color:#F7F8FE;}
.d2-2782748831 .color-AB4{color:#EDF0FD;}
.d2-2782748831 .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="nostar" class="dragon_ball"><g class="shape" ><ellipse rx="25.000000" ry="25.000000" cx="38.000000" cy="37.000000" fill="orange" class="shape stroke-B1" style="stroke-width:0;" /></g></g><g id="1star" class="dragon_ball"><g class="shape" ><ellipse rx="25.000000" ry="25.000000" cx="38.000000" cy="248.000000" fill="orange" class="shape stroke-B1" style="stroke-width:0;" /></g><text x="38.000000" y="253.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">*</text></g><g id="2star" class="dragon_ball"><g class="shape" ><ellipse rx="26.000000" ry="26.000000" cx="38.000000" cy="460.000000" fill="orange" class="shape stroke-B1" style="stroke-width:0;" /></g><text x="38.000000" y="465.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">**</text></g><g id="(nostar -&gt; 1star)[0]" class="path"><marker id="mk-3519660172" markerWidth="16.000000" markerHeight="20.000000" refX="10.000000" refY="10.000000" viewBox="0.000000 0.000000 16.000000 20.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon points="0.000000,0.000000 16.000000,10.000000 0.000000,20.000000" class="connection fill-B1" stroke-width="4" /> </marker><path d="M 38.000000 64.000000 L 38.000000 217.000000" fill="none" class="connection stroke-B1" style="stroke-width:4;" marker-end="url(#mk-3519660172)" mask="url(#d2-2782748831)" /><text x="38.000000" y="148.000000" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px">then</text></g><g id="(1star -&gt; 2star)[0]" class="path"><path d="M 38.000000 275.000000 L 38.000000 428.000000" fill="none" class="connection stroke-B1" style="stroke-width:4;" marker-end="url(#mk-3519660172)" mask="url(#d2-2782748831)" /><text x="38.000000" y="359.000000" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px">then</text></g><mask id="d2-2782748831" maskUnits="userSpaceOnUse" x="12" y="12" width="52" height="474">
<rect x="12" y="12" width="52" height="474" fill="white"></rect>
<rect x="23.000000" y="132.000000" width="30" height="21" fill="black"></rect>
<rect x="23.000000" y="343.000000" width="30" height="21" fill="black"></rect>
</mask></svg></svg>

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -828,15 +828,15 @@
"type": "rectangle", "type": "rectangle",
"pos": { "pos": {
"x": 0, "x": 0,
"y": 0 "y": 41
}, },
"width": 159, "width": 361,
"height": 66, "height": 125,
"opacity": 1, "opacity": 1,
"strokeDash": 0, "strokeDash": 0,
"strokeWidth": 2, "strokeWidth": 2,
"borderRadius": 0, "borderRadius": 0,
"fill": "B6", "fill": "B4",
"stroke": "B1", "stroke": "B1",
"shadow": false, "shadow": false,
"3d": false, "3d": false,
@ -851,6 +851,47 @@
"methods": null, "methods": null,
"columns": null, "columns": null,
"label": "find contractors", "label": "find contractors",
"fontSize": 28,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 187,
"labelHeight": 36,
"labelPosition": "OUTSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "find contractors.craigslist",
"type": "rectangle",
"pos": {
"x": 40,
"y": 70
},
"width": 110,
"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": "craigslist",
"fontSize": 16, "fontSize": 16,
"fontFamily": "DEFAULT", "fontFamily": "DEFAULT",
"language": "", "language": "",
@ -858,18 +899,59 @@
"italic": false, "italic": false,
"bold": true, "bold": true,
"underline": false, "underline": false,
"labelWidth": 114, "labelWidth": 65,
"labelHeight": 21, "labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER", "labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0, "zIndex": 0,
"level": 1 "level": 2
},
{
"id": "find contractors.facebook",
"type": "rectangle",
"pos": {
"x": 210,
"y": 70
},
"width": 111,
"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": "facebook",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 66,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
}, },
{ {
"id": "solicit quotes", "id": "solicit quotes",
"type": "rectangle", "type": "rectangle",
"pos": { "pos": {
"x": 10, "x": 196,
"y": 166 "y": 266
}, },
"width": 140, "width": 140,
"height": 66, "height": 66,
@ -934,20 +1016,20 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 79.5, "x": 265.5,
"y": 66
},
{
"x": 79.5,
"y": 106
},
{
"x": 79.5,
"y": 126
},
{
"x": 79.5,
"y": 166 "y": 166
},
{
"x": 265.5,
"y": 206
},
{
"x": 265.5,
"y": 226
},
{
"x": 265.5,
"y": 266
} }
], ],
"isCurve": true, "isCurve": true,
@ -1004,11 +1086,175 @@
"fontFamily": "SourceSansPro", "fontFamily": "SourceSansPro",
"shapes": [ "shapes": [
{ {
"id": "obtain quotes", "id": "find contractors",
"type": "rectangle", "type": "rectangle",
"pos": { "pos": {
"x": 0, "x": 0,
"y": 0 "y": 41
},
"width": 361,
"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": "find contractors",
"fontSize": 28,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 187,
"labelHeight": 36,
"labelPosition": "OUTSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "find contractors.craigslist",
"type": "rectangle",
"pos": {
"x": 40,
"y": 70
},
"width": 110,
"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": "craigslist",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 65,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "find contractors.facebook",
"type": "rectangle",
"pos": {
"x": 210,
"y": 70
},
"width": 111,
"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": "facebook",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 66,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "solicit quotes",
"type": "rectangle",
"pos": {
"x": 196,
"y": 266
},
"width": 140,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B6",
"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": "solicit quotes",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 95,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "obtain quotes",
"type": "rectangle",
"pos": {
"x": 401,
"y": 50
}, },
"width": 143, "width": 143,
"height": 66, "height": 66,
@ -1048,8 +1294,8 @@
"id": "negotiate", "id": "negotiate",
"type": "rectangle", "type": "rectangle",
"pos": { "pos": {
"x": 16, "x": 417,
"y": 166 "y": 266
}, },
"width": 112, "width": 112,
"height": 66, "height": 66,
@ -1087,6 +1333,55 @@
} }
], ],
"connections": [ "connections": [
{
"id": "(find contractors -> solicit quotes)[0]",
"src": "find contractors",
"srcArrow": "none",
"srcLabel": "",
"dst": "solicit quotes",
"dstArrow": "triangle",
"dstLabel": "",
"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": 265.5,
"y": 166
},
{
"x": 265.5,
"y": 206
},
{
"x": 265.5,
"y": 226
},
{
"x": 265.5,
"y": 266
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{ {
"id": "(obtain quotes -> negotiate)[0]", "id": "(obtain quotes -> negotiate)[0]",
"src": "obtain quotes", "src": "obtain quotes",
@ -1114,20 +1409,20 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 71.5, "x": 472.5,
"y": 66 "y": 116
}, },
{ {
"x": 71.5, "x": 472.5,
"y": 106 "y": 156
}, },
{ {
"x": 71.5, "x": 472.5,
"y": 126 "y": 226
}, },
{ {
"x": 71.5, "x": 472.5,
"y": 166 "y": 266
} }
], ],
"isCurve": true, "isCurve": true,
@ -1183,12 +1478,217 @@
"isFolderOnly": false, "isFolderOnly": false,
"fontFamily": "SourceSansPro", "fontFamily": "SourceSansPro",
"shapes": [ "shapes": [
{
"id": "find contractors",
"type": "rectangle",
"pos": {
"x": 0,
"y": 41
},
"width": 361,
"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": "find contractors",
"fontSize": 28,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 187,
"labelHeight": 36,
"labelPosition": "OUTSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "find contractors.craigslist",
"type": "rectangle",
"pos": {
"x": 40,
"y": 70
},
"width": 110,
"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": "craigslist",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 65,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "find contractors.facebook",
"type": "rectangle",
"pos": {
"x": 210,
"y": 70
},
"width": 111,
"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": "facebook",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 66,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "solicit quotes",
"type": "rectangle",
"pos": {
"x": 196,
"y": 266
},
"width": 140,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B6",
"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": "solicit quotes",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 95,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "obtain quotes",
"type": "rectangle",
"pos": {
"x": 401,
"y": 50
},
"width": 143,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B6",
"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": "obtain quotes",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 98,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{ {
"id": "negotiate", "id": "negotiate",
"type": "rectangle", "type": "rectangle",
"pos": { "pos": {
"x": 28, "x": 417,
"y": 0 "y": 266
}, },
"width": 112, "width": 112,
"height": 66, "height": 66,
@ -1228,8 +1728,8 @@
"id": "book the best bid", "id": "book the best bid",
"type": "rectangle", "type": "rectangle",
"pos": { "pos": {
"x": 0, "x": 389,
"y": 166 "y": 432
}, },
"width": 167, "width": 167,
"height": 66, "height": 66,
@ -1267,6 +1767,104 @@
} }
], ],
"connections": [ "connections": [
{
"id": "(find contractors -> solicit quotes)[0]",
"src": "find contractors",
"srcArrow": "none",
"srcLabel": "",
"dst": "solicit quotes",
"dstArrow": "triangle",
"dstLabel": "",
"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": 265.5,
"y": 166
},
{
"x": 265.5,
"y": 206
},
{
"x": 265.5,
"y": 226
},
{
"x": 265.5,
"y": 266
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(obtain quotes -> negotiate)[0]",
"src": "obtain quotes",
"srcArrow": "none",
"srcLabel": "",
"dst": "negotiate",
"dstArrow": "triangle",
"dstLabel": "",
"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": 472.5,
"y": 116
},
{
"x": 472.5,
"y": 156
},
{
"x": 472.5,
"y": 226
},
{
"x": 472.5,
"y": 266
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{ {
"id": "(negotiate -> book the best bid)[0]", "id": "(negotiate -> book the best bid)[0]",
"src": "negotiate", "src": "negotiate",
@ -1294,20 +1892,20 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 83.5, "x": 472.5,
"y": 66 "y": 332
}, },
{ {
"x": 83.5, "x": 472.5,
"y": 106 "y": 372
}, },
{ {
"x": 83.5, "x": 472.5,
"y": 126 "y": 392
}, },
{ {
"x": 83.5, "x": 472.5,
"y": 166 "y": 432
} }
], ],
"isCurve": true, "isCurve": true,

View file

@ -1,9 +1,9 @@
<?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.3.0-HEAD" preserveAspectRatio="xMinYMin meet" viewBox="0 0 394 68"><svg id="d2-svg" class="d2-3917036827" width="394" height="68" viewBox="-1 -1 394 68"><rect x="-1.000000" y="-1.000000" width="394.000000" height="68.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><style type="text/css"><![CDATA[ <?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.3.0-HEAD" preserveAspectRatio="xMinYMin meet" viewBox="0 0 394 68"><svg id="d2-svg" class="d2-1606881621" width="394" height="68" viewBox="-1 -1 394 68"><rect x="-1.000000" y="-1.000000" width="394.000000" height="68.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><style type="text/css"><![CDATA[
.d2-3917036827 .text-bold { .d2-1606881621 .text-bold {
font-family: "d2-3917036827-font-bold"; font-family: "d2-1606881621-font-bold";
} }
@font-face { @font-face {
font-family: d2-3917036827-font-bold; font-family: d2-1606881621-font-bold;
src: url("data:application/font-woff;base64,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"); src: url("data:application/font-woff;base64,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");
}]]></style><style type="text/css"><![CDATA[.shape { }]]></style><style type="text/css"><![CDATA[.shape {
shape-rendering: geometricPrecision; shape-rendering: geometricPrecision;
@ -18,78 +18,78 @@
opacity: 0.5; opacity: 0.5;
} }
.d2-3917036827 .fill-N1{fill:#0A0F25;} .d2-1606881621 .fill-N1{fill:#0A0F25;}
.d2-3917036827 .fill-N2{fill:#676C7E;} .d2-1606881621 .fill-N2{fill:#676C7E;}
.d2-3917036827 .fill-N3{fill:#9499AB;} .d2-1606881621 .fill-N3{fill:#9499AB;}
.d2-3917036827 .fill-N4{fill:#CFD2DD;} .d2-1606881621 .fill-N4{fill:#CFD2DD;}
.d2-3917036827 .fill-N5{fill:#DEE1EB;} .d2-1606881621 .fill-N5{fill:#DEE1EB;}
.d2-3917036827 .fill-N6{fill:#EEF1F8;} .d2-1606881621 .fill-N6{fill:#EEF1F8;}
.d2-3917036827 .fill-N7{fill:#FFFFFF;} .d2-1606881621 .fill-N7{fill:#FFFFFF;}
.d2-3917036827 .fill-B1{fill:#0D32B2;} .d2-1606881621 .fill-B1{fill:#0D32B2;}
.d2-3917036827 .fill-B2{fill:#0D32B2;} .d2-1606881621 .fill-B2{fill:#0D32B2;}
.d2-3917036827 .fill-B3{fill:#E3E9FD;} .d2-1606881621 .fill-B3{fill:#E3E9FD;}
.d2-3917036827 .fill-B4{fill:#E3E9FD;} .d2-1606881621 .fill-B4{fill:#E3E9FD;}
.d2-3917036827 .fill-B5{fill:#EDF0FD;} .d2-1606881621 .fill-B5{fill:#EDF0FD;}
.d2-3917036827 .fill-B6{fill:#F7F8FE;} .d2-1606881621 .fill-B6{fill:#F7F8FE;}
.d2-3917036827 .fill-AA2{fill:#4A6FF3;} .d2-1606881621 .fill-AA2{fill:#4A6FF3;}
.d2-3917036827 .fill-AA4{fill:#EDF0FD;} .d2-1606881621 .fill-AA4{fill:#EDF0FD;}
.d2-3917036827 .fill-AA5{fill:#F7F8FE;} .d2-1606881621 .fill-AA5{fill:#F7F8FE;}
.d2-3917036827 .fill-AB4{fill:#EDF0FD;} .d2-1606881621 .fill-AB4{fill:#EDF0FD;}
.d2-3917036827 .fill-AB5{fill:#F7F8FE;} .d2-1606881621 .fill-AB5{fill:#F7F8FE;}
.d2-3917036827 .stroke-N1{stroke:#0A0F25;} .d2-1606881621 .stroke-N1{stroke:#0A0F25;}
.d2-3917036827 .stroke-N2{stroke:#676C7E;} .d2-1606881621 .stroke-N2{stroke:#676C7E;}
.d2-3917036827 .stroke-N3{stroke:#9499AB;} .d2-1606881621 .stroke-N3{stroke:#9499AB;}
.d2-3917036827 .stroke-N4{stroke:#CFD2DD;} .d2-1606881621 .stroke-N4{stroke:#CFD2DD;}
.d2-3917036827 .stroke-N5{stroke:#DEE1EB;} .d2-1606881621 .stroke-N5{stroke:#DEE1EB;}
.d2-3917036827 .stroke-N6{stroke:#EEF1F8;} .d2-1606881621 .stroke-N6{stroke:#EEF1F8;}
.d2-3917036827 .stroke-N7{stroke:#FFFFFF;} .d2-1606881621 .stroke-N7{stroke:#FFFFFF;}
.d2-3917036827 .stroke-B1{stroke:#0D32B2;} .d2-1606881621 .stroke-B1{stroke:#0D32B2;}
.d2-3917036827 .stroke-B2{stroke:#0D32B2;} .d2-1606881621 .stroke-B2{stroke:#0D32B2;}
.d2-3917036827 .stroke-B3{stroke:#E3E9FD;} .d2-1606881621 .stroke-B3{stroke:#E3E9FD;}
.d2-3917036827 .stroke-B4{stroke:#E3E9FD;} .d2-1606881621 .stroke-B4{stroke:#E3E9FD;}
.d2-3917036827 .stroke-B5{stroke:#EDF0FD;} .d2-1606881621 .stroke-B5{stroke:#EDF0FD;}
.d2-3917036827 .stroke-B6{stroke:#F7F8FE;} .d2-1606881621 .stroke-B6{stroke:#F7F8FE;}
.d2-3917036827 .stroke-AA2{stroke:#4A6FF3;} .d2-1606881621 .stroke-AA2{stroke:#4A6FF3;}
.d2-3917036827 .stroke-AA4{stroke:#EDF0FD;} .d2-1606881621 .stroke-AA4{stroke:#EDF0FD;}
.d2-3917036827 .stroke-AA5{stroke:#F7F8FE;} .d2-1606881621 .stroke-AA5{stroke:#F7F8FE;}
.d2-3917036827 .stroke-AB4{stroke:#EDF0FD;} .d2-1606881621 .stroke-AB4{stroke:#EDF0FD;}
.d2-3917036827 .stroke-AB5{stroke:#F7F8FE;} .d2-1606881621 .stroke-AB5{stroke:#F7F8FE;}
.d2-3917036827 .background-color-N1{background-color:#0A0F25;} .d2-1606881621 .background-color-N1{background-color:#0A0F25;}
.d2-3917036827 .background-color-N2{background-color:#676C7E;} .d2-1606881621 .background-color-N2{background-color:#676C7E;}
.d2-3917036827 .background-color-N3{background-color:#9499AB;} .d2-1606881621 .background-color-N3{background-color:#9499AB;}
.d2-3917036827 .background-color-N4{background-color:#CFD2DD;} .d2-1606881621 .background-color-N4{background-color:#CFD2DD;}
.d2-3917036827 .background-color-N5{background-color:#DEE1EB;} .d2-1606881621 .background-color-N5{background-color:#DEE1EB;}
.d2-3917036827 .background-color-N6{background-color:#EEF1F8;} .d2-1606881621 .background-color-N6{background-color:#EEF1F8;}
.d2-3917036827 .background-color-N7{background-color:#FFFFFF;} .d2-1606881621 .background-color-N7{background-color:#FFFFFF;}
.d2-3917036827 .background-color-B1{background-color:#0D32B2;} .d2-1606881621 .background-color-B1{background-color:#0D32B2;}
.d2-3917036827 .background-color-B2{background-color:#0D32B2;} .d2-1606881621 .background-color-B2{background-color:#0D32B2;}
.d2-3917036827 .background-color-B3{background-color:#E3E9FD;} .d2-1606881621 .background-color-B3{background-color:#E3E9FD;}
.d2-3917036827 .background-color-B4{background-color:#E3E9FD;} .d2-1606881621 .background-color-B4{background-color:#E3E9FD;}
.d2-3917036827 .background-color-B5{background-color:#EDF0FD;} .d2-1606881621 .background-color-B5{background-color:#EDF0FD;}
.d2-3917036827 .background-color-B6{background-color:#F7F8FE;} .d2-1606881621 .background-color-B6{background-color:#F7F8FE;}
.d2-3917036827 .background-color-AA2{background-color:#4A6FF3;} .d2-1606881621 .background-color-AA2{background-color:#4A6FF3;}
.d2-3917036827 .background-color-AA4{background-color:#EDF0FD;} .d2-1606881621 .background-color-AA4{background-color:#EDF0FD;}
.d2-3917036827 .background-color-AA5{background-color:#F7F8FE;} .d2-1606881621 .background-color-AA5{background-color:#F7F8FE;}
.d2-3917036827 .background-color-AB4{background-color:#EDF0FD;} .d2-1606881621 .background-color-AB4{background-color:#EDF0FD;}
.d2-3917036827 .background-color-AB5{background-color:#F7F8FE;} .d2-1606881621 .background-color-AB5{background-color:#F7F8FE;}
.d2-3917036827 .color-N1{color:#0A0F25;} .d2-1606881621 .color-N1{color:#0A0F25;}
.d2-3917036827 .color-N2{color:#676C7E;} .d2-1606881621 .color-N2{color:#676C7E;}
.d2-3917036827 .color-N3{color:#9499AB;} .d2-1606881621 .color-N3{color:#9499AB;}
.d2-3917036827 .color-N4{color:#CFD2DD;} .d2-1606881621 .color-N4{color:#CFD2DD;}
.d2-3917036827 .color-N5{color:#DEE1EB;} .d2-1606881621 .color-N5{color:#DEE1EB;}
.d2-3917036827 .color-N6{color:#EEF1F8;} .d2-1606881621 .color-N6{color:#EEF1F8;}
.d2-3917036827 .color-N7{color:#FFFFFF;} .d2-1606881621 .color-N7{color:#FFFFFF;}
.d2-3917036827 .color-B1{color:#0D32B2;} .d2-1606881621 .color-B1{color:#0D32B2;}
.d2-3917036827 .color-B2{color:#0D32B2;} .d2-1606881621 .color-B2{color:#0D32B2;}
.d2-3917036827 .color-B3{color:#E3E9FD;} .d2-1606881621 .color-B3{color:#E3E9FD;}
.d2-3917036827 .color-B4{color:#E3E9FD;} .d2-1606881621 .color-B4{color:#E3E9FD;}
.d2-3917036827 .color-B5{color:#EDF0FD;} .d2-1606881621 .color-B5{color:#EDF0FD;}
.d2-3917036827 .color-B6{color:#F7F8FE;} .d2-1606881621 .color-B6{color:#F7F8FE;}
.d2-3917036827 .color-AA2{color:#4A6FF3;} .d2-1606881621 .color-AA2{color:#4A6FF3;}
.d2-3917036827 .color-AA4{color:#EDF0FD;} .d2-1606881621 .color-AA4{color:#EDF0FD;}
.d2-3917036827 .color-AA5{color:#F7F8FE;} .d2-1606881621 .color-AA5{color:#F7F8FE;}
.d2-3917036827 .color-AB4{color:#EDF0FD;} .d2-1606881621 .color-AB4{color:#EDF0FD;}
.d2-3917036827 .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="window"><g class="shape" ><rect x="0.000000" y="0.000000" width="103.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /><rect x="5.000000" y="5.000000" width="93.000000" height="56.000000" fill="transparent" class=" stroke-B1" style="stroke-width:2;" /></g><text x="51.500000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">window</text></g><g id="roof"><g class="shape" ><rect x="163.000000" y="0.000000" width="75.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="200.500000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">roof</text></g><g id="garage"><g class="shape" ><rect x="298.000000" y="0.000000" width="94.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="345.000000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">garage</text></g><mask id="d2-3917036827" maskUnits="userSpaceOnUse" x="-1" y="-1" width="394" height="68"> .d2-1606881621 .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="window"><g class="shape" ><rect x="0.000000" y="0.000000" width="103.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /><rect x="5.000000" y="5.000000" width="93.000000" height="56.000000" fill="transparent" class=" stroke-B1" style="stroke-width:2;" /></g><text x="51.500000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">window</text></g><g id="roof"><g class="shape" ><rect x="163.000000" y="0.000000" width="75.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="200.500000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">roof</text></g><g id="garage"><g class="shape" ><rect x="298.000000" y="0.000000" width="94.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="345.000000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">garage</text></g><mask id="d2-1606881621" maskUnits="userSpaceOnUse" x="-1" y="-1" width="394" height="68">
<rect x="-1" y="-1" width="394" height="68" fill="white"></rect> <rect x="-1" y="-1" width="394" height="68" fill="white"></rect>
</mask></svg></svg> </mask></svg></svg>

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -830,13 +830,13 @@
"x": 12, "x": 12,
"y": 12 "y": 12
}, },
"width": 159, "width": 341,
"height": 66, "height": 166,
"opacity": 1, "opacity": 1,
"strokeDash": 0, "strokeDash": 0,
"strokeWidth": 2, "strokeWidth": 2,
"borderRadius": 0, "borderRadius": 0,
"fill": "B6", "fill": "B4",
"stroke": "B1", "stroke": "B1",
"shadow": false, "shadow": false,
"3d": false, "3d": false,
@ -851,6 +851,47 @@
"methods": null, "methods": null,
"columns": null, "columns": null,
"label": "find contractors", "label": "find contractors",
"fontSize": 28,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 187,
"labelHeight": 36,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "find contractors.craigslist",
"type": "rectangle",
"pos": {
"x": 62,
"y": 62
},
"width": 110,
"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": "craigslist",
"fontSize": 16, "fontSize": 16,
"fontFamily": "DEFAULT", "fontFamily": "DEFAULT",
"language": "", "language": "",
@ -858,18 +899,59 @@
"italic": false, "italic": false,
"bold": true, "bold": true,
"underline": false, "underline": false,
"labelWidth": 114, "labelWidth": 65,
"labelHeight": 21, "labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER", "labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0, "zIndex": 0,
"level": 1 "level": 2
},
{
"id": "find contractors.facebook",
"type": "rectangle",
"pos": {
"x": 192,
"y": 62
},
"width": 111,
"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": "facebook",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 66,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
}, },
{ {
"id": "solicit quotes", "id": "solicit quotes",
"type": "rectangle", "type": "rectangle",
"pos": { "pos": {
"x": 21, "x": 112,
"y": 148 "y": 248
}, },
"width": 140, "width": 140,
"height": 66, "height": 66,
@ -934,12 +1016,12 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 91.5, "x": 182.5,
"y": 78 "y": 178
}, },
{ {
"x": 91.5, "x": 182.5,
"y": 148 "y": 248
} }
], ],
"animated": false, "animated": false,
@ -995,12 +1077,176 @@
"fontFamily": "SourceSansPro", "fontFamily": "SourceSansPro",
"shapes": [ "shapes": [
{ {
"id": "obtain quotes", "id": "find contractors",
"type": "rectangle", "type": "rectangle",
"pos": { "pos": {
"x": 12, "x": 12,
"y": 12 "y": 12
}, },
"width": 341,
"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": "find contractors",
"fontSize": 28,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 187,
"labelHeight": 36,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "find contractors.craigslist",
"type": "rectangle",
"pos": {
"x": 62,
"y": 62
},
"width": 110,
"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": "craigslist",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 65,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "find contractors.facebook",
"type": "rectangle",
"pos": {
"x": 192,
"y": 62
},
"width": 111,
"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": "facebook",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 66,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "solicit quotes",
"type": "rectangle",
"pos": {
"x": 112,
"y": 248
},
"width": 140,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B6",
"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": "solicit quotes",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 95,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "obtain quotes",
"type": "rectangle",
"pos": {
"x": 373,
"y": 112
},
"width": 143, "width": 143,
"height": 66, "height": 66,
"opacity": 1, "opacity": 1,
@ -1039,8 +1285,8 @@
"id": "negotiate", "id": "negotiate",
"type": "rectangle", "type": "rectangle",
"pos": { "pos": {
"x": 27, "x": 388,
"y": 148 "y": 248
}, },
"width": 112, "width": 112,
"height": 66, "height": 66,
@ -1078,6 +1324,46 @@
} }
], ],
"connections": [ "connections": [
{
"id": "(find contractors -> solicit quotes)[0]",
"src": "find contractors",
"srcArrow": "none",
"srcLabel": "",
"dst": "solicit quotes",
"dstArrow": "triangle",
"dstLabel": "",
"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": 182.5,
"y": 178
},
{
"x": 182.5,
"y": 248
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{ {
"id": "(obtain quotes -> negotiate)[0]", "id": "(obtain quotes -> negotiate)[0]",
"src": "obtain quotes", "src": "obtain quotes",
@ -1105,12 +1391,12 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 83.5, "x": 444.5,
"y": 78 "y": 178
}, },
{ {
"x": 83.5, "x": 444.5,
"y": 148 "y": 248
} }
], ],
"animated": false, "animated": false,
@ -1165,12 +1451,217 @@
"isFolderOnly": false, "isFolderOnly": false,
"fontFamily": "SourceSansPro", "fontFamily": "SourceSansPro",
"shapes": [ "shapes": [
{
"id": "find contractors",
"type": "rectangle",
"pos": {
"x": 12,
"y": 12
},
"width": 341,
"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": "find contractors",
"fontSize": 28,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 187,
"labelHeight": 36,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "find contractors.craigslist",
"type": "rectangle",
"pos": {
"x": 62,
"y": 62
},
"width": 110,
"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": "craigslist",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 65,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "find contractors.facebook",
"type": "rectangle",
"pos": {
"x": 192,
"y": 62
},
"width": 111,
"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": "facebook",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 66,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "solicit quotes",
"type": "rectangle",
"pos": {
"x": 112,
"y": 248
},
"width": 140,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B6",
"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": "solicit quotes",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 95,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "obtain quotes",
"type": "rectangle",
"pos": {
"x": 373,
"y": 112
},
"width": 143,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B6",
"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": "obtain quotes",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 98,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{ {
"id": "negotiate", "id": "negotiate",
"type": "rectangle", "type": "rectangle",
"pos": { "pos": {
"x": 39, "x": 388,
"y": 12 "y": 248
}, },
"width": 112, "width": 112,
"height": 66, "height": 66,
@ -1210,8 +1701,8 @@
"id": "book the best bid", "id": "book the best bid",
"type": "rectangle", "type": "rectangle",
"pos": { "pos": {
"x": 12, "x": 361,
"y": 148 "y": 384
}, },
"width": 167, "width": 167,
"height": 66, "height": 66,
@ -1249,6 +1740,86 @@
} }
], ],
"connections": [ "connections": [
{
"id": "(find contractors -> solicit quotes)[0]",
"src": "find contractors",
"srcArrow": "none",
"srcLabel": "",
"dst": "solicit quotes",
"dstArrow": "triangle",
"dstLabel": "",
"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": 182.5,
"y": 178
},
{
"x": 182.5,
"y": 248
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(obtain quotes -> negotiate)[0]",
"src": "obtain quotes",
"srcArrow": "none",
"srcLabel": "",
"dst": "negotiate",
"dstArrow": "triangle",
"dstLabel": "",
"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": 444.5,
"y": 178
},
{
"x": 444.5,
"y": 248
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{ {
"id": "(negotiate -> book the best bid)[0]", "id": "(negotiate -> book the best bid)[0]",
"src": "negotiate", "src": "negotiate",
@ -1276,12 +1847,12 @@
"labelPercentage": 0, "labelPercentage": 0,
"route": [ "route": [
{ {
"x": 95.5, "x": 444.5,
"y": 78 "y": 314
}, },
{ {
"x": 95.5, "x": 444.5,
"y": 148 "y": 384
} }
], ],
"animated": false, "animated": false,

View file

@ -1,9 +1,9 @@
<?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.3.0-HEAD" preserveAspectRatio="xMinYMin meet" viewBox="0 0 314 68"><svg id="d2-svg" class="d2-2455851432" width="314" height="68" viewBox="11 11 314 68"><rect x="11.000000" y="11.000000" width="314.000000" height="68.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><style type="text/css"><![CDATA[ <?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.3.0-HEAD" preserveAspectRatio="xMinYMin meet" viewBox="0 0 314 68"><svg id="d2-svg" class="d2-1428720329" width="314" height="68" viewBox="11 11 314 68"><rect x="11.000000" y="11.000000" width="314.000000" height="68.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><style type="text/css"><![CDATA[
.d2-2455851432 .text-bold { .d2-1428720329 .text-bold {
font-family: "d2-2455851432-font-bold"; font-family: "d2-1428720329-font-bold";
} }
@font-face { @font-face {
font-family: d2-2455851432-font-bold; font-family: d2-1428720329-font-bold;
src: url("data:application/font-woff;base64,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"); src: url("data:application/font-woff;base64,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");
}]]></style><style type="text/css"><![CDATA[.shape { }]]></style><style type="text/css"><![CDATA[.shape {
shape-rendering: geometricPrecision; shape-rendering: geometricPrecision;
@ -18,78 +18,78 @@
opacity: 0.5; opacity: 0.5;
} }
.d2-2455851432 .fill-N1{fill:#0A0F25;} .d2-1428720329 .fill-N1{fill:#0A0F25;}
.d2-2455851432 .fill-N2{fill:#676C7E;} .d2-1428720329 .fill-N2{fill:#676C7E;}
.d2-2455851432 .fill-N3{fill:#9499AB;} .d2-1428720329 .fill-N3{fill:#9499AB;}
.d2-2455851432 .fill-N4{fill:#CFD2DD;} .d2-1428720329 .fill-N4{fill:#CFD2DD;}
.d2-2455851432 .fill-N5{fill:#DEE1EB;} .d2-1428720329 .fill-N5{fill:#DEE1EB;}
.d2-2455851432 .fill-N6{fill:#EEF1F8;} .d2-1428720329 .fill-N6{fill:#EEF1F8;}
.d2-2455851432 .fill-N7{fill:#FFFFFF;} .d2-1428720329 .fill-N7{fill:#FFFFFF;}
.d2-2455851432 .fill-B1{fill:#0D32B2;} .d2-1428720329 .fill-B1{fill:#0D32B2;}
.d2-2455851432 .fill-B2{fill:#0D32B2;} .d2-1428720329 .fill-B2{fill:#0D32B2;}
.d2-2455851432 .fill-B3{fill:#E3E9FD;} .d2-1428720329 .fill-B3{fill:#E3E9FD;}
.d2-2455851432 .fill-B4{fill:#E3E9FD;} .d2-1428720329 .fill-B4{fill:#E3E9FD;}
.d2-2455851432 .fill-B5{fill:#EDF0FD;} .d2-1428720329 .fill-B5{fill:#EDF0FD;}
.d2-2455851432 .fill-B6{fill:#F7F8FE;} .d2-1428720329 .fill-B6{fill:#F7F8FE;}
.d2-2455851432 .fill-AA2{fill:#4A6FF3;} .d2-1428720329 .fill-AA2{fill:#4A6FF3;}
.d2-2455851432 .fill-AA4{fill:#EDF0FD;} .d2-1428720329 .fill-AA4{fill:#EDF0FD;}
.d2-2455851432 .fill-AA5{fill:#F7F8FE;} .d2-1428720329 .fill-AA5{fill:#F7F8FE;}
.d2-2455851432 .fill-AB4{fill:#EDF0FD;} .d2-1428720329 .fill-AB4{fill:#EDF0FD;}
.d2-2455851432 .fill-AB5{fill:#F7F8FE;} .d2-1428720329 .fill-AB5{fill:#F7F8FE;}
.d2-2455851432 .stroke-N1{stroke:#0A0F25;} .d2-1428720329 .stroke-N1{stroke:#0A0F25;}
.d2-2455851432 .stroke-N2{stroke:#676C7E;} .d2-1428720329 .stroke-N2{stroke:#676C7E;}
.d2-2455851432 .stroke-N3{stroke:#9499AB;} .d2-1428720329 .stroke-N3{stroke:#9499AB;}
.d2-2455851432 .stroke-N4{stroke:#CFD2DD;} .d2-1428720329 .stroke-N4{stroke:#CFD2DD;}
.d2-2455851432 .stroke-N5{stroke:#DEE1EB;} .d2-1428720329 .stroke-N5{stroke:#DEE1EB;}
.d2-2455851432 .stroke-N6{stroke:#EEF1F8;} .d2-1428720329 .stroke-N6{stroke:#EEF1F8;}
.d2-2455851432 .stroke-N7{stroke:#FFFFFF;} .d2-1428720329 .stroke-N7{stroke:#FFFFFF;}
.d2-2455851432 .stroke-B1{stroke:#0D32B2;} .d2-1428720329 .stroke-B1{stroke:#0D32B2;}
.d2-2455851432 .stroke-B2{stroke:#0D32B2;} .d2-1428720329 .stroke-B2{stroke:#0D32B2;}
.d2-2455851432 .stroke-B3{stroke:#E3E9FD;} .d2-1428720329 .stroke-B3{stroke:#E3E9FD;}
.d2-2455851432 .stroke-B4{stroke:#E3E9FD;} .d2-1428720329 .stroke-B4{stroke:#E3E9FD;}
.d2-2455851432 .stroke-B5{stroke:#EDF0FD;} .d2-1428720329 .stroke-B5{stroke:#EDF0FD;}
.d2-2455851432 .stroke-B6{stroke:#F7F8FE;} .d2-1428720329 .stroke-B6{stroke:#F7F8FE;}
.d2-2455851432 .stroke-AA2{stroke:#4A6FF3;} .d2-1428720329 .stroke-AA2{stroke:#4A6FF3;}
.d2-2455851432 .stroke-AA4{stroke:#EDF0FD;} .d2-1428720329 .stroke-AA4{stroke:#EDF0FD;}
.d2-2455851432 .stroke-AA5{stroke:#F7F8FE;} .d2-1428720329 .stroke-AA5{stroke:#F7F8FE;}
.d2-2455851432 .stroke-AB4{stroke:#EDF0FD;} .d2-1428720329 .stroke-AB4{stroke:#EDF0FD;}
.d2-2455851432 .stroke-AB5{stroke:#F7F8FE;} .d2-1428720329 .stroke-AB5{stroke:#F7F8FE;}
.d2-2455851432 .background-color-N1{background-color:#0A0F25;} .d2-1428720329 .background-color-N1{background-color:#0A0F25;}
.d2-2455851432 .background-color-N2{background-color:#676C7E;} .d2-1428720329 .background-color-N2{background-color:#676C7E;}
.d2-2455851432 .background-color-N3{background-color:#9499AB;} .d2-1428720329 .background-color-N3{background-color:#9499AB;}
.d2-2455851432 .background-color-N4{background-color:#CFD2DD;} .d2-1428720329 .background-color-N4{background-color:#CFD2DD;}
.d2-2455851432 .background-color-N5{background-color:#DEE1EB;} .d2-1428720329 .background-color-N5{background-color:#DEE1EB;}
.d2-2455851432 .background-color-N6{background-color:#EEF1F8;} .d2-1428720329 .background-color-N6{background-color:#EEF1F8;}
.d2-2455851432 .background-color-N7{background-color:#FFFFFF;} .d2-1428720329 .background-color-N7{background-color:#FFFFFF;}
.d2-2455851432 .background-color-B1{background-color:#0D32B2;} .d2-1428720329 .background-color-B1{background-color:#0D32B2;}
.d2-2455851432 .background-color-B2{background-color:#0D32B2;} .d2-1428720329 .background-color-B2{background-color:#0D32B2;}
.d2-2455851432 .background-color-B3{background-color:#E3E9FD;} .d2-1428720329 .background-color-B3{background-color:#E3E9FD;}
.d2-2455851432 .background-color-B4{background-color:#E3E9FD;} .d2-1428720329 .background-color-B4{background-color:#E3E9FD;}
.d2-2455851432 .background-color-B5{background-color:#EDF0FD;} .d2-1428720329 .background-color-B5{background-color:#EDF0FD;}
.d2-2455851432 .background-color-B6{background-color:#F7F8FE;} .d2-1428720329 .background-color-B6{background-color:#F7F8FE;}
.d2-2455851432 .background-color-AA2{background-color:#4A6FF3;} .d2-1428720329 .background-color-AA2{background-color:#4A6FF3;}
.d2-2455851432 .background-color-AA4{background-color:#EDF0FD;} .d2-1428720329 .background-color-AA4{background-color:#EDF0FD;}
.d2-2455851432 .background-color-AA5{background-color:#F7F8FE;} .d2-1428720329 .background-color-AA5{background-color:#F7F8FE;}
.d2-2455851432 .background-color-AB4{background-color:#EDF0FD;} .d2-1428720329 .background-color-AB4{background-color:#EDF0FD;}
.d2-2455851432 .background-color-AB5{background-color:#F7F8FE;} .d2-1428720329 .background-color-AB5{background-color:#F7F8FE;}
.d2-2455851432 .color-N1{color:#0A0F25;} .d2-1428720329 .color-N1{color:#0A0F25;}
.d2-2455851432 .color-N2{color:#676C7E;} .d2-1428720329 .color-N2{color:#676C7E;}
.d2-2455851432 .color-N3{color:#9499AB;} .d2-1428720329 .color-N3{color:#9499AB;}
.d2-2455851432 .color-N4{color:#CFD2DD;} .d2-1428720329 .color-N4{color:#CFD2DD;}
.d2-2455851432 .color-N5{color:#DEE1EB;} .d2-1428720329 .color-N5{color:#DEE1EB;}
.d2-2455851432 .color-N6{color:#EEF1F8;} .d2-1428720329 .color-N6{color:#EEF1F8;}
.d2-2455851432 .color-N7{color:#FFFFFF;} .d2-1428720329 .color-N7{color:#FFFFFF;}
.d2-2455851432 .color-B1{color:#0D32B2;} .d2-1428720329 .color-B1{color:#0D32B2;}
.d2-2455851432 .color-B2{color:#0D32B2;} .d2-1428720329 .color-B2{color:#0D32B2;}
.d2-2455851432 .color-B3{color:#E3E9FD;} .d2-1428720329 .color-B3{color:#E3E9FD;}
.d2-2455851432 .color-B4{color:#E3E9FD;} .d2-1428720329 .color-B4{color:#E3E9FD;}
.d2-2455851432 .color-B5{color:#EDF0FD;} .d2-1428720329 .color-B5{color:#EDF0FD;}
.d2-2455851432 .color-B6{color:#F7F8FE;} .d2-1428720329 .color-B6{color:#F7F8FE;}
.d2-2455851432 .color-AA2{color:#4A6FF3;} .d2-1428720329 .color-AA2{color:#4A6FF3;}
.d2-2455851432 .color-AA4{color:#EDF0FD;} .d2-1428720329 .color-AA4{color:#EDF0FD;}
.d2-2455851432 .color-AA5{color:#F7F8FE;} .d2-1428720329 .color-AA5{color:#F7F8FE;}
.d2-2455851432 .color-AB4{color:#EDF0FD;} .d2-1428720329 .color-AB4{color:#EDF0FD;}
.d2-2455851432 .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="window"><g class="shape" ><rect x="12.000000" y="12.000000" width="103.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /><rect x="17.000000" y="17.000000" width="93.000000" height="56.000000" fill="transparent" class=" stroke-B1" style="stroke-width:2;" /></g><text x="63.500000" y="50.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">window</text></g><g id="roof"><g class="shape" ><rect x="135.000000" y="12.000000" width="75.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="172.500000" y="50.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">roof</text></g><g id="garage"><g class="shape" ><rect x="230.000000" y="12.000000" width="94.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="277.000000" y="50.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">garage</text></g><mask id="d2-2455851432" maskUnits="userSpaceOnUse" x="11" y="11" width="314" height="68"> .d2-1428720329 .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="window"><g class="shape" ><rect x="12.000000" y="12.000000" width="103.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /><rect x="17.000000" y="17.000000" width="93.000000" height="56.000000" fill="transparent" class=" stroke-B1" style="stroke-width:2;" /></g><text x="63.500000" y="50.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">window</text></g><g id="roof"><g class="shape" ><rect x="135.000000" y="12.000000" width="75.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="172.500000" y="50.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">roof</text></g><g id="garage"><g class="shape" ><rect x="230.000000" y="12.000000" width="94.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="277.000000" y="50.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">garage</text></g><mask id="d2-1428720329" maskUnits="userSpaceOnUse" x="11" y="11" width="314" height="68">
<rect x="11" y="11" width="314" height="68" fill="white"></rect> <rect x="11" y="11" width="314" height="68" fill="white"></rect>
</mask></svg></svg> </mask></svg></svg>

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -122,7 +122,6 @@
"underline": false, "underline": false,
"labelWidth": 162, "labelWidth": 162,
"labelHeight": 21, "labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0, "zIndex": 0,
"level": 1 "level": 1
}, },
@ -163,7 +162,6 @@
"underline": false, "underline": false,
"labelWidth": 943, "labelWidth": 943,
"labelHeight": 131, "labelHeight": 131,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0, "zIndex": 0,
"level": 1 "level": 1
}, },
@ -286,7 +284,6 @@
"underline": false, "underline": false,
"labelWidth": 80, "labelWidth": 80,
"labelHeight": 21, "labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0, "zIndex": 0,
"level": 1 "level": 1
}, },
@ -327,7 +324,6 @@
"underline": false, "underline": false,
"labelWidth": 90, "labelWidth": 90,
"labelHeight": 21, "labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0, "zIndex": 0,
"level": 1 "level": 1
}, },
@ -368,7 +364,6 @@
"underline": false, "underline": false,
"labelWidth": 107, "labelWidth": 107,
"labelHeight": 21, "labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0, "zIndex": 0,
"level": 1 "level": 1
}, },
@ -409,7 +404,6 @@
"underline": false, "underline": false,
"labelWidth": 117, "labelWidth": 117,
"labelHeight": 21, "labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0, "zIndex": 0,
"level": 1 "level": 1
} }

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View file

@ -122,7 +122,6 @@
"underline": false, "underline": false,
"labelWidth": 162, "labelWidth": 162,
"labelHeight": 21, "labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0, "zIndex": 0,
"level": 1 "level": 1
}, },
@ -163,7 +162,6 @@
"underline": false, "underline": false,
"labelWidth": 943, "labelWidth": 943,
"labelHeight": 131, "labelHeight": 131,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0, "zIndex": 0,
"level": 1 "level": 1
}, },
@ -286,7 +284,6 @@
"underline": false, "underline": false,
"labelWidth": 80, "labelWidth": 80,
"labelHeight": 21, "labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0, "zIndex": 0,
"level": 1 "level": 1
}, },
@ -327,7 +324,6 @@
"underline": false, "underline": false,
"labelWidth": 90, "labelWidth": 90,
"labelHeight": 21, "labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0, "zIndex": 0,
"level": 1 "level": 1
}, },
@ -368,7 +364,6 @@
"underline": false, "underline": false,
"labelWidth": 107, "labelWidth": 107,
"labelHeight": 21, "labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0, "zIndex": 0,
"level": 1 "level": 1
}, },
@ -409,7 +404,6 @@
"underline": false, "underline": false,
"labelWidth": 117, "labelWidth": 117,
"labelHeight": 21, "labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0, "zIndex": 0,
"level": 1 "level": 1
} }

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View file

@ -245,7 +245,6 @@
"underline": false, "underline": false,
"labelWidth": 266, "labelWidth": 266,
"labelHeight": 51, "labelHeight": 51,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0, "zIndex": 0,
"level": 1 "level": 1
} }

Some files were not shown because too many files have changed in this diff Show more